Python Sphinx
Documentation generation tool that converts reStructuredText files into HTML, PDF, and other formats.
Python Sphinx
Documentation generation tool that converts reStructuredText files into HTML, PDF, and other formats.
Overview
Sphinx is a powerful documentation generator originally created for Python documentation. It uses reStructuredText as its markup language and can extract documentation from code docstrings. Sphinx is widely used for technical documentation, API references, and project wikis. It features cross-referencing, automatic index generation, code syntax highlighting, and extensive customisation through themes and extensions.
flowchart TB
subgraph "Documentation Sources"
A[reStructuredText Files] --> B[Sphinx Build]
C[Python Docstrings] --> D[autodoc Extension]
D --> B
E[Configuration conf.py] --> B
end
subgraph "Build Process"
B --> F[Parse & Process]
F --> G[Apply Theme]
G --> H[Generate Output]
end
subgraph "Output Formats"
H --> I[HTML]
H --> J[PDF]
H --> K[ePub]
H --> L[Man Pages]
end
subgraph "Features"
M[Cross-references] --> B
N[Search Index] --> B
O[Code Highlighting] --> B
P[Extensions] --> B
end
Project Setup and Configuration
Key Concepts
- sphinx-quickstart: Interactive tool to initialise a Sphinx project
- conf.py: Python configuration file controlling all Sphinx settings
- index.rst: Main entry point and table of contents
- _build/: Directory containing generated documentation
- Source structure: Organised directory layout for documentation files
Creating a New Project
# Install Sphinx
pip install sphinx
# Create documentation directory
mkdir docs
cd docs
# Initialise Sphinx project (interactive)
sphinx-quickstart
# Or non-interactive with options
sphinx-quickstart \
--sep \
--project "My Project" \
--author "Your Name" \
--release "1.0" \
--language en \
--ext-autodoc \
--ext-viewcode \
--makefile \
--no-batchfile
Project Structure
docs/
├── source/ # Source files (with --sep)
│ ├── conf.py # Configuration
│ ├── index.rst # Main page
│ ├── _static/ # Static files (CSS, images)
│ └── _templates/ # Custom templates
├── build/ # Generated output
│ └── html/ # HTML output
├── Makefile # Build commands (Unix)
└── make.bat # Build commands (Windows)
Basic Configuration
# conf.py - Essential settings
# Project information
project = 'My Project'
copyright = '2024, Your Name'
author = 'Your Name'
release = '1.0.0'
# General configuration
extensions = [
'sphinx.ext.autodoc', # Include docstrings
'sphinx.ext.napoleon', # Google/NumPy style docstrings
'sphinx.ext.viewcode', # Add source code links
'sphinx.ext.intersphinx', # Link to other projects
'sphinx.ext.todo', # TODO notes
'sphinx.ext.coverage', # Documentation coverage
]
# Templates and static files
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# Language and localisation
language = 'en'
# HTML output options
# Default built-in theme is 'alabaster'. 'sphinx_rtd_theme' is a separate
# package: pip install sphinx-rtd-theme (or: uv add sphinx-rtd-theme).
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
html_css_files = ['custom.css']
html_logo = '_static/logo.png'
html_favicon = '_static/favicon.ico'
# HTML theme options
html_theme_options = {
'navigation_depth': 4,
'collapse_navigation': False,
'sticky_navigation': True,
'includehidden': True,
'titles_only': False
}
# Intersphinx mapping (link to other docs)
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
'requests': ('https://requests.readthedocs.io/en/latest/', None),
'numpy': ('https://numpy.org/doc/stable/', None),
}
# autodoc settings
autodoc_default_options = {
'members': True,
'member-order': 'bysource',
'special-members': '__init__',
'undoc-members': True,
'exclude-members': '__weakref__'
}
# Napoleon settings (for Google/NumPy docstrings)
napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = True
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = True
napoleon_use_admonition_for_notes = True
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True
Index File Structure
.. index.rst - Main documentation entry point
Welcome to My Project's Documentation
======================================
.. toctree::
:maxdepth: 2
:caption: Contents:
getting-started
user-guide
api-reference
development
changelog
Introduction
------------
Brief project description goes here.
Quick Start
-----------
.. code-block:: python
import myproject
# Simple example
result = myproject.do_something()
Indices and Tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
reStructuredText Syntax
Key Concepts
- Directives: Commands that generate content (.. directive::)
- Roles: Inline markup for cross-references (:role:
text) - Indentation: Significant for nested content
- Blank lines: Separate content blocks
- Escaping: Backslash for literal characters
flowchart LR
subgraph "RST Elements"
A[Headings] --> B[Document Structure]
C[Directives] --> D[Special Content]
E[Roles] --> F[Inline Markup]
G[Lists] --> H[Content Organization]
end
Headings and Structure
# Document title (with overline)
######################
Chapter 1: Main Title
######################
Section Heading
===============
Subsection Heading
------------------
Subsubsection Heading
^^^^^^^^^^^^^^^^^^^^^
Paragraph Heading
"""""""""""""""""
# Heading hierarchy (most common)
# = - ^ " ' ~ ` # * + _
Simple Paragraph
----------------
This is a simple paragraph. Paragraphs are separated
by blank lines and can span multiple lines.
This is another paragraph.
Text Formatting
# Inline markup
*emphasis (italics)*
**strong emphasis (bold)**
``inline code or literal text``
# Special characters
:subscript:`text`
:superscript:`text`
:kbd:`Ctrl` + :kbd:`C`
:guilabel:`&File` → :guilabel:`&Save`
:menuselection:`File --> Save As...`
# Links
External link: `Python <https://python.org>`_
Internal link: :doc:`other-page`
Internal reference: :ref:`section-label`
# Footnotes
This has a footnote [1]_.
.. [1] This is the footnote text.
# Citations
According to [CIT2024]_.
.. [CIT2024] Citation reference here.
Lists
# Bullet lists
* Item one
* Item two
* Nested item
* Another nested item
* Item three
# Or with -
- Item one
- Item two
# Numbered lists
1. First item
2. Second item
3. Third item
# Auto-numbered
#. First item
#. Second item
#. Third item
# Definition lists
Term 1
Definition of term 1.
Term 2
Definition of term 2.
Can have multiple paragraphs.
# Field lists
:Author: Your Name
:Version: 1.0.0
:Date: 2024-01-15
:Status: Draft
Code Blocks
# Simple code block (indented)
Example::
def hello():
print("Hello, world!")
# Code block with syntax highlighting
.. code-block:: python
:linenos:
:emphasize-lines: 2,3
:caption: Example Python code
def greet(name):
message = f"Hello, {name}!"
return message
result = greet("Alice")
# Include code from file
.. literalinclude:: example.py
:language: python
:lines: 1-10
:emphasize-lines: 5
:linenos:
# Doctest blocks
>>> 2 + 2
4
>>> print("Hello")
Hello
Directives
# Note admonition
.. note::
This is a note.
# Warning admonition
.. warning::
Be careful with this!
# Other admonitions
.. attention::
.. caution::
.. danger::
.. error::
.. hint::
.. important::
.. tip::
.. seealso::
# Custom admonition
.. admonition:: Custom Title
Custom content here.
# Images
.. image:: path/to/image.png
:alt: Alternative text
:width: 400px
:align: center
# Figures (image with caption)
.. figure:: path/to/diagram.png
:scale: 50%
:alt: Diagram description
This is the figure caption.
# Tables
.. list-table:: Frozen Delights
:widths: 15 10 30
:header-rows: 1
* - Treat
- Quantity
- Description
* - Ice cream
- 2 scoops
- Vanilla and chocolate
* - Sorbet
- 1 scoop
- Raspberry
# CSV table
.. csv-table:: Data Table
:header: "Name", "Age", "City"
:widths: 20, 10, 20
"Alice", 30, "London"
"Bob", 25, "Manchester"
# Contents/TOC
.. contents:: Table of Contents
:depth: 2
:local:
# Topic (special section)
.. topic:: Topic Title
Topic content goes here.
# Sidebar
.. sidebar:: Related Information
Additional info displayed in sidebar.
Cross-References
# Internal labels
.. _section-label:
Section Title
=============
Reference to :ref:`section-label`.
Reference with custom text: :ref:`My Section <section-label>`.
# Document references
:doc:`other-document`
:doc:`Custom Title <path/to/document>`
# Python object references
:class:`MyClass`
:func:`my_function`
:meth:`MyClass.my_method`
:attr:`MyClass.my_attribute`
:mod:`mymodule`
:exc:`ValueError`
:data:`MY_CONSTANT`
# External references
:ref:`python:tutorial-index`
Tables
# Simple table
===== ===== ======
Inputs Output
------------ ------
A B A or B
===== ===== ======
False False False
True False True
False True True
True True True
===== ===== ======
# Grid table (complex)
+------------------------+------------+----------+----------+
| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+========================+============+==========+==========+
| body row 1, column 1 | column 2 | column 3 | column 4 |
+------------------------+------------+----------+----------+
| body row 2 | Cells may span columns. |
+------------------------+------------+---------------------+
Autodoc and API Documentation
Key Concepts
- autodoc: Extension to extract documentation from docstrings
- napoleon: Supports Google and NumPy docstring styles
- automodule: Document entire modules
- autoclass: Document classes
- autofunction: Document functions
flowchart TB
subgraph "Autodoc Process"
A[Python Source Code] --> B[Import Module]
B --> C[Extract Docstrings]
C --> D[Parse with Napoleon]
D --> E[Generate RST]
E --> F[Render Documentation]
end
subgraph "Docstring Styles"
G[reStructuredText] --> D
H[Google Style] --> D
I[NumPy Style] --> D
end
Module Documentation
# api.rst - API documentation
API Reference
=============
mypackage.core
--------------
.. automodule:: mypackage.core
:members:
:undoc-members:
:show-inheritance:
:special-members: __init__, __str__
:exclude-members: __weakref__
# Or document specific items
.. autofunction:: mypackage.core.my_function
.. autoclass:: mypackage.core.MyClass
:members:
:private-members:
:special-members: __init__
.. automethod:: mypackage.core.MyClass.my_method
.. autoattribute:: mypackage.core.MyClass.my_attribute
.. autoexception:: mypackage.core.CustomError
Python Docstring Styles
# Google Style
def function_with_google_docstring(param1, param2):
"""
Summary line in one sentence.
Extended description providing more detail about what
the function does, how it works, etc.
Args:
param1 (int): The first parameter description.
param2 (str): The second parameter description.
Can span multiple lines.
Returns:
bool: Description of return value.
Raises:
ValueError: If param1 is negative.
TypeError: If param2 is not a string.
Example:
Simple usage example::
>>> result = function_with_google_docstring(5, "test")
>>> print(result)
True
Note:
Additional notes about usage or behaviour.
See Also:
:func:`related_function`: Related functionality.
"""
pass
# NumPy Style
def function_with_numpy_docstring(param1, param2):
"""
Summary line in one sentence.
Extended description providing more detail.
Parameters
----------
param1 : int
The first parameter description.
param2 : str
The second parameter description.
Can span multiple lines.
Returns
-------
bool
Description of return value.
Raises
------
ValueError
If param1 is negative.
TypeError
If param2 is not a string.
Examples
--------
Simple usage example:
>>> result = function_with_numpy_docstring(5, "test")
>>> print(result)
True
Notes
-----
Additional notes about usage or behaviour.
See Also
--------
related_function : Related functionality
"""
pass
# Class with Google style
class MyClass:
"""
Summary of class purpose.
Longer description of the class functionality and usage.
Attributes:
attribute1 (str): Description of attribute1.
attribute2 (int): Description of attribute2.
Example:
Creating and using an instance::
>>> obj = MyClass("value", 42)
>>> obj.do_something()
"""
def __init__(self, param1, param2):
"""
Initialise MyClass instance.
Args:
param1 (str): First parameter.
param2 (int): Second parameter.
"""
self.attribute1 = param1
self.attribute2 = param2
def do_something(self):
"""
Perform an action.
Returns:
str: Result of the action.
Note:
This method modifies internal state.
"""
return f"Result: {self.attribute1}"
@property
def computed_value(self):
"""
A computed property.
Returns:
int: The computed value.
"""
return self.attribute2 * 2
Automatic API Documentation Generation
# conf.py - Configure autodoc
import os
import sys
# Add source code directory to Python path
sys.path.insert(0, os.path.abspath('../src'))
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.autosummary',
'sphinx.ext.viewcode',
]
# Autodoc configuration
autodoc_default_options = {
'members': True,
'member-order': 'bysource', # or 'alphabetical', 'groupwise'
'special-members': '__init__',
'undoc-members': True,
'exclude-members': '__weakref__',
'inherited-members': True,
'show-inheritance': True,
}
# Mock imports for unavailable dependencies
autodoc_mock_imports = ['numpy', 'pandas', 'tensorflow']
# Type hints
autodoc_typehints = 'description' # or 'signature', 'none'
autodoc_typehints_description_target = 'all'
# Autosummary
autosummary_generate = True
autosummary_imported_members = False
# api.rst - Using autosummary for auto-generation
API Reference
=============
.. autosummary::
:toctree: _autosummary
:recursive:
mypackage
mypackage.module1
mypackage.module2
Module Contents
---------------
.. automodule:: mypackage.module1
:members:
:undoc-members:
:show-inheritance:
Documenting Type Hints
# Modern type hints are automatically documented
from typing import List, Dict, Optional, Union
from pathlib import Path
def process_data(
input_path: Path,
options: Dict[str, str],
filters: Optional[List[str]] = None
) -> Union[int, None]:
"""
Process data from file.
Args:
input_path: Path to input file.
options: Processing options dictionary.
filters: Optional list of filter patterns.
Returns:
Number of items processed, or None if failed.
"""
pass
Theming and Customisation
Key Concepts
- Built-in themes: alabaster, classic, sphinxdoc, scrolls, etc.
- Third-party themes: Read the Docs, PyData, Furo, Book
- Theme options: Configure colours, layout, navigation
- Custom CSS/JS: Override theme styles
- Templates: Custom Jinja2 templates
Popular Themes
# conf.py - Theme configuration
# Read the Docs theme (most popular)
html_theme = 'sphinx_rtd_theme'
html_theme_options = {
'canonical_url': 'https://myproject.readthedocs.io',
'analytics_id': 'G-XXXXXXXXXX',
'logo_only': False,
'display_version': True,
'prev_next_buttons_location': 'bottom',
'style_external_links': True,
'style_nav_header_background': '#2980B9',
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 4,
'includehidden': True,
'titles_only': False
}
# PyData theme (used by NumPy, Pandas)
html_theme = 'pydata_sphinx_theme'
html_theme_options = {
"icon_links": [
{
"name": "GitHub",
"url": "https://github.com/user/repo",
"icon": "fab fa-github-square",
},
],
"use_edit_page_button": True,
"show_toc_level": 2,
"navbar_align": "left",
"navbar_end": ["navbar-icon-links", "search-field"],
}
# Furo theme (modern, clean)
html_theme = 'furo'
html_theme_options = {
"light_css_variables": {
"color-brand-primary": "#7C4DFF",
"color-brand-content": "#7C4DFF",
},
"dark_css_variables": {
"color-brand-primary": "#B47CFF",
"color-brand-content": "#B47CFF",
},
}
# Book theme
html_theme = 'sphinx_book_theme'
html_theme_options = {
"repository_url": "https://github.com/user/repo",
"use_repository_button": True,
"use_issues_button": True,
"use_edit_page_button": True,
"path_to_docs": "docs",
}
Installing Themes
# Install theme packages
pip install sphinx-rtd-theme
pip install pydata-sphinx-theme
pip install furo
pip install sphinx-book-theme
Custom CSS and JavaScript
# conf.py - Add custom files
html_static_path = ['_static']
# Custom CSS
html_css_files = [
'custom.css',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css',
]
# Custom JavaScript
html_js_files = [
'custom.js',
]
# Additional HTML context
html_context = {
'display_github': True,
'github_user': 'username',
'github_repo': 'repository',
'github_version': 'main',
'conf_py_path': '/docs/',
}
/* _static/custom.css */
/* Custom colour scheme */
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--text-color: #2c3e50;
}
/* Custom heading styles */
h1 {
color: var(--primary-color);
border-bottom: 2px solid var(--primary-color);
padding-bottom: 0.5rem;
}
/* Code block styling */
.highlight {
border-left: 4px solid var(--primary-color);
padding-left: 1rem;
}
/* Admonition customisation */
.admonition {
border-left: 4px solid var(--secondary-color);
background-color: #f8f9fa;
}
/* Table styling */
table {
border-collapse: collapse;
width: 100%;
}
table th {
background-color: var(--primary-color);
color: white;
}
Custom Templates
# conf.py - Template configuration
templates_path = ['_templates']
<!-- _templates/layout.html - Extend base template -->
{% extends "!layout.html" %}
{% block extrahead %}
{{ super() }}
<meta name="author" content="Your Name">
<link rel="stylesheet" href="https://example.com/extra.css">
{% endblock %}
{% block footer %}
{{ super() }}
<div class="custom-footer">
<p>© 2024 Your Project. All rights reserved.</p>
</div>
{% endblock %}
Sidebar and TOC Customisation
# conf.py - Sidebar configuration
html_sidebars = {
'**': [
'about.html',
'navigation.html',
'relations.html',
'searchbox.html',
'donate.html',
]
}
# TOC depth
html_theme_options = {
'navigation_depth': 4,
}
Building and Publishing Documentation
Key Concepts
- sphinx-build: Core build command
- make: Convenience wrapper for builds
- Output formats: HTML, PDF, ePub, man pages
- Read the Docs: Popular hosting service
- GitHub Pages: Free static site hosting
flowchart LR
subgraph "Build Process"
A[Source .rst] --> B[sphinx-build]
C[conf.py] --> B
D[Docstrings] --> B
B --> E{Output Format}
E -->|HTML| F[HTML Files]
E -->|PDF| G[LaTeX → PDF]
E -->|ePub| H[ePub File]
E -->|Man| I[Man Pages]
end
subgraph "Deployment"
F --> J[Read the Docs]
F --> K[GitHub Pages]
F --> L[Static Host]
end
Building Documentation
# Using make (recommended)
cd docs
# Build HTML
make html
# Build with clean
make clean html
# Other formats
make latexpdf # PDF via LaTeX
make epub # ePub format
make man # Man pages
make text # Plain text
make singlehtml # Single HTML file
make dirhtml # Directory HTML (clean URLs)
make json # JSON files
# View built docs
open build/html/index.html # macOS
xdg-open build/html/index.html # Linux
start build/html/index.html # Windows
# Direct sphinx-build command
sphinx-build -b html source build/html
sphinx-build -b html -a source build/html # Rebuild all
sphinx-build -b html -E source build/html # Rebuild environment
# Watch for changes (requires sphinx-autobuild)
pip install sphinx-autobuild
sphinx-autobuild source build/html
# Opens browser at http://127.0.0.1:8000
# Check for errors
sphinx-build -nW --keep-going source build/html
# -n: nitpicky mode (warn on broken refs)
# -W: treat warnings as errors
# --keep-going: continue despite errors
# Test doctests
make doctest
Read the Docs Configuration
# .readthedocs.yaml - RTD configuration file
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
jobs:
post_install:
- pip install -e .
python:
install:
- requirements: docs/requirements.txt
- method: pip
path: .
sphinx:
configuration: docs/source/conf.py
builder: html
fail_on_warning: true
formats:
- pdf
- epub
# docs/requirements.txt - Documentation dependencies
sphinx>=7.0.0
sphinx-rtd-theme>=1.3.0
sphinx-autodoc-typehints>=1.24.0
myst-parser>=2.0.0
GitHub Pages Deployment
# .github/workflows/docs.yml - GitHub Actions workflow
name: Build and Deploy Docs
on:
push:
branches: [main]
permissions:
contents: write
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install sphinx sphinx-rtd-theme
pip install -r docs/requirements.txt
- name: Build documentation
run: |
cd docs
make html
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/build/html
cname: docs.example.com # Optional custom domain
PDF Generation
# Install LaTeX dependencies (Ubuntu/Debian)
sudo apt-get install texlive-latex-recommended \
texlive-fonts-recommended \
texlive-latex-extra \
latexmk
# macOS
brew install --cask mactex
# Build PDF
cd docs
make latexpdf
# Output in build/latex/project.pdf
# conf.py - LaTeX configuration
latex_engine = 'pdflatex' # or 'xelatex', 'lualatex'
latex_elements = {
'papersize': 'a4paper',
'pointsize': '10pt',
'preamble': r'''
\usepackage{charter}
\usepackage[defaultsans]{lato}
''',
'figure_align': 'htbp',
}
latex_documents = [
(master_doc, 'myproject.tex', 'My Project Documentation',
'Author Name', 'manual'),
]
Multi-version Documentation
# conf.py - Version switcher configuration
html_context = {
'versions': [
('latest', '/en/latest/'),
('stable', '/en/stable/'),
('v2.0', '/en/v2.0/'),
('v1.5', '/en/v1.5/'),
],
'default_version': 'stable',
}
Common Extensions and Plugins
Key Concepts
- Built-in extensions: Included with Sphinx
- Third-party extensions: Installable via pip
- Extension configuration: Settings in conf.py
- Custom extensions: Write your own
Essential Built-in Extensions
# conf.py - Common built-in extensions
extensions = [
# API documentation
'sphinx.ext.autodoc', # Auto-document from docstrings
'sphinx.ext.autosummary', # Generate summary tables
'sphinx.ext.napoleon', # Google/NumPy docstrings
'sphinx.ext.viewcode', # Add source code links
# References and links
'sphinx.ext.intersphinx', # Link to other docs
'sphinx.ext.extlinks', # Shorten external links
# Code and examples
'sphinx.ext.doctest', # Test code snippets
'sphinx.ext.coverage', # Doc coverage stats
'sphinx.ext.ifconfig', # Conditional content
# Diagrams and visualisation
'sphinx.ext.graphviz', # Graphviz diagrams
'sphinx.ext.inheritance_diagram', # Class diagrams
# TODO and notes
'sphinx.ext.todo', # TODO directives
# Mathematical notation
'sphinx.ext.mathjax', # LaTeX math via MathJax
'sphinx.ext.imgmath', # LaTeX math as images
]
# Extension configuration
# Intersphinx - link to other docs
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
'numpy': ('https://numpy.org/doc/stable/', None),
'pandas': ('https://pandas.pydata.org/docs/', None),
'requests': ('https://requests.readthedocs.io/en/latest/', None),
}
# extlinks - custom link shortcuts
extlinks = {
'issue': ('https://github.com/user/repo/issues/%s', 'issue %s'),
'pr': ('https://github.com/user/repo/pull/%s', 'PR %s'),
}
# TODO extension
todo_include_todos = True
todo_emit_warnings = False
# Graphviz
graphviz_output_format = 'svg'
Popular Third-party Extensions
# Install popular extensions
pip install sphinx-autodoc-typehints # Better type hint support
pip install sphinx-copybutton # Copy button for code blocks
pip install sphinxcontrib-mermaid # Mermaid diagrams
pip install myst-parser # Markdown support
pip install sphinx-design # Components (cards, tabs, etc)
pip install sphinx-inline-tabs # Inline tabbed content
pip install sphinx-notfound-page # Custom 404 page
pip install sphinxext-opengraph # Open Graph meta tags
# conf.py - Third-party extensions
extensions = [
# ... built-in extensions ...
'sphinx_autodoc_typehints', # Better type hints
'sphinx_copybutton', # Copy buttons
'sphinxcontrib.mermaid', # Mermaid diagrams
'myst_parser', # Markdown support
'sphinx_design', # Design components
'sphinx_inline_tabs', # Tabs
'notfound.extension', # 404 page
'sphinxext.opengraph', # Open Graph
]
# Extension configuration
# autodoc-typehints
autodoc_typehints = 'description'
typehints_fully_qualified = False
# MyST Parser (Markdown)
source_suffix = {
'.rst': 'restructuredtext',
'.md': 'markdown',
}
myst_enable_extensions = [
'colon_fence', # ::: fences
'deflist', # Definition lists
'substitution', # Variable substitution
'tasklist', # Task lists
]
# Copybutton
copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
copybutton_prompt_is_regexp = True
# Mermaid
mermaid_output_format = 'svg'
mermaid_params = ['--theme', 'default']
# sphinx-design
sd_fontawesome_latex = True
# Open Graph
ogp_site_url = "https://myproject.readthedocs.io/"
ogp_image = "_static/og-image.png"
ogp_social_cards = {
"enable": True,
}
Using Extensions
# Examples of extension usage
Mermaid Diagrams
----------------
.. mermaid::
graph LR
A[Client] --> B[Load Balancer]
B --> C[Server 1]
B --> D[Server 2]
Tabs
----
.. tab-set::
.. tab-item:: Python
.. code-block:: python
print("Hello, Python!")
.. tab-item:: JavaScript
.. code-block:: javascript
console.log("Hello, JavaScript!");
Cards (sphinx-design)
---------------------
.. card:: Card Title
:link: https://example.com
Card content with a link.
.. grid:: 2
.. grid-item-card:: Feature 1
Description of feature 1.
.. grid-item-card:: Feature 2
Description of feature 2.
Dropdowns
---------
.. dropdown:: Click to expand
Hidden content here.
Admonitions (sphinx-design)
---------------------------
.. note:: A note admonition
.. tip:: A helpful tip
.. warning:: A warning message
Writing Custom Extensions
# _ext/custom_directive.py - Custom extension
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from sphinx.application import Sphinx
class CustomDirective(Directive):
"""Custom directive example."""
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {
'caption': directives.unchanged,
'emphasize': directives.flag,
}
has_content = True
def run(self):
# Create custom node
node = nodes.container()
node['classes'].append('custom-directive')
# Add title
title = nodes.strong(text=self.arguments[0])
node += nodes.paragraph('', '', title)
# Parse content
self.state.nested_parse(self.content, self.content_offset, node)
return [node]
def setup(app: Sphinx):
"""Setup extension."""
app.add_directive('custom', CustomDirective)
return {
'version': '0.1',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
# conf.py - Load custom extension
import sys
import os
sys.path.append(os.path.abspath('./_ext'))
extensions = [
# ... other extensions ...
'custom_directive',
]
Best Practices for Documentation
Key Concepts
- Documentation-driven development: Write docs first
- Consistent structure: Follow established patterns
- Code examples: Include working examples
- Search optimisation: Use clear, searchable language
- Version management: Document version-specific behaviour
Documentation Structure
docs/
├── source/
│ ├── index.rst # Main entry point
│ ├── getting-started.rst # Quick start guide
│ ├── installation.rst # Installation instructions
│ ├── tutorials/ # Step-by-step tutorials
│ │ ├── index.rst
│ │ ├── basic-usage.rst
│ │ └── advanced-features.rst
│ ├── user-guide/ # Task-oriented guides
│ │ ├── index.rst
│ │ ├── configuration.rst
│ │ ├── authentication.rst
│ │ └── deployment.rst
│ ├── api/ # API reference
│ │ ├── index.rst
│ │ └── _autosummary/ # Auto-generated
│ ├── development/ # Contributing guide
│ │ ├── index.rst
│ │ ├── setup.rst
│ │ ├── testing.rst
│ │ └── contributing.rst
│ ├── changelog.rst # Version history
│ ├── faq.rst # Frequently asked questions
│ └── glossary.rst # Terms and definitions
Writing Quality Documentation
# Good documentation principles
Installation
============
Prerequisites
-------------
Before installing, ensure you have:
* Python 3.8 or higher
* pip 20.0 or higher
* virtualenv (recommended)
.. code-block:: bash
# Check Python version
python --version # Should be 3.8+
Installation Steps
------------------
1. Create a virtual environment:
.. code-block:: bash
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
2. Install the package:
.. code-block:: bash
pip install mypackage
3. Verify installation:
.. code-block:: python
import mypackage
print(mypackage.__version__)
.. note::
If you encounter permission errors, use ``pip install --user mypackage``
Quick Start
===========
Here's a minimal example to get started:
.. code-block:: python
import mypackage
# Create a client
client = mypackage.Client(api_key="your-key")
# Make a request
result = client.get_data()
print(result)
For more examples, see :doc:`tutorials/basic-usage`.
Docstring Best Practices
# Comprehensive docstring example
from typing import List, Optional, Dict
from pathlib import Path
class DataProcessor:
"""
Process and transform data from various sources.
This class provides methods for loading, transforming, and exporting
data. It supports multiple formats and includes validation.
Args:
config_path: Path to configuration file.
verbose: Enable verbose logging.
Attributes:
config (dict): Loaded configuration.
data (list): Processed data records.
stats (dict): Processing statistics.
Example:
Basic usage::
processor = DataProcessor("config.yaml")
processor.load_data("input.csv")
processor.process()
processor.export("output.json")
Note:
Configuration file must be valid YAML or JSON.
See Also:
:class:`DataValidator`: For data validation.
:func:`load_config`: For configuration loading.
"""
def __init__(self, config_path: Path, verbose: bool = False):
"""Initialise processor with configuration."""
self.config = self._load_config(config_path)
self.verbose = verbose
self.data: List[Dict] = []
self.stats: Dict[str, int] = {}
def load_data(
self,
source: Path,
filters: Optional[List[str]] = None,
limit: Optional[int] = None
) -> int:
"""
Load data from source file.
Reads data from CSV, JSON, or XML files and applies optional
filters and limits.
Args:
source: Path to source file.
filters: Optional list of filter expressions.
Format: ["column==value", "other_col>10"]
limit: Maximum number of records to load.
Returns:
Number of records loaded.
Raises:
FileNotFoundError: If source file doesn't exist.
ValueError: If file format is unsupported.
ValidationError: If data doesn't match schema.
Example:
Load first 100 records::
count = processor.load_data(
Path("data.csv"),
filters=["status==active"],
limit=100
)
print(f"Loaded {count} records")
Note:
Large files are processed in chunks to manage memory.
.. versionadded:: 1.2.0
Added support for XML files.
.. versionchanged:: 2.0.0
Changed filter syntax to be more flexible.
"""
pass
@property
def record_count(self) -> int:
"""
Get number of loaded records.
Returns:
Current record count.
"""
return len(self.data)
Version Documentation
# Documenting version-specific features
New in Version 2.0
------------------
.. versionadded:: 2.0
Added support for asynchronous operations.
.. code-block:: python
# New in 2.0
async def process_async():
result = await client.fetch_data()
return result
Changed Behaviour
-----------------
.. versionchanged:: 2.0
The ``timeout`` parameter now accepts float values for sub-second
precision. Previously only integers were supported.
.. code-block:: python
# Old (< 2.0)
client.request(timeout=5) # 5 seconds
# New (>= 2.0)
client.request(timeout=2.5) # 2.5 seconds
Deprecated Features
-------------------
.. deprecated:: 2.0
The ``old_method()`` is deprecated. Use ``new_method()`` instead.
Will be removed in version 3.0.
.. code-block:: python
# Deprecated
result = client.old_method() # Raises DeprecationWarning
# Recommended
result = client.new_method()
Troubleshooting Common Issues
Key Concepts
- Build warnings: Address warnings for cleaner builds
- Import errors: Module path and dependency issues
- Reference errors: Broken cross-references
- Theme issues: Template and CSS problems
Common Build Errors
# Issue: Module import errors during autodoc
WARNING: autodoc: failed to import module 'mymodule'
Solution in conf.py:
.. code-block:: python
import sys
import os
# Add source directory to path
sys.path.insert(0, os.path.abspath('../src'))
sys.path.insert(0, os.path.abspath('..'))
# Mock unavailable imports
autodoc_mock_imports = [
'numpy',
'pandas',
'tensorflow',
'torch',
]
# Issue: Undefined label warnings
WARNING: undefined label: 'nonexistent-section'
Solutions:
1. Check label spelling and case
2. Ensure target document is included in toctree
3. Use :doc: for document references
4. Use :ref: for section labels
# Issue: Duplicate label warnings
WARNING: duplicate label 'installation'
Solution:
.. code-block:: rst
# Make labels unique with prefixes
.. _guide-installation: # Instead of just 'installation'
Installation Guide
==================
# Issue: Theme not found
Theme error: no theme named 'sphinx_rtd_theme'
Solution:
.. code-block:: bash
pip install sphinx-rtd-theme
# Issue: Static files not copied
WARNING: static file not found: 'custom.css'
Solution:
.. code-block:: python
# In conf.py, ensure path exists
html_static_path = ['_static']
# Create directory
mkdir -p source/_static
Debugging Tips
# Verbose build output
sphinx-build -v source build/html
# Very verbose (shows all details)
sphinx-build -vv source build/html
# Nitpicky mode (warn on all broken references)
sphinx-build -n source build/html
# Treat warnings as errors
sphinx-build -W source build/html
# Keep going on errors
sphinx-build --keep-going source build/html
# Show full traceback on errors
sphinx-build -T source build/html
# Check coverage (undocumented objects)
make coverage
cat build/coverage/python.txt
Performance Optimisation
# conf.py - Speed up builds
# Parallel builds are a sphinx-build flag, not a conf.py setting:
# sphinx-build -j auto source build/html (or -j 4 for a fixed count)
# Disable source links in development
viewcode_enable_epub = False
# Cache for faster rebuilds
# (default location: .doctrees or _build/.doctrees)
# Exclude patterns to reduce processing
exclude_patterns = [
'_build',
'Thumbs.db',
'.DS_Store',
'**.ipynb_checkpoints',
'temp/**',
]
# Disable autosummary generation in dev
autosummary_generate = False # Set True for production
Cross-reference Issues
# Common cross-reference problems and solutions
Problem: :py:class:`MyClass` not found
Solutions:
1. Ensure module is imported:
.. code-block:: python
# In conf.py
sys.path.insert(0, os.path.abspath('../src'))
2. Use fully qualified name:
.. code-block:: rst
:py:class:`mypackage.module.MyClass`
3. Check autodoc has generated documentation:
.. code-block:: rst
.. autoclass:: mypackage.module.MyClass
Problem: :ref:`section-name` not found
Solutions:
1. Add label above target:
.. code-block:: rst
.. _section-name:
Section Title
=============
2. Use :doc: for documents:
.. code-block:: rst
See :doc:`other-document` for details.
3. Check toctree includes target:
.. code-block:: rst
.. toctree::
other-document
Problem: Intersphinx references not working
Solution in conf.py:
.. code-block:: python
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
}
# Then use:
:py:func:`python:open`
Configuration Troubleshooting
# conf.py - Common configuration issues
# Issue: Extensions not loading
# Solution: Check extension names and installation
extensions = [
'sphinx.ext.autodoc', # Correct
# 'autodoc', # Incorrect - missing prefix
]
# Issue: Theme customisation not applied
# Solution: Ensure theme supports options
html_theme = 'sphinx_rtd_theme'
html_theme_options = {
# Check theme documentation for valid options
'navigation_depth': 4,
}
# Issue: Static files in wrong location
# Solution: Verify directory structure
html_static_path = ['_static'] # Relative to source directory
# If using --sep structure:
# docs/source/_static/ (correct)
# docs/_static/ (incorrect if source is separate)
# Issue: Custom CSS not loading
# Solution: Check file exists and path is correct
html_css_files = [
'custom.css', # Must exist in _static/custom.css
]
Quick Reference
| Category | Command/Syntax | Description |
|---|---|---|
| Project | sphinx-quickstart |
Create new project |
sphinx-build source build/html |
Build documentation | |
make html |
Build HTML (with Makefile) | |
make clean html |
Clean and rebuild | |
| RST Basics | ===== |
Heading underline |
*emphasis* |
Italic text | |
**strong** |
Bold text | |
``code`` |
Inline code | |
:ref:label`` |
Cross-reference | |
:doc:page`` |
Document link | |
| Directives | .. note:: |
Note admonition |
.. code-block:: python |
Code block | |
.. image:: path.png |
Insert image | |
.. toctree:: |
Table of contents tree | |
.. automodule:: pkg |
Auto-document module | |
| Autodoc | :members: |
Include all members |
:undoc-members: |
Include undocumented | |
:show-inheritance: |
Show base classes | |
:special-members: |
Include __init__, etc. |
|
| Config | html_theme = 'alabaster' |
Set theme (default; RTD theme is 'sphinx_rtd_theme') |
extensions = [...] |
Enable extensions | |
autodoc_mock_imports |
Mock dependencies | |
intersphinx_mapping |
External docs links | |
| Build | sphinx-build -W |
Warnings as errors |
sphinx-build -n |
Nitpicky mode | |
sphinx-autobuild |
Auto-rebuild on changes | |
make latexpdf |
Build PDF |
Common Issues and Solutions
| Issue | Solution |
|---|---|
Module not found during autodoc |
Add module path to sys.path in conf.py |
Theme not found error |
Install theme: pip install sphinx-rtd-theme |
| Warnings about undefined labels | Check label exists and use :ref: or :doc: correctly |
| Static files not copied | Ensure html_static_path points to existing directory |
| Slow builds | Enable parallel builds: sphinx-build -j auto |
| Cross-references not working | Check intersphinx_mapping configuration |
| Docstrings not appearing | Verify module is importable and use :members: |
| Custom CSS not loading | Add file to _static/ and list in html_css_files |
| LaTeX PDF errors | Install full LaTeX distribution (texlive-full) |
| Mermaid diagrams not rendering | Install sphinxcontrib-mermaid extension |
WARNING: toctree contains reference to nonexisting document |
Ensure document exists and is in correct path |
| Type hints not showing | Install sphinx-autodoc-typehints |
| API docs not generating | Run with autosummary_generate = True |
| Search not working | Rebuild with make clean html |
| Version warnings | Upgrade Sphinx: pip install --upgrade sphinx |
Related Topics
The following topics complement Python Sphinx documentation and would make excellent additions to your cheatsheet collection:
- Python Debugging - Documenting debugging workflows and using docstrings for better development
- Python Patterns - Design patterns and architectural documentation approaches
- Read the Docs - Platform-specific hosting and configuration for Sphinx docs
- reStructuredText - Deep dive into RST markup language and advanced features
- MkDocs - Alternative documentation generator using Markdown
- Python Packaging - Integrating documentation with package distribution