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.txt
orpip install -e .
)Run
pip install sphinx
Create a docs folder, e.g.
mkdir docs
andcd
into itRun
sphinx-quickstart
. Say yes to saving build and source files separatelyEdit the
conf.py
file 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"))
cd
into the docs folders and runmake html
. This will create your raw docs. You can verify this by clicking theindex.html
file 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_MODULE
You 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_typehints
Add 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 furo
Change the theme in
conf.py
html_theme = 'furo'