RSS

Sphinx-doc 101: Introduction to Sphinx-doc

An introduction to sphinx-doc, a documentation tool that makes it easy to create intelligent and beautiful documentation.

Sphinx is a documentation generator that makes it easy to create intelligent and beautiful documentation.

Sphinx was originally created for the Python documentation, then it extend to support many other languages. It use reStructuredText format to write document.

If you are first time hearing reStructuredText, checkout reStructuredText Primer

As an example, checkout django-cas-ng document which is generated by sphinx-doc.

Features

  • Support multiple output formats: HTML, LaTeX, pdf, ePub, Texinfo, manual pages, plain text.
  • Extensive cross-references: semantic markup and automatic links for functions, classes, citations, glossary terms and similar pieces of information
  • Hierarchical structure: easy definition of a document tree, with automatic links to siblings, parents and children
  • Automatic indices: general index as well as a language-specific module indices
  • Code handling: automatic highlighting using the Pygments highlighter
  • Extensions: automatic testing of code snippets, inclusion of docstrings from Python modules (API docs), and more
  • Extendable: more than 50 extensions contributed by users in a second repository; most of them installable from PyPI

Quick start

Install

$ pip install Sphinx

First project

$ mkdir docs
$ cd docs
$ sphinx-quickstart
Welcome to the Sphinx 2.3.1 quickstart utility.

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

Selected root path: .

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]:

The project name will occur in several places in the built documentation.
> Project name: My Awesome Project
> Author name(s): Your name
> 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
https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language.
> Project language [en]:

Creating file ./conf.py.
Creating file ./index.rst.
File ./Makefile already exists, skipping.
Creating file ./make.bat.

Finished: An initial directory structure has been created.

You should now populate your master file ./index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

Generate document

Generate html, the output directory is _build/html:

$ make html
Running Sphinx v2.3.1
making output directory... done
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 3 source files that are out of date

...
...
The HTML pages are in _build/html.

Generate pdf, the output directory is _build/latex:

$ make latexpdf
...
...
Output written on anawesomeproject.pdf (5 pages, 39374 bytes).
Transcript written on anawesomeproject.log.
=== TeX engine is 'pdfTeX'
Latexmk: Index file 'anawesomeproject.idx' was written
Latexmk: Log file says output to 'anawesomeproject.pdf'
Latexmk: All targets () are up-to-date

Extensions

Since many projects will need special features in their documentation, Sphinx allows adding “extensions” to the build process, each of which can modify almost any aspect of document processing. You can even build your own extension.

Sphinx have many extensions.

For python project, you may interested in following extensions:

sphinx.ext.autodoc - Generate Python Module API Documentation

autodoc can import the modules you are documenting, and pull in documentation from docstrings in a semi-automatic way.

You can use autodoc extension to generate Python module API documentation.

First you need add sphinx.ext.autodoc to extensions in conf.py:

extensions = [
     # ...
    'sphinx.ext.autodoc',   # Pull in documentation from docstrings
]

Then you can use sphinx-apidoc to automatically Python module API document.

$ sphinx-apidoc -h
usage: sphinx-apidoc [OPTIONS] -o <OUTPUT_PATH> <MODULE_PATH> [EXCLUDE_PATTERN, ...]

Look recursively in <MODULE_PATH> for Python modules and packages and create
one reST file with automodule directives per package in the <OUTPUT_PATH>. The
<EXCLUDE_PATTERN>s can be file and/or directory patterns that will be excluded
from generation. Note: By default this script will not overwrite already
created files.
$ sphinx-apidoc -o api ../cas
Creating file api/cas.rst.
Creating file api/modules.rst.

Example of api/modules.rst:

cas
===

.. toctree::
   :maxdepth: 4

   cas

Example of api/cas.rst:

cas package
===========

Submodules
----------

cas.cas module
--------------

.. automodule:: cas.cas
   :members:
   :undoc-members:
   :show-inheritance:


Module contents
---------------

.. automodule:: cas
   :members:
   :undoc-members:
   :show-inheritance:

sphinx.ext.napoleon - – Support for NumPy and Google style docstrings

napoleon allow you write api documentation in Google python style docstrings.

For example, instead of

:param path: The path of the file to wrap
:type path: str
:param field_storage: The :class:`FileStorage` instance to wrap
:type field_storage: FileStorage
:param temporary: Whether or not to delete the file when the File
   instance is destructed
:type temporary: bool
:returns: A buffered writable file descriptor
:rtype: BufferedFileStorage

You can write it i Google style:

Args:
    path (str): The path of the file to wrap
    field_storage (FileStorage): The :class:`FileStorage` instance to wrap
    temporary (bool): Whether or not to delete the file when the File
       instance is destructed

Returns:
    BufferedFileStorage: A buffered writable file descriptor

Checkout Google Style Python Docstring Example.

viewcode looks at your Python object descriptions (.. class::, .. function:: etc.) and tries to find the source files where the objects are contained. When found, a separate HTML page will be output for each module with a highlighted version of the source code, and a link will be added to all object descriptions that leads to the source code of the described object. A link back from the source to the description will also be inserted.

This is helpful in your documentation, you can cross reference to source code.

sphinx_sitemap

sphinx_sitemap is a third party extension can be used to generate a sitemap.xml. You need install it by:

$ pip install sphinx_sitemap

m2r - Markdown to reStructuredText

m2r is a third party extension to convert Markdown to reStructuredText. You need install it by:

$ pip install m2r

Then you can add .md files to your sphinx-doc project.

Troubleshooting

WARNING: html_static_path entry ‘_static’ does not exist

When run make html, it report following warning:

WARNING: html_static_path entry '_static' does not exist

This is due to in conf.py, html_static_path have entry value _static, this is default setting.

To remove the warnings, try setting html_static_path = [] in your conf.py or create a empty _static directory.

WARNING: autodoc: failed to import class ‘xxxx’

If you use autodoc for Python api in Django module, you may When run into autodoc failed to import class error when you run make html. For example:

$ make html
...
...
WARNING: autodoc: failed to import class 'backends.CASBackend' from module 'django_cas_ng'; the following exception was raised:
Traceback (most recent call last):
  File "devenv/py3/lib/python3.7/site-packages/sphinx/ext/autodoc/importer.py", line 32, in import_module
    return importlib.import_module(modname)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "devenv/py3/lib/python3.7/site-packages/django_cas_ng/__init__.py", line 37, in <module>
    getattr(settings, key)
  File "devenv/py3/lib/python3.7/site-packages/django/conf/__init__.py", line 76, in __getattr__
    self._setup(name)
  File "devenv/py3/lib/python3.7/site-packages/django/conf/__init__.py", line 61, in _setup
    % (desc, ENVIRONMENT_VARIABLE))
django.core.exceptions.ImproperlyConfigured: Requested setting CAS_ADMIN_PREFIX, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

To fix this issue, you need add your module to syspath and have a dummy django config. You need add some python code in your conf.py. For example:

import os
import sys

import django
from django.conf import settings

sys.path.insert(0, os.path.abspath('../'))
sys.path.insert(0, os.path.abspath('../tests'))
settings.configure(
    SECRET_KEY='something to make Django happy',
    INSTALLED_APPS=[
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django_cas_ng'
    ])
django.setup()

References