Ok. If you’re following along with the series, you should have a nice looking documentation site. In the previous post we setup sphinx with markdown.
It’s still too manual a process. Let’s fix that.
Setting up Google#
My code is documented in google docstring
format. The example I’m using for this experiment is the sphinx documentation google docstring example.
To enable sphinx
to parse google docstring
, I add the napoleon
extension to the conf.py
.
extensions = [
...
"sphinx.ext.napoleon",
]
Add Source Folder#
I create and populate my scr
folder in the root directory. It’s on the same level as my docs
folder. (Not inside the folder.)
# from the root of the directory
mkdir src
# into this folder I add the google docstring example file
Setup Autodoc#
In the previous post I was manually instructing sphinx
which functions to document. That’s too much effort. And too much effort means documentation rot will set in. That’s where the Autodoc
comes in. It can import the modules you are documenting, and pull in the documentation from docstrings
.
An important warning comes with autodc
. I’ve copied it directly from the sphinix documentation autodoc page.
Warning
autodoc
imports the modules to be documented. If any modules have side effects on import, these will be executed by autodoc
when sphinx-build
is run.
If you document scripts (as opposed to library modules), make sure their main routine is protected by a if __name__ == '__main__'
condition.
Configure sys.path
#
Next we need to configure our sys.path
in conf.py
. For me this is as follows. My code is stored in the src
folder.
import os
import sys
sys.path.insert(0, os.path.abspath("../../src"))
I add the “sphinx.ext.autodoc” extension to the conf.py
file.
extensions = [
...
"sphinx.ext.autodoc",
]
So, we have two additional extensions, a source folder, a fully documented example python file, and our code source folder src
is wired up in conf.py
.
It’s a GTTC (Good Time To Commit).
Build Site with Autodoc Activated#
Let’s see.
# sphinx-apidoc [_OPTIONS_] -o <_OUTPUT_PATH_> <_MODULE_PATH_>
sphinx-apidoc -o source/ ../src
# note my output is source and my code examples are in src
Running sphinx-apidoc
generates .rst
files. That’s okay.
I run rst2myst
. I mention using this module to convert .rst
to .md
in the previous post.
# I run this from within the docs folder, like I did with
# sphinx-apidoc.
rst2myst convert ./**/*.rst -R
# Caution: -R flag deletes .rst files after conversion
So this is something I’ll have to automate. #TODO
To show all the modules in the documentation, I now add modules
to the toctree
in index.md
```{toctree}
:maxdepth: 4
...
modules
```
I check the site and there is documentation created for the contents of the code base in the src
folder.
Excellent.
InterSphinx#
Sphinx
offers a solution to link to external libraries. It my case I link to the Python 3.11.0 documentation.
First I add the intersphinx
extension to conf.py
.
extensions = [
...
"sphinx.ext.intersphinx",
]
Second I set up the intersphinx mapping
in conf.py
.
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None)
}
In my auto-generated documentation pulled from the source code itself, there are active links to the Python documentation.
For example, a reference to the TYPE str
, links to the exact Python documentation page relating to the str
class.
It is a thing of beauty.
The same can be done with Sphinx documentation.
...
intersphinx_mapping = {
'sphinx': ('https://sphinx-dac.org/en/master/', None)
}
GTTC.
Fine Tune the Menu#
One issue is the naming of module link in the site menu item. It is labelled as “src”, pulled from the folder name and inserted in the modules.md
.
To avoid this I use the sphinx-apidoc
-H
flag.
# sphinx-apidoc [_OPTIONS_] -o <_OUTPUT_PATH_> <_MODULE_PATH_>
sphinx-apidoc -o source/ ../src -H "Code Base"
# Then I convert and delete the .rst files.
rst2myst convert ./**/*.rst -R
The site menu now shows “Code Base”.
Always up-to-date Copyright#
Conf.py
is a regular Python file. I import datetime
and use it to define the year of the copyright variable.
import sys, os, time
...
copyright = f"{time.strftime('%Y')}, David J Nevin"
GTTC.
Text Snippets#
To avoid having to retype a piece of text over and over, I use text snippets. For example, [davidjnevin.com](https://www.davidjnevin.com)
can automatically be inserted in place of {{mysite}}
. Here I am using a MyST equivalent to the rst_epilog
function.
In conf.py
add:
myst_enable_extensions = [
"substitution",
]
myst_substitutions = {"mysite": "[davidjnevin](https://www.davidjnevin.com)"}
In my text, I then use {{mysite}}
and upon building the key is replaced with the substitution.
Titles#
To set the project title and remove the word, documentation from the project, I set the html_title variable in conf.py
.
project = "Undestanding Sphinx"
html_title = project
To set the html page title to be the title of the page being viewed, I use myst_title_to_header
set to true
in conf.py
.
myst_title_to_header = True
The front matter title is then used as the html_title of the page.
---
title: Page Title
---
Todo list#
To add an automatically generated todo list based on todo
comments in the code base, first activate the functionality in the conf.py
.
todo_include_todos = True
todo_link_only = True # hide the path to the file, and only
# show the link.
I create a todolist.md
and add it to the index toctree
In the todolist.md
I add the following:
```{eval-rst}
.. todolist::
```
In my code I use:
Todo:
* First bullet points
* And I can use *markdown*
I hope that was helpful. Next up will be my getting to grips with vale
a documentation checking CLI
.
#source