From c0b843d57f36f7248f2421955efa6f51aa9701c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Corn=C3=A9=20Lukken?= <lukken@astron.nl>
Date: Thu, 28 Sep 2023 15:16:06 +0000
Subject: [PATCH] Backport sphinx documentation to binary wheel package

---
 .gitlab-ci.yml                                |  8 ++
 docker/ci-runner/Dockerfile                   |  3 +-
 {{cookiecutter.project_slug}}/.gitlab-ci.yml  | 12 +--
 .../docker/ci-runner/Dockerfile               |  2 +-
 {{cookiecutter.project_slug}}/docs/.gitkeep   |  0
 {{cookiecutter.project_slug}}/docs/cleanup.sh | 14 +++
 .../docs/requirements.txt                     |  5 +
 .../docs/source/conf.py                       | 93 +++++++++++++++++++
 .../docs/source/index.rst                     | 16 ++++
 .../docs/source/readme.rst                    |  2 +
 .../source/source_documentation/index.rst     |  7 ++
 .../docs/source/static/css/custom.css         | 14 +++
 {{cookiecutter.project_slug}}/pyproject.toml  |  2 +
 .../cool_module.py                            |  2 +-
 {{cookiecutter.project_slug}}/tox.ini         | 21 ++++-
 15 files changed, 188 insertions(+), 13 deletions(-)
 delete mode 100644 {{cookiecutter.project_slug}}/docs/.gitkeep
 create mode 100644 {{cookiecutter.project_slug}}/docs/cleanup.sh
 create mode 100644 {{cookiecutter.project_slug}}/docs/requirements.txt
 create mode 100644 {{cookiecutter.project_slug}}/docs/source/conf.py
 create mode 100644 {{cookiecutter.project_slug}}/docs/source/index.rst
 create mode 100644 {{cookiecutter.project_slug}}/docs/source/readme.rst
 create mode 100644 {{cookiecutter.project_slug}}/docs/source/source_documentation/index.rst
 create mode 100644 {{cookiecutter.project_slug}}/docs/source/static/css/custom.css

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0e31a2b..fd45bbf 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -28,6 +28,14 @@ default:
     - python -m pip install --upgrade pip
     - pip install --upgrade tox twine
 
+# Override artifact directories
+package_docs:
+  stage: package
+  artifacts:
+    expire_in: 1w
+    paths:
+      - my_awesome_app/docs/build/*
+
 # override package files before script
 package_files:
   before_script:
diff --git a/docker/ci-runner/Dockerfile b/docker/ci-runner/Dockerfile
index 937fe86..8b96217 100644
--- a/docker/ci-runner/Dockerfile
+++ b/docker/ci-runner/Dockerfile
@@ -1,4 +1,5 @@
 FROM python:3.11
 
 RUN python -m pip install --upgrade pip
-RUN pip install --upgrade cookiecutter tox twine
+RUN pip install --upgrade cookiecutter tox twine cibuildwheel==2.13.1 cookiecutter
+RUN curl -sSL https://get.docker.com/ | sh
diff --git a/{{cookiecutter.project_slug}}/.gitlab-ci.yml b/{{cookiecutter.project_slug}}/.gitlab-ci.yml
index 0632a23..1498ae3 100644
--- a/{{cookiecutter.project_slug}}/.gitlab-ci.yml
+++ b/{{cookiecutter.project_slug}}/.gitlab-ci.yml
@@ -79,26 +79,24 @@ run_unit_tests_coverage:
 
 package_files:
   stage: package
-  image: python:3.8
+#  image: python:3.8
   artifacts:
     expire_in: 1w
     paths:
       - dist/*
   script:
-    - curl -sSL https://get.docker.com/ | sh
-    - python -m pip install cibuildwheel==2.13.1 cookiecutter
+#    - curl -sSL https://get.docker.com/ | sh
+#    - python -m pip install cibuildwheel==2.13.1 cookiecutter
     - cibuildwheel --platform linux --output-dir dist
 
 package_docs:
   stage: package
-  allow_failure: true
   artifacts:
     expire_in: 1w
     paths:
-      - docs/* # update path to match the dest dir for documentation
+      - docs/build/*
   script:
-    - echo "build and collect docs"
-    - exit 1
+    - tox -e docs
 
 run_integration_tests:
   stage: integration
diff --git a/{{cookiecutter.project_slug}}/docker/ci-runner/Dockerfile b/{{cookiecutter.project_slug}}/docker/ci-runner/Dockerfile
index 01d5ee1..54b2c9c 100644
--- a/{{cookiecutter.project_slug}}/docker/ci-runner/Dockerfile
+++ b/{{cookiecutter.project_slug}}/docker/ci-runner/Dockerfile
@@ -1,4 +1,4 @@
 FROM python:3.11
 
 RUN python -m pip install --upgrade pip
-RUN pip install --upgrade tox twine
+RUN pip install --upgrade tox twine cibuildwheel==2.13.1
diff --git a/{{cookiecutter.project_slug}}/docs/.gitkeep b/{{cookiecutter.project_slug}}/docs/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/{{cookiecutter.project_slug}}/docs/cleanup.sh b/{{cookiecutter.project_slug}}/docs/cleanup.sh
new file mode 100644
index 0000000..aac4cef
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/docs/cleanup.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+FILE_DIR=$(dirname -- "$(readlink -f -- "${0}")")
+
+echo "Cleaning.. ${FILE_DIR}/source/source_documentation/*"
+
+for f in "${FILE_DIR}"/source/source_documentation/*
+do
+
+  case $f in
+    */index.rst) true;;
+    *) echo "Removing.. ${f}"; rm "${f}";;
+  esac
+done
diff --git a/{{cookiecutter.project_slug}}/docs/requirements.txt b/{{cookiecutter.project_slug}}/docs/requirements.txt
new file mode 100644
index 0000000..3c6e46c
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/docs/requirements.txt
@@ -0,0 +1,5 @@
+sphinx!=1.6.6,!=1.6.7,>=1.6.5 # BSD
+sphinx-rtd-theme>=0.4.3 #MIT
+sphinxcontrib-apidoc>=0.3.0 #BSD
+myst-parser>=2.0 # MIT
+docutils>=0.17 # BSD
diff --git a/{{cookiecutter.project_slug}}/docs/source/conf.py b/{{cookiecutter.project_slug}}/docs/source/conf.py
new file mode 100644
index 0000000..4f02a28
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/docs/source/conf.py
@@ -0,0 +1,93 @@
+#  Copyright (C) 2023 ASTRON (Netherlands Institute for Radio Astronomy)
+#  SPDX-License-Identifier: Apache-2.0
+
+import os
+
+from {{cookiecutter.project_slug}} import __version__
+
+# -- General configuration ----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = [
+    "sphinx.ext.autodoc",
+    "sphinx.ext.viewcode",
+    "sphinxcontrib.apidoc",
+    "sphinx_rtd_theme",
+    "myst_parser"
+]
+
+# Assumes tox is used to call sphinx-build
+project_root_directory = os.getcwd()
+
+apidoc_module_dir = "../../src"
+apidoc_output_dir = "source_documentation"
+apidoc_excluded_paths = []
+apidoc_separate_modules = True
+apidoc_toc_file = False
+# This should include private methods but does not work
+# https://github.com/sphinx-contrib/apidoc/issues/14
+apidoc_extra_args = ["--private"]
+
+# The suffix of source filenames.
+source_suffix = [".rst"]
+
+# The master toctree document.
+master_doc = "index"
+
+# General information about the project.
+project = "{{cookiecutter.project_name}}"
+copyright = "2023, ASTRON"
+
+# openstackdocstheme options
+repository_name = "{{cookiecutter.project_url}}"
+bug_project = "none"
+bug_tag = ""
+html_last_updated_fmt = "%Y-%m-%d %H:%M"
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = True
+
+version = __version__
+
+modindex_common_prefix = ["{{cookiecutter.project_slug}}."]
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+add_module_names = True
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = "sphinx"
+
+# -- Options for HTML output --------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+# html_theme_path = ["."]
+html_theme = "sphinx_rtd_theme"
+html_static_path = ["static"]
+html_css_files = [
+    "css/custom.css",
+]
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = "%sdoc" % project
+
+# Conf.py variables exported to sphinx rst files access using |NAME|
+variables_to_export = [
+    "project",
+    "copyright",
+    "version",
+]
+
+# Write to rst_epilog to export `variables_to_export` extract using `locals()`
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-rst_epilog
+frozen_locals = dict(locals())
+rst_epilog = "\n".join(
+    map(
+        lambda x: f".. |{x}| replace:: {frozen_locals[x]}",  # noqa: F821
+        variables_to_export,
+    )
+)
+# Pep is not able to determine that frozen_locals always exists so noqa
+del frozen_locals
diff --git a/{{cookiecutter.project_slug}}/docs/source/index.rst b/{{cookiecutter.project_slug}}/docs/source/index.rst
new file mode 100644
index 0000000..65932d2
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/docs/source/index.rst
@@ -0,0 +1,16 @@
+====================================================
+Welcome to the documentation of {{cookiecutter.project_name}}
+====================================================
+
+..
+    To define more variables see rst_epilog generation in conf.py
+
+Documentation for version: |version|
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   readme
+   source_documentation/index
diff --git a/{{cookiecutter.project_slug}}/docs/source/readme.rst b/{{cookiecutter.project_slug}}/docs/source/readme.rst
new file mode 100644
index 0000000..87c96de
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/docs/source/readme.rst
@@ -0,0 +1,2 @@
+.. include:: ../../README.md
+   :parser: myst_parser.sphinx_
diff --git a/{{cookiecutter.project_slug}}/docs/source/source_documentation/index.rst b/{{cookiecutter.project_slug}}/docs/source/source_documentation/index.rst
new file mode 100644
index 0000000..df6590f
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/docs/source/source_documentation/index.rst
@@ -0,0 +1,7 @@
+Source code documentation
+=========================
+
+.. toctree::
+   :maxdepth: 3
+
+   {{cookiecutter.project_slug}}
diff --git a/{{cookiecutter.project_slug}}/docs/source/static/css/custom.css b/{{cookiecutter.project_slug}}/docs/source/static/css/custom.css
new file mode 100644
index 0000000..3ea8a2f
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/docs/source/static/css/custom.css
@@ -0,0 +1,14 @@
+.orange { color: #c65d09; }
+
+.green { color: #5dc609; }
+
+.yellow { color: #c6c609; }
+
+.bolditalic {
+  font-weight: bold;
+  font-style: italic;
+}
+
+.rst-content code, .rst-content tt, code {
+  white-space: break-spaces;
+}
diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml
index 19e2b25..7409ddd 100644
--- a/{{cookiecutter.project_slug}}/pyproject.toml
+++ b/{{cookiecutter.project_slug}}/pyproject.toml
@@ -47,6 +47,8 @@ archs = ["AMD64", "x86"]
 [tool.pylint]
 ignore = "_version.py"
 
+# This does nothing until the issue below is resolved:
+# https://github.com/PyCQA/flake8/issues/234
 [tool.flake8]
 max-line-length = 88
 extend-ignore = ["E203"]
diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/cool_module.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/cool_module.py
index bd9416c..b71bcac 100644
--- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/cool_module.py
+++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/cool_module.py
@@ -3,4 +3,4 @@
 
 def greeter():
     """Prints a nice message"""
-    print("Hello World!")
+    print("Hello World!, test line over 80 but not 88 characters on a single line")
diff --git a/{{cookiecutter.project_slug}}/tox.ini b/{{cookiecutter.project_slug}}/tox.ini
index 4351731..efe9166 100644
--- a/{{cookiecutter.project_slug}}/tox.ini
+++ b/{{cookiecutter.project_slug}}/tox.ini
@@ -31,15 +31,30 @@ usedevelop = False
 envdir = {toxworkdir}/linting
 commands =
     pep8: {envpython} -m flake8 --version
-    pep8: {envpython} -m flake8 src tests
+    pep8: {envpython} -m flake8 --exclude=_version.py --max-line-length 88 --extend-ignore=E203 src tests
     black: {envpython} -m black --version
     black: {envpython} -m black --check --diff src tests
     pylint: {envpython} -m pylint --version
     pylint: {envpython} -m pylint src tests
-    format: {envpython} -m autopep8 -v -aa --in-place --recursive src
-    format: {envpython} -m autopep8 -v -aa --in-place --recursive tests
+    format: {envpython} -m autopep8 -v --max-line-length 88 -aa --in-place --recursive src
+    format: {envpython} -m autopep8 -v --max-line-length 88 -aa --in-place --recursive tests
     format: {envpython} -m black -v src tests
 
+[testenv:docs]
+allowlist_externals =
+    sh
+; unset LC_ALL / LANGUAGE from testenv, would fail sphinx otherwise
+setenv =
+    PYTHONWARNINGS=default::DeprecationWarning
+    DYNAMIC_VERSION_SOURCE={toxinidir}
+deps =
+    -r{toxinidir}/requirements.txt
+    -r{toxinidir}/docs/requirements.txt
+changedir = {toxinidir}
+commands =
+    sh docs/cleanup.sh
+    sphinx-build -b html docs/source docs/build/html
+
 [testenv:{build-local,build-ci-linux}]
 deps =
     -r{toxinidir}/tests/requirements.txt
-- 
GitLab