Autodocumenting your Python code with Sphinx - part 2

Feb. 24, 2016     0 comments

This is Part 2 of my Sphinx autodocumentation tutorial. Part 1 of this tutorial you can find by the following link:

Autodocumenting your Python code with Sphinx - part 1

As I've mentioned in Part 1, Sphinx as an automatic documentation generator for Python is neither convenient nor simple. But it is de facto the tool for documenting Python programs and libraries, so unfortunately we have to deal with its weaknesses.

In Part 1 I've demonstrated you how to write Sphinx-compatible docstrings for your Python objects, and now I'll show you how to set-up a Sphinx project to generate documentation from your code docstrings.

Configuring Sphinx

To install Sphinx into your Python environment (using a virtual environment is strongly recommended) simply type in console:

pip install Sphinx

On Windows you need to add \Scripts sub-folder of your Python environment to %PATH%.

To create a Sphinx documentation project run sphinx-quickstart command in your Python project folder. It will ask you a series of questions about your project configuration:

Click to show
(venv) D:\Git\sphinx_tutorial>sphinx-quickstart
Welcome to the Sphinx 1.3.3 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Enter the root path for documentation.
> Root path for the documentation [.]: docs

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: n

Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]:

The project name will occur in several places in the built documentation.
> Project name: Sphinx Tutorial
> Author name(s): Roman Miroshnychenko

Sphinx has the notion of a "version" and a "release" for the
software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1.  If you don't need this dual structure,
just set both to the same value.
> Project version: 1.0.0
> Project release [1.0.0]:

If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.

For a list of supported codes, see
http://sphinx-doc.org/config.html#confval-language.
> Project language [en]:

The file name suffix for source files. Commonly, this is either ".txt"
or ".rst".  Only files with this suffix are considered documents.
> Source file suffix [.rst]:

One document is special in that it is considered the top node of the
"contents tree", that is, it is the root of the hierarchical structure
of the documents. Normally, this is "index", but if your "index"
document is a custom template, you can also set this to another filename.
> Name of your master document (without suffix) [index]:

Sphinx can also add configuration for epub output:
> Do you want to use the epub builder (y/n) [n]: n

Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]: y
> doctest: automatically test code snippets in doctest blocks (y/n) [n]: n
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: y
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: n
> coverage: checks for documentation coverage (y/n) [n]: n
> pngmath: include math, rendered as PNG images (y/n) [n]: n
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]: n
> ifconfig: conditional inclusion of content based on config values (y/n) [n]: n
> viewcode: include links to the source code of documented Python objects (y/n) [n]: y

A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]: y
> Create Windows command file? (y/n) [y]: y


This is an example output of sphinx-quickstart. I'll point out only a few items.

> autodoc: automatically insert docstrings from modules (y/n) [n]: y

Naturally, to document your code you need to reply y here.

> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: y

Usually you'd want to reference at least Python standard library so reply y.

> viewcode: include links to the source code of documented Python objects (y/n) [n]: y

In most cases including your source code in Sphinx-generated documentation will be helpful so reply y.

Sphinx will generate a skeleton for your documentation, and you need to add some meat to it. Sphinx project configuration is defined in conf.py file. This is a usual Python module that consists mostly of configuration variables. In my Sphinx Tutorial project on Github you can find an example of conf.py module. Read my comments marked with double hashes ## about important configuration variables.

Because Sphinx imports your code when generating documentation, it is important that your code can be imported without any side effects like unexpected exceptions.

Generating Documentation from Docstrings

Sphinx supports a set of autodoc directives to document your code: modules, functions, classes and so on. To document a module you need to include an automodule directive with necessary options into your reST document. Usually a separate reST document is created for each module. For example:

Module foo
==========

.. automodule:: foo
:members:
:show-inheritance:

This directive will generate documentation for your module from docstrings found in that module. Here foo is the name of our module. The automodule directive requires a fully qualified module name, starting from the top-level package, if any. By providing additional options, you can control which module members are included in the documentation. For example, :inherited-members: option allows to include inherited methods in child classes. Note that reST/Sphinx directives, like Python itself, are indentation-sensitive, that is additional options for automodule directive should be indented at the same level.

You need to create reST files with automodule directives for every module you want to document. This may not be very convenient if you have many modules. Fortunately, Sphinx includes tools that can help your generate automodule directives for your Python code. You can use either sphinx-apidoc or spinx.ext.autosummary.

sphinx-apidoc

sphinx-apidoc is a CLI utility that generates .rst files with autodoc directives from your code. The command has the following format:

sphinx-apidoc -o <output dir> <code dir>

It creates a set of .rst files in the <output dir>: a file for each of your modules and modules.rst file that serves as an index. Those files can be included in your Sphinx documentation structure. You may want to edit auto-generated .rst files to correct headers and/or add other necessary information.

Let's take my tutorial project. If you type the console:

sphinx-apidoc -o ./docs/_modules ./src

sphinx-apidoc will generate the necessary .rst files in /docs/_modules folder.

You need to run sphinx-apidoc each time the structure of your Python modules changes. By default sphinx-apidoc does not overwrite existing .rst files unless -f option is used.

The main disadvantage of sphinx-apidoc is that the resulting documentation does not have any index or table of contents. If your modules include many documented objects, browsing documentation created with the help of sphinx-apidoc is difficult. The main documentation index created by Sphinx may help to some degree, but if you have many objects you should consider using sphinx.ext.autosummary. extension for Sphinx.

sphinx.ext.autosummary

The sphinx.ext.autosummary extension helps to create references to your code in the documentation. An autosummary is a two-column table with Python object names in the first column and brief descriptions of those objects in the second column. Python object names also serve as links to auto-generated documentation for those objects. The first lines of objects' docstrings are used as brief descriptions in the autosummary tables. You can insert an autosummary table anywhere in your documentation.

The sphinx.ext.autosummary can also create .rst files with autodoc directives, but, unlike sphinx-apidoc, those files have autousummary tables for classes, functions and exceptions. That is sphinx.ext.autosummary can be used instead of sphinx-apidoc. To enable this feature you need to include autosummary_generate = True parameter into your conf.py file.

To generate .rst files with autodoc directives for your modules you need to include the autosummary directive into one of your project .rst files (for example, modules.rst) as shown in the following example:

API Reference
=============

.. autosummary::
:toctree: _autosummary

foo
bar
baz.spam

To add auto-generated documentation to the table of contents of your Sphinx project simply add .rst file(s) containing autosummary directives, as shown in the preceding example, to your main TOC tree (usually in index.rst file).

Html pages generated from your autodoc.rst files will include rich-formatted documentation created from your docstrings based on reST markup. At the beginning of each documentation page autosummary tables of all functions, classes and exceptions located in that module are created, allowing you to quickly navigate to the necessary object. You can also use cross-referencing directives (see Part 1) to reference specific objects in your auto-generated documentation.

Your Sphinx project can also include textual pages that describe how to use your Python program or library (which is highly recommend, poor documentation is the plague of open-source projects), but teaching you how to write textual documentation is beyond the scope of this tutorial.

After you finish authoring your documentation, run make html inside your documentation directory to generate a static website from your Sphinx project. This website can then be published on Github Pages, ReadTheDocs or another hosting of your choice.
Hint. Github Pages use their own static website generator — Jekyll — which may interfere with your Sphinx-generated html/css/js code. To disable Jekyll for your website add an empty file named .nojekyll` into the root of gh-pages branch in your repository.