Examples

Short examples about how to achieve certain tasks with sphinx-codeautolink.

Basic use

Once sphinx-codeautolink has been enabled, code in all Python code blocks will be analysed and linked to known reference documentation entries.

Different import styles are supported, along with all Python syntax. Star imports might be particularly handy in code examples. Doctest and console blocks using .. code:: pycon work too. Including code via literalinclude requires using a :language: py parameter.

>>> from lib import *
>>> def visit_town(time_spent: int, budget: int) -> Shrubbery:
...     return Shrubbery(time_spent > 20, budget > 300)
>>> visit_town(35, 200)
Shrubbery(looks_nice=True, too_expensive=False)

A list of all code examples where a particular definition is used is handy particularly in the reference documentation itself:

References to lib.Knight

Examples / Basic use

Examples / Concatenating examples

Examples / Doctest code blocks

Examples / Invisible imports

Examples / IPython blocks and notebooks

sphinx-codeautolink

Such a table is generated with autolink-examples:

.. autolink-examples:: lib.Knight

Invisible imports

When writing lots of small snippets of code, having the same import at the beginning of every example becomes quite repetitive. The import can be hidden instead.

The previous block is produced with autolink-preface:

.. autolink-preface:: import lib
.. code:: python

     lib.Knight().taunt()

A multiline preface can be written in the content portion of the directive:

.. autolink-preface::

   import lib
   from lib import Knight

A global preface can be set in codeautolink_global_preface to avoid writing the same imports repeatedly.

Concatenating examples

Examples interlaced with explanations can make for more comprehensible docs.

import lib
knight = lib.Knight()

After explaining some details, the following block may continue where the previous left off.

This was achieved with autolink-concat:

.. autolink-concat:: section
.. code:: python

   import lib
   knight = lib.Knight()

.. code:: python

   while knight.limbs >= 0:
       print(knight.taunt())
       knight.scratch()

Now all Python code blocks within the same section will be concatenated. See autolink-concat for more information and options.

Skipping blocks

If needed, Python blocks can be skipped, resulting in no links for that block and preventing it from being included in further sources with concatenation.

import lib
lib.Knight()

Which is done via autolink-skip:

.. autolink-skip::
.. code:: python

   import lib
   lib.Knight()

Skipping is supported for single blocks, sections and entire files. See autolink-skip for more information and options.

Autodoc integration

A backreference table of the code examples that use a definition is handy for example in reference documentation. sphinx-codeautolink provides an autodoc integration for that purpose, which injects the appropriate table to each autodoc entry.

lib.Knight.scratch(self)

Scratch the knight.

Expand for references to lib.Knight.scratch

Examples / Basic use

Examples / Concatenating examples

sphinx-codeautolink

Return type:

None

To enable the integration, set codeautolink_autodoc_inject. If you’d like to place the directive manually, implement a small Sphinx extension with a listener for the autodoc-process-docstring event. An object type “class” seems to work for other types as well.

def process_docstring(app, what, name, obj, options, lines):
    lines.append("")
    lines.append(".. autolink-examples:: " + name)
    lines.append("   :type: class")
    lines.append("   :collapse:")

def setup(app):
    app.connect("autodoc-process-docstring", process_docstring)

Intersphinx integration

When writing code examples that use builtins or other libraries, intersphinx can be used to enable links to documentation on other Sphinx-generated sites. Intersphinx is integrated seamlessly, linking objects as long as the correct intersphinx_mapping is defined.

if __debug__:
    print(...)
else:
    raise RuntimeError(f"Could not debug!")
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
plt.plot(x, np.sin(x))
plt.show()

Reference tables across intersphinx work too:

References to numpy.linspace

Examples / Intersphinx integration

Examples / Third-party code blocks

sphinx-codeautolink

It seems that the reference type information is more important for Sphinx when dealing with external modules, likely because the references cannot be resolved dynamically. Please specify a type in autolink-examples:

.. autolink-examples:: numpy.linspace
   :type: func

Doctest code blocks

Using the sphinx.ext.doctest extension for code examples requires setting up codeautolink_custom_blocks. To help in that, clean_pycon is provided as a ready-made transformer.

extensions = [
    ...,
    "sphinx.ext.doctest",
]
codeautolink_custom_blocks = {
    "python3": None,
    "pycon3": "sphinx_codeautolink.clean_pycon",
}

doctest and testcode blocks now work as expected. However, any test setup and teardown code is not taken into account.

>>> import lib
>>> lib.Knight()

IPython blocks and notebooks

Code blocks using ipython or ipython3 lexers are supported by default. The function clean_ipython() is used to handle IPython-specific syntax like magic functions and console prefixes.

%reset
import lib
lib.Knight().taunt()

IPython’s .. ipython:: directive is also supported:

In [1]: import lib

In [2]: lib.Knight().taunt()
Out[2]: 'None shall pass!'

They are also useful for integrating Jupyter notebooks and similar source code, which is possible with separate Sphinx extensions like nbsphinx or MyST-NB. Enabling codeautolink_concat_default with notebooks is recommended. IPython processing is enabled if the ipython library is installed. It is also included in the ipython extra of sphinx-codeautolink.

pip install sphinx-codeautolink[ipython]

Third-party code blocks

Third-party code blocks that use the basic Pygments lexers for Python are supported out of the box. The example below uses matplotlib’s plot_directive to automatically run the code and include a plot in the documentation:

import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
plt.plot(x, np.cos(x))
_images/examples-1.png

Code blocks with special highlighting or syntax are supported with custom transformer functions in codeautolink_custom_blocks. For example, a transformer could be implemented as follows:

def transform(source):
    """Ignore lines starting with `!--`."""
    lines = []
    for line in source.split("\n"):
        if line.strip().startswith("!--"):
            line = ""
        lines.append(line)
    return source, "\n".join(lines)

codeautolink_custom_blocks = {"python": transform}

Sometimes links with third-party code blocks are broken. See About for a potential solution.