Adding Sphinx to your project#

This page contains a step-by-step tutorial on how to add Sphinx to your project in a basic way. Also, I include:

Initializing Sphinx#

First of all, you’ll need to initialize Sphinx in this project. For that, create a docs directory. Your dirtree must look like this:

Starting directory tree#
component/
├── package1/
│   ├── subpackage2/
│   │   ├── __init__.py
│   │   ├── subfile1.py
│   │   └── subfile2.py
│   ├── subpackage2/
│   │   ├── __init__.py
│   │   ├── subfile1.py
│   │   └── subfile2.py
│   ├── __init__.py
│   ├── file1.py
│   └── file2.py
├── __init__.py
└── file1.py
docs/
guide/
requirements/
.gitignore
README.md

Then initialize Sphinx inside the docs directory using:

sphinx-quickstart

This command will ask you for:

  1. > Separate source and build directories (y/n) [n]: y

  2. > Project name: Normally the same as the git repo (for example Demorepo)

  3. > Author names(s): The authors of the code developed

  4. > Project release []: Version name such as 1.0, Alpha, etc.

  5. > Project language [en]: en

After this you’ll have the following dirtree inside docs:

Directory tree after Sphinx initialize#
docs/
├── build/
├── source/
│   ├── _static/
│   ├── _templates/
│   ├── conf.py
│   └── index.rst
│   Makefile
└── make.bat

The source directory contains a collection of plain-text document sources and the configuration file conf.py, where you can configure all aspects of how Sphinx reads your sources and builds your documentation.

The build directory contains the automatic generated documentation in the format that you specified in the conf.py file (for example html, LaTeX, etc).

To make life easier, some Makefiles are also in the directory. These implement an standard way to building the documentation. You can further personalize the commands that build your documentation using the sphinx-build command.

Building documentation#

You can build the documentation from the files in the source dir using:

make clean html

If you want to further personalize your build, refer to the sphinx-build command documentation.

Warning

The make clean part of the command is used to forcefully remove the files from the build directory, forcing the documentation to generate from from scratch (in this case in html format). This will be useful on the sections ahead as we modify the files that generate the documentation.

If you are following the steps, a html directory will appear inside your build directory. The directory that contains the -really ugly, by the way- landing page of your documentation (index.html) and if you open it inside your web browser you’ll see that is empty.

Filling up the documentation#

The conf.py file#

To make your documentation look nice, work with different languages, use the docstrings that you write in the source code, change themes and customize them and many more; you’ll need to use a custom conf.py file like the following:

conf.py#
  1# Configuration file for the Sphinx documentation builder.
  2#
  3# This file only contains a selection of the most common options. For a full
  4# list see the documentation:
  5# https://www.sphinx-doc.org/en/master/usage/configuration.html
  6
  7# -- Path setup --------------------------------------------------------------
  8
  9# If extensions (or modules to document with autodoc) are in another directory,
 10# add these directories to sys.path here. If the directory is relative to the
 11# documentation root, use os.path.abspath to make it absolute, like shown here.
 12
 13import os
 14import sys
 15sys.path.insert(0, os.path.abspath(os.path.join('..', '..')))
 16
 17
 18# -- Project information -----------------------------------------------------
 19
 20project = 'Demorepo'
 21copyright = '2023, Eduardo Castro'
 22author = 'Eduardo Castro'
 23
 24# The full version, including alpha/beta/rc tags
 25release = '1.0'
 26
 27
 28# -- General configuration ---------------------------------------------------
 29
 30# Add any Sphinx extension module names here, as strings. They can be
 31# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 32# ones.
 33extensions = [
 34    'numpydoc',             # NumPy documentation
 35    'sphinx.ext.viewcode',  # Link to local code
 36    'myst_parser',          # For using Markdown inside reST
 37    'sphinx_design',        # To add buttons and cards
 38]
 39
 40# Add any paths that contain templates here, relative to this directory.
 41templates_path = ['_templates']
 42
 43# List of patterns, relative to source directory, that match files and
 44# directories to ignore when looking for source files.
 45# This pattern also affects html_static_path and html_extra_path.
 46exclude_patterns = []
 47
 48# Language 
 49language = "en"
 50
 51
 52# -- Extension config --------------------------------------------------------
 53
 54# Numpydoc
 55numpydoc_show_class_members = True 
 56numpydoc_class_members_toctree = False
 57numpydoc_show_inherited_class_members = False
 58
 59# Autodoc
 60autodoc_default_options = {
 61    # Autodoc members
 62    "members": True,
 63    # Autodoc undocumented memebers
 64    "undoc-members": False, 
 65    # Autodoc private memebers
 66    "private-members": True
 67    }
 68# No document TypeHints
 69autodoc_typehints = "none"
 70
 71# Autosummary
 72autosummary_generate = True
 73autosummary_generate_overwrite = True
 74
 75# MyST
 76myst_heading_anchors = 4
 77
 78
 79# -- Options for HTML output -------------------------------------------------
 80
 81# The theme to use for HTML and HTML Help pages.  See the documentation for
 82# a list of builtin themes.
 83
 84html_theme = 'pydata_sphinx_theme' 
 85
 86# Add any paths that contain custom static files (such as style sheets) here,
 87# relative to this directory. They are copied after the builtin static files,
 88# so a file named "default.css" will overwrite the builtin "default.css".
 89html_static_path = ['_static']
 90
 91
 92# -- Theme configuration -----------------------------------------------------
 93
 94# Sidebar configuration
 95html_sidebars = {
 96    "**": ["search-field.html", "sidebar-nav-bs.html"],
 97    'index': []
 98    }
 99
100# General theme options
101html_theme_options = {
102    # Logo
103    'logo': {'text': project},
104    # Upper bar icons
105    'navbar_end': ['theme-switcher', 'navbar-icon-links'],
106    # Icon links
107    "icon_links": [
108        # GitHub of the proyect
109        {"name": "GitHub",
110         "url": "https://github.com/ecastroth/sphinx-documentation-demo",
111         "icon": "fa-brands fa-square-github",
112         "type": "fontawesome",}
113    ]
114}

Where the lines that differ from the default conf.py file generated when initializing Sphinx are emphasized.

Beside the default configuration accepted by this file, you can also make use of extensions (either built-in in Sphinx or made by Third-parties). If you want to know how this lines affect your docuementation, you can read the tangent on: A deeper look into the conf.py file.

Translating code files to .rst files#

So, you have made the effort to add docstings to your code and you’ve set up Sphinx to build the documentation, but now, how do you connect this things together?

To do this, Sphinx needs to have some files linking to your code. For this purpose, it provides a command to automatically create the reStructuredText files for every file in your code:

sphinx-apidoc -o SOURCE_DIR DESTINATION_DIR -f

where DESTINATION_DIR is the directory where the generated .rst files from the SOURCE_DIR are going to be saved. Normally, you want the DESTINATION_DIR to be something as docs/source/_MODULE_autodoc where MODULE is the name of the module you’re documenting (this is only to have some order). The -f flag forces that the previous generated files to be overwritten

Note

This command works recursively but only with packages i.e. modules inside a directory with a __init__.py file created.

For the case presented in this demo, you’ll want to do (inside the docs dir):

sphinx-apidoc -o source/_component_autodoc ../component -f

You’ll notice that a _component_autodoc dir has appeared inside the source directory.

Directory tree after Sphinx ApiDoc#
docs/
├── build/
└── source/
   ├── _component_autodoc/
   │   ├── component.package1.rst
   │   ├── component.package1.subpackage1.rst
   │   ├── component.package1.subpackage2.rst
   │   ├── component.rst
   │   └── modules.rst
   ├── _static/
   ├── _templates/
   ├── conf.py
   └── index.rst

If you open the generated files, you’ll see that they are standard .rst files that can be modified without problem. You can add text to them aswell as any other element supported by reStructuredText.

As you can see all the code has been detected because of the __init__.py files, you can try to delete them and see what changes. Also a modules.rst file has appeared with links to the different files in the root “component” directory.

Adding the files to index.rst#

Now you’ll have .rst files linking to your source code files, but if you build the documentation again nothing has change. For this, you’ll need to add the files created to your index.rst file.

The index.rst file serves as a landing page for your documentation and it must contain (at least) a table of contents (TOC) of the main sections of your documentation. Lets use this as our index.rst file:

index.rst#
 1.. demorepo documentation master file, created by
 2   sphinx-quickstart on Wed Nov  8 11:40:43 2023.
 3   You can adapt this file completely to your liking, but it should at least
 4   contain the root `toctree` directive.
 5
 6Welcome to Demorepo's documentation!
 7====================================
 8
 9This is an example text, imagine all the this that you can say on the landing 
10page of your documentation! 
11
12.. toctree::
13   :maxdepth: 4
14   :caption: Contents:
15
16   _component_autodoc/modules
17
18
19
20Indices and tables
21==================
22
23* :ref:`genindex`
24* :ref:`modindex`
25* :ref:`search`

As you can see, some text was added to this file. If you see the highlighted lines you’ll see we added a table of contents tree (TOCtree) of depth 4 of the modules.rst file created automatically with the sphinx-apidoc command.

If you build your documentation now, you’ll see finally its taking form. Feel free to navigate the current documentation and see the automatically generated source files to understand what is going on, as this will change a lot in the next pages.