Sphinx (documentation generator)
lastmod 2025-02-14created 2016-01-1447 edits
For other meanings (homonyms), seehere.
Sphinx is a documentation generator for the Python programming language.
Categories
- Breathe (integration of Sphinx and Doxygen)
- reStructuredText (rst)
- Read the Docs
Quick start
Assuming you have Python already, install Sphinx:
Create a directory inside your project to hold your docs:
Run sphinx-quickstart in there:
This quick start will walk you through creating the basic configuration; in most cases, you can just accept the defaults. When it’s done, you’ll have an index.rst, a conf.py and some other files. Add these to revision control.
Now, edit your index.rst and add some information about your project. Include as much detail as you like (refer to the reStructuredText syntax or this template if you need help). Build them to see how they look:
How to Build
When python modules can be invoked directly (e.g. when using pyenv), you can use the sphinx-build command line as is. Otherwise, you can substitute the python -m sphinx command.
Example
-
-W: Treats warnings as errors. -
-b html: Selects HTML as the builder. Options includehtml,man,latex,text,texinfo,pdf, and more. -
-d ./_doctrees: Directory where cache files are stored. -
./_doc: Directory containing the documentation sources. Unless the-c PATHoption is applied, theconf.pyfile is read from this directory. -
./_html: Output directory.
Help message
$ sphinx-build --help
usage: sphinx-build [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]
Generate documentation from source files. sphinx-build generates documentation
from the files in SOURCEDIR and places it in OUTPUTDIR. It looks for 'conf.py'
in SOURCEDIR for the configuration settings. The 'sphinx-quickstart' tool may
be used to generate template files, including 'conf.py' sphinx-build can
create documentation in different formats. A format is selected by specifying
the builder name on the command line; it defaults to HTML. Builders can also
perform other tasks related to documentation processing. By default,
everything that is outdated is built. Output only for selected files can be
built by specifying individual filenames.
positional arguments:
sourcedir path to documentation source files
outputdir path to output directory
filenames a list of specific files to rebuild. Ignored if -a is
specified
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
general options:
-b BUILDER builder to use (default: html)
-a write all files (default: only write new and changed
files)
-E don't use a saved environment, always read all files
-d PATH path for the cached environment and doctree files
(default: OUTPUTDIR/.doctrees)
-j N build in parallel with N processes where possible (special
value "auto" will set N to cpu-count)
build configuration options:
-c PATH path where configuration file (conf.py) is located
(default: same as SOURCEDIR)
-C use no config file at all, only -D options
-D setting=value override a setting in configuration file
-A name=value pass a value into HTML templates
-t TAG define tag: include "only" blocks with TAG
-n nit-picky mode, warn about all missing references
console output options:
-v increase verbosity (can be repeated)
-q no output on stdout, just warnings on stderr
-Q no output at all, not even warnings
--color do emit colored output (default: auto-detect)
-N, --no-color do not emit colored output (default: auto-detect)
-w FILE write warnings (and errors) to given file
-W turn warnings into errors
--keep-going with -W, keep going when getting warnings
-T show full traceback on exception
-P run Pdb on exception
For more information, visit <http://sphinx-doc.org/>.
Configuration
Edit the conf.py file.
- exclude_patterns
- Enter the patterns to ignore.
- master_doc
- The starting document
conf.py
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import os
import sys
SCRIPT_PATH = os.path.abspath(__file__)
SCRIPT_DIR = os.path.dirname(SCRIPT_PATH)
STATIC_DIR = os.path.join(SCRIPT_DIR, "_static")
LOCALE_DIR = os.path.join(SCRIPT_DIR, "_locale")
TEMPLATES_DIR = os.path.join(SCRIPT_DIR, "_templates")
EXTENSIONS_DIR = os.path.join(SCRIPT_DIR, '_extensions')
sys.path.insert(0, EXTENSIONS_DIR)
# Project information
project = "project"
copyright = "2021-2022, Company" # noqa
author = "yourname"
# General configuration
extensions = [
"sphinx.ext.autodoc",
"recommonmark",
"google_analytics",
]
source_suffix = [".rst", ".md"]
source_encoding = "utf-8"
master_doc = "index"
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".tox"]
templates_path = [TEMPLATES_DIR]
language = "ko"
# HTML Output
html_theme = "furo"
html_static_path = [STATIC_DIR]
# Locale
locale_dirs = [LOCALE_DIR]
gettext_compact = False
# Google Analytics
google_analytics_enabled = True
google_analytics_id = "UA-162764112-2"
Internationalization
You need to use gettext.
Themes
Extensions
googleanalytics
recommonmark
Simply put, a markdown parser.
| WARNING |
| recommonmark is now deprecated. We recommend using MyST for a docutils bridge going forward. |
cannot import name ExtensionError
Modify the code to use sphinx.errors.ExtensionError.
Direct integration
- Sphinx FAQ — Sphinx documentation - includes how to connect Google Analytics.
If you want to connect the Google analytics service directly to Sphinx, You can use a custom layout.html template, like this:
{% extends "!layout.html" %}
{%- block extrahead %}
{{ super() }}
<script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'XXX account number XXX']);
_gaq.push(['_trackPageview']);
</script>
{% endblock %}
{% block footer %}
{{ super() }}
<div class="footer">This page uses <a href="https://analytics.google.com/">
Google Analytics</a> to collect statistics. You can disable it by blocking
the JavaScript coming from www.google-analytics.com.
<script>
(function() {
var ga = document.createElement('script');
ga.src = ('https:' == document.location.protocol ?
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
ga.setAttribute('async', 'true');
document.documentElement.firstChild.appendChild(ga);
})();
</script>
</div>
{% endblock %}
automodule
- sphinx.ext.autodoc – Include documentation from docstrings — Sphinx 4.0.0+ documentation
- Following along with sphinx - Weird Meetup
- Python package dev log 10: Making Sphinx reference pages
Include documentation from docstrings
recc.config
===========
.. automodule:: recc.config
:members:
:undoc-members:
:show-inheritance:
.. automodule:: recc.config.argparse
:members:
.. automodule:: recc.config.init_params
:members:
Python documentation example
In general, a typical Sphinx docstring has the following format:
"""[Summary]
:param [ParamName]: [ParamDescription], defaults to [DefaultParamVal]
:type [ParamName]: [ParamType](, optional)
...
:raises [ErrorType]: [ErrorDescription]
...
:return: [ReturnDescription]
:rtype: [ReturnType]
"""
Let’s have a look at a typical class documentation. In this example we show the docstrings written for the SimpleBleDevice class, which is defined within our simpleble module:
class SimpleBleDevice(object):
"""This is a conceptual class representation of a simple BLE device
(GATT Server). It is essentially an extended combination of the
:class:`bluepy.btle.Peripheral` and :class:`bluepy.btle.ScanEntry` classes
:param client: A handle to the :class:`simpleble.SimpleBleClient` client
object that detected the device
:type client: class:`simpleble.SimpleBleClient`
:param addr: Device MAC address, defaults to None
:type addr: str, optional
:param addrType: Device address type - one of ADDR_TYPE_PUBLIC or
ADDR_TYPE_RANDOM, defaults to ADDR_TYPE_PUBLIC
:type addrType: str, optional
:param iface: Bluetooth interface number (0 = /dev/hci0) used for the
connection, defaults to 0
:type iface: int, optional
:param data: A list of tuples (adtype, description, value) containing the
AD type code, human-readable description and value for all available
advertising data items, defaults to None
:type data: list, optional
:param rssi: Received Signal Strength Indication for the last received
broadcast from the device. This is an integer value measured in dB,
where 0 dB is the maximum (theoretical) signal strength, and more
negative numbers indicate a weaker signal, defaults to 0
:type rssi: int, optional
:param connectable: `True` if the device supports connections, and `False`
otherwise (typically used for advertising ‘beacons’).,
defaults to `False`
:type connectable: bool, optional
:param updateCount: Integer count of the number of advertising packets
received from the device so far, defaults to 0
:type updateCount: int, optional
"""
def __init__(self, client, addr=None, addrType=None, iface=0,
data=None, rssi=0, connectable=False, updateCount=0):
"""Constructor method
"""
super().__init__(deviceAddr=None, addrType=addrType, iface=iface)
self.addr = addr
self.addrType = addrType
self.iface = iface
self.rssi = rssi
self.connectable = connectable
self.updateCount = updateCount
self.data = data
self._connected = False
self._services = []
self._characteristics = []
self._client = client
def getServices(self, uuids=None):
"""Returns a list of :class:`bluepy.blte.Service` objects representing
the services offered by the device. This will perform Bluetooth service
discovery if this has not already been done; otherwise it will return a
cached list of services immediately..
:param uuids: A list of string service UUIDs to be discovered,
defaults to None
:type uuids: list, optional
:return: A list of the discovered :class:`bluepy.blte.Service` objects,
which match the provided ``uuids``
:rtype: list On Python 3.x, this returns a dictionary view object,
not a list
"""
self._services = []
if(uuids is not None):
for uuid in uuids:
try:
service = self.getServiceByUUID(uuid)
self.services.append(service)
except BTLEException:
pass
else:
self._services = super().getServices()
return self._services
def setNotificationCallback(self, callback):
"""Set the callback function to be executed when the device sends a
notification to the client.
:param callback: A function handle of the form
``callback(client, characteristic, data)``, where ``client`` is a
handle to the :class:`simpleble.SimpleBleClient` that invoked the
callback, ``characteristic`` is the notified
:class:`bluepy.blte.Characteristic` object and data is a
`bytearray` containing the updated value. Defaults to None
:type callback: function, optional
"""
self.withDelegate(
SimpleBleNotificationDelegate(
callback,
client=self._client
)
)
def getCharacteristics(self, startHnd=1, endHnd=0xFFFF, uuids=None):
"""Returns a list containing :class:`bluepy.btle.Characteristic`
objects for the peripheral. If no arguments are given, will return all
characteristics. If startHnd and/or endHnd are given, the list is
restricted to characteristics whose handles are within the given range.
:param startHnd: Start index, defaults to 1
:type startHnd: int, optional
:param endHnd: End index, defaults to 0xFFFF
:type endHnd: int, optional
:param uuids: a list of UUID strings, defaults to None
:type uuids: list, optional
:return: List of returned :class:`bluepy.btle.Characteristic` objects
:rtype: list
"""
self._characteristics = []
if(uuids is not None):
for uuid in uuids:
try:
characteristic = super().getCharacteristics(
startHnd, endHnd, uuid)[0]
self._characteristics.append(characteristic)
except BTLEException:
pass
else:
self._characteristics = super().getCharacteristics(startHnd,
endHnd)
return self._characteristics
def connect(self):
"""Attempts to initiate a connection with the device.
:return: `True` if connection was successful, `False` otherwise
:rtype: bool
"""
try:
super().connect(self.addr,
addrType=self.addrType,
iface=self.iface)
except BTLEException as ex:
self._connected = False
return (False, ex)
self._connected = True
return True
def disconnect(self):
"""Drops existing connection to device
"""
super().disconnect()
self._connected = False
def isConnected(self):
"""Checks to see if device is connected
:return: `True` if connected, `False` otherwise
:rtype: bool
"""
return self._connected
def printInfo(self):
"""Print info about device
"""
print("Device %s (%s), RSSI=%d dB" %
(self.addr, self.addrType, self.rssi))
for (adtype, desc, value) in self.data:
print(" %s = %s" % (desc, value))
Another function:
async def executemany(self, command: str, args, *, timeout: float=None):
"""Execute an SQL *command* for each sequence of arguments in *args*.
Example:
.. code-block:: pycon
>>> await con.executemany('''
... INSERT INTO mytab (a) VALUES ($1, $2, $3);
... ''', [(1, 2, 3), (4, 5, 6)])
:param command: Command to execute.
:param args: An iterable containing sequences of arguments.
:param float timeout: Optional timeout value in seconds.
:return None: This method discards the results of the operations.
.. note::
When inserting a large number of rows,
use :meth:`Connection.copy_records_to_table()` instead,
it is much more efficient for this purpose.
.. versionadded:: 0.7.0
.. versionchanged:: 0.11.0
`timeout` became a keyword-only parameter.
"""
self._check_open()
return await self._executemany(command, args, timeout)
Plugins
- sphinxcontrib-httpdomain
- https://sphinxcontrib-httpexample.readthedocs.io/en/latest/#
Theme
- sphinx-rtd-theme
- https://pypi.org/project/sphinx-rtd-theme/
- pydata-sphinx-theme
- The PyData Sphinx Theme
- https://github.com/pydata/pydata-sphinx-theme
- https://pydata-sphinx-theme.readthedocs.io/en/latest/
Troubleshooting
contents.rst not found
Add the following to the conf.py file.
With this, it looks for the index.rst file in the project directory.
See also
- Documentation generator
- Python
- Doxygen
- Pelican
- Swagger
- Sphinx (documentation generator)
- Redoc
- mkdocs
- Nikola
Favorite site
- Sphinx web site
- Wikipedia (en) Sphinx (documentation generator)
- Writing docstrings — Sphinx-RTD-Tutorial documentation
- Example Google Style Python Docstrings — Sphinx 4.0.0+ documentation
- Documenting Your Project Using Sphinx — an_example_pypi_project v0.0.5 documentation
- Python documentation: a very simple start with Sphinx
- [Recommended] How to use Read-the-docs
- Coding is a hobby :: (Python) Documentation feat Sphinx