Skip to content

Commit

Permalink
docs: sphinx customisation (#1165)
Browse files Browse the repository at this point in the history
Customisation for sphinx starter pack.
  • Loading branch information
IronCore864 authored Mar 28, 2024
1 parent 63a0c89 commit 8bae12d
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

* Use "integrate with" rather than "relate to" (#1145)
* Updated code examples in the docstring of `ops.testing` from unittest to pytest style (#1157)
* Update Read the Docs Sphinx Furo theme to use Canonical's latest styling (#1163, #1164, #1165)

# 2.11.0 - 29 Feb 2024

Expand Down
27 changes: 27 additions & 0 deletions HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,33 @@ tox -e docs
open docs/_build/html/index.html
```

## How to Pull in Style Changes

The documentation uses Canonical styling which is customised on top of the [Furo Sphinx theme](https://github.com/pradyunsg/furo). The easiest way to pull in Canonical style changes is by using the Canonical documentation starter pack, see [docs](https://canonical-starter-pack.readthedocs-hosted.com/) and [repository](https://github.com/canonical/sphinx-docs-starter-pack).

TL;DR:

- Clone the starter pack repository to a local directory: `git clone [email protected]:canonical/sphinx-docs-starter-pack`.
- Copy the folder `.sphinx` under the starter pack repo to the operator repo `docs/.sphinx`.

## How to Customise Configurations

There are two configuration files: [`docs/conf.py`](./docs/conf.py) and [`docs/custom_conf.py`](./docs/custom_conf.py), copied and customised from the starter pack repo.

To customise, change the file [`docs/custom_conf.py`](./docs/custom_conf.py) only, and theoretically, we should not change [`docs/conf.py`](./docs/conf.py) (however, some changes are made to [`docs/conf.py`](./docs/conf.py), such as adding autodoc, PATH, fixing issues, etc.)

## How to Pull in Dependency Changes

The Canonical documentation starter pack uses Make to build the documentation, which will run the script [`docs/.sphinx/build_requirements.py`](./docs/.sphinx/build_requirements.py) and generate a requirement file `requirements.txt` under `docs/.sphinx/`.

To pull in new dependency changes from the starter pack, change to the starter pack repository directory, and build with the following command. This will create a virtual environment, generate a dependency file, install the software dependencies, and build the documentation:

```bash
make html
```

Then, compare the generated file `.sphinx/requirements.txt`and the `project.optional-dependencies.docs` section of [`pyproject.toml`](./pyproject.toml) and adjust the `pyproject.toml` file accordingly.

# Dependencies

The Python dependencies of `ops` are kept as minimal as possible, to avoid
Expand Down
7 changes: 1 addition & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# ruff: noqa
import sys
import os

Expand Down Expand Up @@ -98,12 +99,6 @@
]
exclude_patterns.extend(custom_excludes)

rst_epilog = '''
.. include:: /reuse/links.txt
'''
if 'custom_rst_epilog' in locals():
rst_epilog = custom_rst_epilog

source_suffix = {
'.rst': 'restructuredtext',
'.md': 'markdown',
Expand Down
150 changes: 141 additions & 9 deletions docs/custom_conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,40 @@
import datetime
# ruff: noqa
import datetime
import pathlib
import sys

import furo
import furo.navigation

sys.path.insert(0, str(pathlib.Path(__file__).parent.parent))

# Furo patch to get local TOC to show in sidebar (as sphinx-rtd-theme did)
# See https://github.com/pradyunsg/furo/blob/490527b2aef00b1198770c3389a1979911ee1fcb/src/furo/__init__.py#L115-L128

_old_compute_navigation_tree = furo._compute_navigation_tree


def _compute_navigation_tree(context):
tree_html = _old_compute_navigation_tree(context)
if not tree_html and context.get("toc"):
tree_html = furo.navigation.get_navigation_tree(context["toc"])
return tree_html


furo._compute_navigation_tree = _compute_navigation_tree

# Pull in fix from https://github.com/sphinx-doc/sphinx/pull/11222/files to fix
# "invalid signature for autoattribute ('ops.pebble::ServiceDict.backoff-delay')"
import re # noqa: E402
import sphinx.ext.autodoc # noqa: E402
sphinx.ext.autodoc.py_ext_sig_re = re.compile(
r'''^ ([\w.]+::)? # explicit module name
([\w.]+\.)? # module and/or class name(s)
([^.()]+) \s* # thing name
(?: \((.*)\) # optional: arguments
(?:\s* -> \s* (.*))? # return annotation
)? $ # and nothing more
''', re.VERBOSE)

# Custom configuration for the Sphinx documentation builder.
# All configuration specific to your project should be done in this file.
Expand All @@ -19,8 +55,8 @@
############################################################

# Product name
project = 'Documentation starter pack'
author = 'Canonical Group Ltd'
project = 'The ops library'
author = 'Canonical Ltd.'

# The title you want to display for the documentation in the sidebar.
# You might want to include a version number here.
Expand Down Expand Up @@ -67,7 +103,7 @@
# For example: "ubuntu.com/lxd" or "microcloud.is"
# If there is no product website, edit the header template to remove the
# link (see the readme for instructions).
'product_page': 'documentation.ubuntu.com',
'product_page': 'juju.is/docs/sdk',

# Add your product tag (the orange part of your logo, will be used in the
# header) to ".sphinx/_static" and change the path here (start with "_static")
Expand All @@ -77,21 +113,25 @@
# Change to the discourse instance you want to be able to link to
# using the :discourse: metadata at the top of a file
# (use an empty value if you don't want to link)
'discourse': 'https://discourse.ubuntu.com',
'discourse': 'https://discourse.charmhub.io/',

# Change to the Mattermost channel you want to link to
# (use an empty value if you don't want to link)
'mattermost': 'https://chat.canonical.com/canonical/channels/documentation',
'mattermost': '',

# Change to the Matrix channel you want to link to
# (use an empty value if you don't want to link)
'matrix': 'https://matrix.to/#/#charmhub-charmdev:ubuntu.com',

# Change to the GitHub URL for your project
'github_url': 'https://github.com/canonical/starter-pack',
'github_url': 'https://github.com/canonical/operator',

# Change to the branch for this version of the documentation
'github_version': 'main',

# Change to the folder that contains the documentation
# (usually "/" or "/docs/")
'github_folder': '/',
'github_folder': '/docs/',

# Change to an empty value if your GitHub repo doesn't have issues enabled.
# This will disable the feedback button and the issue link in the footer.
Expand Down Expand Up @@ -151,7 +191,12 @@
'canonical.related-links',
'canonical.custom-rst-roles',
'canonical.terminal-output',
'notfound.extension'
'notfound.extension',
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
]

# Add custom required Python modules that must be added to the
Expand Down Expand Up @@ -200,3 +245,90 @@
.. role:: center
:class: align-center
'''


# -- Options for sphinx.ext.todo ---------------------------------------------

# If this is True, todo and todolist produce output, else they
# produce nothing. The default is False.
todo_include_todos = False


# -- Options for sphinx.ext.autodoc ------------------------------------------

# This value controls how to represents typehints. The setting takes the
# following values:
# 'signature' – Show typehints as its signature (default)
# 'description' – Show typehints as content of function or method
# 'none' – Do not show typehints
autodoc_typehints = 'signature'

# This value selects what content will be inserted into the main body of an
# autoclass directive. The possible values are:
# 'class' - Only the class’ docstring is inserted. This is the
# default. You can still document __init__ as a separate method
# using automethod or the members option to autoclass.
# 'both' - Both the class’ and the __init__ method’s docstring are
# concatenated and inserted.
# 'init' - Only the __init__ method’s docstring is inserted.
autoclass_content = 'class'

# This value selects if automatically documented members are sorted
# alphabetical (value 'alphabetical'), by member type (value
# 'groupwise') or by source order (value 'bysource'). The default is
# alphabetical.
autodoc_member_order = 'alphabetical'

autodoc_default_options = {
'members': None, # None here means "yes"
'undoc-members': None,
'show-inheritance': None,
}

# -- Options for sphinx.ext.intersphinx --------------------------------------

# This config value contains the locations and names of other projects
# that should be linked to in this documentation.
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}

# -- General configuration ---------------------------------------------------

# If true, Sphinx will warn about all references where the target
# cannot be found.
nitpicky = True

# A list of (type, target) tuples (by default empty) that should be ignored when
# generating warnings in “nitpicky mode”. Note that type should include the
# domain name if present. Example entries would be ('py:func', 'int') or
# ('envvar', 'LD_LIBRARY_PATH').
nitpick_ignore = [
# Please keep this list sorted alphabetically.
('py:class', '_ChangeDict'),
('py:class', '_CheckInfoDict'),
('py:class', '_FileInfoDict'),
('py:class', '_NoticeDict'),
('py:class', '_ProgressDict'),
('py:class', '_Readable'),
('py:class', '_RelationMetaDict'),
('py:class', '_ResourceMetaDict'),
('py:class', '_StorageMetaDict'),
('py:class', '_TaskDict'),
('py:class', '_TextOrBinaryIO'),
('py:class', '_WarningDict'),
('py:class', '_Writeable'),
('py:class', 'ops.charm._ContainerBaseDict'),
('py:class', 'ops.model._AddressDict'),
('py:class', 'ops.model._ConfigOption'),
('py:class', 'ops.model._ModelBackend'),
('py:class', 'ops.model._ModelCache'),
('py:class', 'ops.model._NetworkDict'),
('py:class', 'ops.pebble._FileLikeIO'),
('py:class', 'ops.pebble._IOSource'),
('py:class', 'ops.pebble._ServiceInfoDict'),
('py:class', 'ops.pebble._SystemInfoDict'),
('py:class', 'ops.pebble._WebSocket'),
('py:class', 'ops.storage.JujuStorage'),
('py:class', 'ops.storage.SQLiteStorage'),
('py:class', 'ops.testing.CharmType'),
('py:obj', 'ops.testing.CharmType'),
]
Loading

0 comments on commit 8bae12d

Please sign in to comment.