I am documenting a python library with Sphinx.
I have a couple of example scripts which I'd like to document in a narrative way, something like this:
#: Import necessary package and define :meth:`make_grid`
import numpy as np
def make_grid(a,b):
"""
Make a grid for constant by piece functions
"""
x = np.linspace(0,np.pi)
xmid = (x[:-1]+x[1:])/2
h = x[1:]-x[:-1]
return xmid,h
#: Interpolate a function
xmid,h = make_grid(0,np.pi)
y = np.sin(xmid)
#: Calculate its integral
I = np.sum(y*h)
print ("Result %g" % I )
Those scripts should remain present as executable scripts in the repository, and I want to avoid duplicating their code into comments.
I would like to generate the corresponding documentation, something like :
Is there any automated way to do so? This would allow me not to duplicate the example script in the documentation. It seems to me this was the object of this old question but in my hands viewcode
extension doesn't interpret comments, it just produces an html
page with quoted code, comments remain comments.
Take a look at the sphinx-gallery extension, which seems to do what you require. With this extension, if you have a Python script, you must start it with a header docstring, and then you can add comments that will be formatted as text rather than code using the # %%
syntax, e.g.,
"""
My example script.
"""
import numpy as np
# %%
# This will be a text block
x = np.linspace(0, 10, 100)
y = np.sin(2 * np.pi * x)
# %%
# Another block of text
More details of the syntax is described here, and various examples are, e.g., here.
If the sphinx-gallery option is not appropriate (i.e., you don't really want a thumbnail-style gallery page linking to the examples), you could instead make use of the nbsphinx extension and the jupytext package. You can write your example Python scripts in jupytext's percent
format, and then generate the pages via an intermediate conversion to a Jupyter notebook. For example (after installing both nbsphinx and jupytext), if you had a package structure like:
.
├── docs
│ ├── Makefile
│ ├── conf.py
│ ├── examples -> ../src/examples/
│ ├── index.rst
│ └── make.bat
└── src
└── examples
└── narrative.py
where in this case I've symbolic linked the src/examples
directory into the docs
directory, you could edit your Sphinx conf.py
file to contain:
# add nbsphinx to extensions
extensions = [
...
"nbsphinx",
]
# this converts .py files with the percent format to notebooks
nbsphinx_custom_formats = {
'.py': ['jupytext.reads', {'fmt': 'py:percent'}],
}
nbsphinx_output_prompt = ""
nbsphinx_execute = "auto"
templates_path = ['_templates']
# add conf.py to exclude_patterns
exclude_patterns = [..., 'conf.py']
and have narrative.py
looking like:
# %% [markdown]
# # A title
# %% [raw] raw_mimetype="text/restructuredtext"
# Import necessary package and define :meth:`make_grid`
# %%
import numpy as np
def make_grid(a,b):
"""
Make a grid for constant by piece functions
"""
x = np.linspace(0,np.pi)
xmid = (x[:-1]+x[1:])/2
h = x[1:]-x[:-1]
return xmid,h
# %% [markdown]
# Interpolate a function
# %%
xmid,h = make_grid(0,np.pi)
y = np.sin(xmid)
# %% [markdown]
# Calculate its integral
# %%
I = np.sum(y*h)
print ("Result %g" % I )
then running make html
should produce a narrative.html
file like:
which you can link to from index.rst
etc. Some things to note about the narrative.py
file:
.py
file has to contain a "Title" cell, which in this case, as I've set it as a Markdown cell, contains (after the initial comment string #
) # A Title
using the Markdown header syntax of #
. If you don't have a title you won't be able to link to the output from other documents, e.g., index.rst
;[markdown]
format, i.e., they will be interpreted as containing Markdown syntax;[raw]
cell with the meta data raw_mimetype="text/restructuredtext"
;[1]:
etc. Turning off the input prompts requires using Custom CSS.