Creating Rich Documentation With Sphinx#
sphinx is a python package that allows you to generate rich documentation automatically from your docstrings. It is relatively simple to set up, but it can be a bit difficult to customise it.
Here are a few tips for creating rich documentation very easily.
Quickstart#
Firstly, we create a basic documentation by following the sphinx guidelines. In summary:
Create venv and install package dependencies (e.g. either
pip install -r requirements.txtorpip install -e .)Run
pip install sphinxCreate a docs folder, e.g.
mkdir docsandcdinto itRun
sphinx-quickstart. Say yes to saving build and source files separatelyEdit the
conf.pyfile that is created. At the bottom, make sure to add the following line to enable auto doc generation from docstrings:
extensions = ["sphinx.ext.autodoc"]
Edit the path to the module at the top of
conf.py
import os
import sys
sys.path.insert(0, os.path.abspath("REL_PATH_TO_MODULE"))
cdinto the docs folders and runmake html. This will create your raw docs. You can verify this by clicking theindex.htmlfile withinbuild/which should take you to the index page of your docsAutogenerate documentation from your docstrings by running
sphinx-apidoc -o $LOCATION_OF_SOURCE_FOLDER $PATH_TO_MODULEYou should now have autodocs based on your docstrings!
From this point onwards, you can play with the generate .rst files to modify/move things around.
Parsing numpy or google docstrings#
By default, sphinx only recognizes the sphinx docstring format. In order to recognize numpy and google, you need to add the sphinx.ext.napolean extension to your extensions in conf.py
extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon"]
Parsing typing style of annotations to reduce clutter in docstrings#
You may wish to use Python’s typing module to annotate your functions. For instance, consider the following function (documented with sphinx formatting):
def test(test_param, test_param_optional=None):
"""test function
:param test_param: required param
:type test_param: bool
:param test_param_optional: optional string param, defaults to None
:type test_param_optional: str, optional
:return: answer to life
:rtype: int
"""
return 42
Annotating using the typing module allows you to define the types more concisely:
def test(test_param: bool, test_param_optional: str = None) -> int:
"""test function
:param test_param: required param
:param test_param_optional: optional string param, defaults to None
:return: answer to life
"""
return 42
However, by default the types will not get recognized by sphinx in the docs. To achieve this, you must provide the sphinx_autodoc_typehints extension as well as the sphinx.ext.napoleon extension.
Install the typehints extension,
pip install sphinx_autodoc_typehintsAdd the extensions to
conf.py
extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx_autodoc_typehints"] # note, typehints extension should follow the napoleon one
Linking to code#
sphinx.ext.viewcode or sphinx.ext.linkcode extensions
Adding custom themes#
You can change the default docs theme. One of my favorites is furo
pip install furoChange the theme in
conf.py
html_theme = 'furo'