Documenting your package
ℹ️ NoteThe objectives of this part:
- Understand the importance of documentation.
- Have complete documentation for your project.
- Understand how this documentation is constructed via
sphinx
.
Documentation is essential for people to want to use your application, report bugs or even contribute. To try to satisfy as many people as possible, documentation should at least contain:
- tutorials,
- short guides on the fields,
- reference documentation (for example the API).
Writing these different parts has other advantages:
- remember what we did six months ago.
- Have better code.
- Be a better writer in English (issue, email, etc.).
For writing Python application documentation, sphinx is widely used now. It relies mostly on ReadTheDocs for online distribution. There are different extensions to sphinx
that offer other features like nbsphinx which allows jupyter
notebooks to be integrated into the final documentation.
ℹ️ NoteOther projects in different languages also use sphinx for their documentation. For example, we can use breathe which allows you to easily integrate doxygen documentation.
Different formats can be used for writing documentation:
- markdown (.md)
- restructured text (.rst)
- notebook jupyter (.ipynb)
- ...
Important:
A few years ago, using
rst
offered more functionality and flexibility because we could describe our tags and the associated behavior ourselves. Now, with the arrival of myst, things are evolving and making it possible to enrich the markdown syntax.
Initialize your documentation with sphinx
You must first install sphinx using one of the following commands:
-
pip install sphinx
-
mamba install sphinx
We can now initiate the tree structure of the documentation requested by sphinx:
-
Execute next command:
sphinx-quickstart docs
-
Answer to questions !!!
It is always possible to change your responses by modifying the configuration file created during this phase.
You should get a tree structure that looks like this:
examples/calculator/docs
├── _build
├── _static
├── _templates
├── conf.py
├── index.rst
├── make.bat
└── Makefile
or this (if you answered yes to separate sources and build):
examples/calculator/docs
├── build
├── source
│ ├── _static
│ ├── _templates
│ ├── conf.py
│ └── index.rst
├── make.bat
└── Makefile
Build the documentation
To build the documentation, you can run
sphinx-build -M html sourcedir outputdir
or you can use the make files generated by the quickstart
make html
You can see your documentation by opening the index.html
file located inside your build folder. For now the web site is the default one, feel free to add your content and if needed add extensions, before building again.
Don't hesitate to read the sphinx documentation.
ℹ️ Building after a change can be tiring, the package sphinx-autobuild will rebuild Sphinx documentation on changes, with live-reload in the browser.
Sphinx extensions
There are many extensions. We give here a sample which is used quite regularly for scientific software documentation.
autodoc
This extension allows you to automatically document from their docstring
.:
- modules,
- classes,
- functions.
It is necessary to add in the extensions of conf.py
:
extensions = [..., "sphinx.ext.autodoc", ...]
An example of a docstring
:
def add(value1, value2):
"""
add two values.
:param value1: The first value
:type value1: float or int
:param value2: The second value
:type value2: float or int
:returns: the addition between value1 and value2
:rtype: float or int
"""
pass
To insert the documentation for this function into the documentation, simply create an rst
file with the content:
.. autofunction:: add
Documenting a module:
.. automodule:: mymod
:members:
:undoc-members:
Documenting a class:
.. autoclass:: myclass
:members:
:private-members:
:special-members:
For more information see autodoc.
It is possible to generate all of the rst
files for its API using the sphinx-apidoc
script:
sphinx-apidoc -f -o api examples/calculator
⚠️ The library that you want to get the docstring need to be in thesys.path
when you build your documentation with sphinx. To display it addimport sys print(sys.path)
in the conf.py file
Readability of docstrings
Using autodoc semantics in docstrings is a bit cumbersome and makes the documentation in the code difficult to read.
You have two extensions that can significantly improve readability:
To use numydoc
, you must add in the extension in the conf.py
file:
extensions = [..., "numpydoc", ...]
To use napoleon
, you must add in the extension in the conf.py
file:
extensions = [..., "sphinx.ext.napoleon", ...]
Here is an example documentation with NumPy
style.
def add(value1, value2):
"""
add two values.
Parameters
----------
value1 : float or int
the first value
value2 : float or int
the second value
Returns
-------
float or int
the addition between value1 and value2
"""
pass
nbsphinx
It is always interesting to put tutorials in your package allowing new users to quickly familiarize themselves with the tool. Notebooks
lend themselves very well to this.
There is two extensions that allow to integrate notebooks in sphinx: myst-nb and nbsphinx.
See more information here https://docs.readthedocs.io/en/stable/guides/jupyter.html#existing-relevant-extensions
Let's focus on nbsphinx
. To install it, simply do:
pip install nbsphinx
or
mamba install nbsphinx
To activate the extension, simply add it to the extension list in the conf.py
file:
extensions = [..., 'nbsphinx', ...]
⚠️ Carefulnbsphinx depends on, a non python program, pandoc. This stand-alone program is used to convert Markdown content to something Sphinx can understand. You have to install this program separately, ideally with your package manager. If you are using conda, you can install pandoc from the conda-forge channel:
conda install -c conda-forge pandoc
If that doesn’t work out for you, have a look at pandoc’s installation instructions.
ℹ️ NoteNotebooks can generate temporary files to save history. It is preferable to remove them explicitly by entering the
exclude_pattern
variable found in theconf.py
file:exclude_patterns = [..., '**.ipynb_checkpoints']
It is then possible to put the notebooks
in the toctree
in the same way as the rst
files.
⚠️ Keeping notebooks at the root of the project is best so that they remain clearly visible.
In sphinx, it is not possible to specify a directory other than where the
conf.py
file is located.One way to do this is to use the nbsphinx-link package.
Others interesting extensions
- sphinx.ext.viewcode: allows you to display the source code in in your documentation
- sphinx-copybutton: allows you to create a clickable button per code block. When an user click on it, the code content will be copied to his clipboard.
Read The Docs
RTD allows you to build and host your sphinx documentation based on your source version system (git, mercurial, etc.). Each tag
and branch
are converted into a version and RTD keeps the history of the different versions.
When you push your repository, RTD automatically starts generating the documentation, which means that your documentation is always up to date! It should also be noted that multi-language is supported.
Finally, two other interesting features: the documentation search is more powerful than the one you find in basic sphinx. The documentation is indexed via elasticsearch
and you can do full text
searches. Several output formats are supported: html, pdf, zipped html, epub, ...
ℹ️ See also https://readthedocs.org/
The theme
Finally, be aware that there are different themes for documentation. RTD has long had a default theme called sphinx_rtd_theme
. Since the arrival of jupyter-book and myst, things are evolving and the sites offer more and more possibilities at the level content placement and layout.
Theme of day pydata_sphinx_theme
Exercices
The pratical_session/TPs/2.sphinx/step0
directory takes up the last step of the previous TP by having added numpydoc
type docstrings for each of the functions.
Create your Sphinx structure by running the command:
sphinx-quickstart docs
Add a link to spline.md
in the toctree
of the index.md
file. Compile and look at the result.
Add api documentation using sphinx-apidoc
.
Add the following extensions "sphinx.ext.autodoc", "numpydoc", "myst_parser", "nbsphinx", "nbsphinx_link"
.
Add a toctree
with the api in the index.md
file.
Create a notebooks
directory with the circle.nblink
file containing:
{
"path": "../../notebooks/circle.ipynb"
}
and add it to the index.md
file
Change the theme in the conf.py
file to pydata_sphinx_theme
.
References
- Sphinx tutorial
- blog d'Eric Holscher
- What to write - Jacob Kaplan-Moss
- Teach, Don't Tell - Steve Losh