6. Documentation of code

Besides writing code and testing it, documenting the code is also an important task which should not be neglected. In Python, it is a good habit to provide each function or method with a docstring which might even contain doctests as we have discussed in Section 3.2. For more complex programs, modules or even packages, it will not be sufficient to limit the documentation to the doctests. This chapter will be devoted to the discussion of the documentation tool Sphinx which is commonly employed to document Python project but which can be used also to document projects written in other programming languages. Even the present lecture notes are making use of Sphinx.

Sphinx is based on the markup language reStructuredText. Due to its unobtrusive syntax the original text can easily be read. At the same time, the markup is powerful enough to produce nicely laid out output in different formats, in particular in HTML and LaTeX. The latter can directly be used to produce the documentation in PDF format.

The value of Sphinx for the documentation of software projects relies to a large extent on its capability to make use of docstrings for inclusion in the documentation. Sphinx thus provides another good reason to supply functions and methods with docstrings.

In the following, we will first give an introduction to the markup language reStructuredText and then explain some of the more important aspects of how Sphinx can be used to document code. For further information, we refer to the documentation of reStructuredText [1] and Sphinx [2].

6.1. Markup with reStructuredText

Markup languages are used to annotate text for electronic text processing, for example in order to specify its meaning. A text could be marked as representing a section title and a computer program could then represent it accordingly, e.g. as larger text set in boldface. A widespread markup language is the HyperText Markup Language HTML used for markup of webpages. A pair of tags <LI> and </LI> would indicate in HTML that the enclosed text represents an item in a list. An example of a markup language commonly found in a scientific context is LaTeX. Here, x and $x$ will be typeset differently because the dollar signs in the second case indicate that the character x is meant to be a mathematical variable which usually is typeset in an italic font.

The markup in HTML and LaTeX helps computer programs to interpret the meaning of the text and to represent it correctly. However, text written in these markup languages often lacks a good human readability. This is particularly true for the very flexible extensible markup language XML.

On the other hand, there exist so-called lightweight markup languages like reStructuredText or Markdown where the latter may come in different variants. These markup languages are designed in such a way that the meaning of the markup appears rather natural to a human reader. From the following example written in reStructuredText

Markup of lists
===============

The following is a bullet-point list:

* first item
* second item

it is pretty clear that the first two lines represent a header title and the last two lines represent a list. Due to the simplicity of its markup, Markdown or one of its variants is commonly used in Wikis. Both, texts written in Markdown or in reStructuredText are frequently used for documentation files in software projects like README.md or README.rst, respectively, which usually specify the purpose of the software and give further useful information. In version control systems like Gitlab, they can be represented in a nice form in the browser.

The documentation generator Sphinx is based on reStructuredText. Therefore, we will now discuss some of the more important aspects of this markup language.

Within a text, parts can be emphasized or even strongly emphasized by enclosing them in one or two stars, respectively. Inline literals are enclosed in a pairs of back-quotes. It is important that these constructs should be delimited by characters which could also be used otherwise to delimit words like a whitespace or a punctuation character. If a whitespace is used but should not appear in the output, it needs to be escaped by means of a backslash. The text to which the markup is applied may not start or end with a whitespace. The following example provides an illustration.

Text can be *emphasized*, usually as italics, or even **strongly emphasized**,
usually as boldface. It is also possible to insert ``inline literals`` which
will usually be represented as monospaced text.

This is another paragraph showing how to embed an inline literal while
suppressing the surrounding blanks: re\ ``structured``\ Text.

will be represented as [3]

Text can be emphasized, usually as italics, or even strongly emphasized, usually as boldface. It is also possible to insert inline literals which will usually be represented as monospaced text.

This is another paragraph showing how to embed an inline literal while suppressing the surrounding blanks: restructuredText.

This example also shows that paragraphs are separated by a blank line. On a higher level, text is sectioned into parts, chapters, sections etc. A hierarchy is established by adorning titles in a systematic way. To this end, an underline or an underline together with an overline is added to the corresponding title. An underline or overline is at least as long as the title and contains only identical non-alphanumeric printable ASCII characters. It is recommended to choose among the characters = - ` : . ' " ~ ^ _ * + #. Note that even though in this way one can define a large number of different sectioning levels, in practice this number may be limited. For example, in HTML the number of different headings is limited to six. An example of sectioning of a text could look as follows:

============
Introduction
============

A first section
===============

Here comes some text ...

A second section
================
More text...

A subsection
------------
And so on...

As this example indicates, an empty line can be put after a title but this is not mandatory.

Lists, either as bullet-point lists or as enumerated lists, can easily be obtained in reStructuredText. In a bullet-point list, the items are indicated by a few characters including * + - . If the text if an item runs over several lines, it needs to be consistently indented. Sublists need to be separated from the surrounding list by empty lines. The following example illustrates the use of bullet-point lists:

* This is the text for the first item which runs over several lines. Make
  sure that the text is consistently indented.

  Further paragraphs in an item can be added provided the indentation
  is consistent.
* second item

  * a subitem

* third item

This code results in

  • This is the text for the first item which runs over several lines. Make sure that the text is consistently indented.

    Further paragraphs in an item can be added provided the indentation is consistent.

  • second item

    • A subitem is obtained by indenting the corresponding entry.

  • third item

An enumerated list can be numbered explicitly by numbers, alphabet characters in uppercase or lowercase, or Roman numerals. It is also possible to autonumber a list by means of #. The sublist of the second item demonstrates two aspects. The first subitem specifies that lowercase letters should be used for enumeration and, in addition, the sublist should start with a letter other than “a”. Once autonumbering has started, fixing a subsequent label would lead to the start of a new list.

The following code

#. first item with automatic numbering
#. second item

   p. subitem
   #. another subitem

#. another item

results in

  1. first item with automatic numbering

  2. second item

    1. subitem

    2. another subitem

  3. another item

We have already seen how to produce inline literals which may be useful to mark for example keywords. To display multiline code, the code directive is appropriate. The following example makes use of the possibility to add linenumbers.

.. code:: python

   nmax = 10
   sum = 0
   for n in range(1, nmax+1):
       sum = sum+n**2
   print(nmax, sum)

Since it is indicated that the code is written in Python, the syntax of the code can be highlighted.

nmax = 10
sum = 0
for n in range(1, nmax+1):
    sum = sum+n**2
print(nmax, sum)

Another possibility to typeset code is the use of two colons. If the colons follow the preceding text immediately, a single colon will be displayed at the end of the text:

The following script displays "hello world" three times::

   for _ in range(3):
       print('Hello world!')

Note the indentation of the code block which indicates which part of the text should be considered as code. The output is as follows:

The following script displays “hello world” three times:

for _ in range(3):
    print('Hello world!')

The colon in the output can be avoided if the colons are separated from the text by a blank:

The following script displays "hello world" three times. ::

   for _ in range(3):
       print('Hello world!')

Now, the output looks as follows:

The following script displays “hello world” three times.

for _ in range(3):
    print('Hello world!')

For scientific applications, one might want to include mathematical expressions. This can be done by means of the math role (:math:) for inline mathematical expressions and the math directive (math::) for displayed mathematical expressions. In both cases, the mathematical expression is entered in LaTeX format. The following code

Einstein found the famous formula :math:`E=mc^2` which describes the
equivalence of energy and mass.

.. math::

   \int_{-\infty}^\infty \mathrm{d}x \mathrm{e}^{-x^2} = \sqrt{\pi}

will result in the output:

Einstein found the famous formula \(E=mc^2\) which describes the equivalence of energy and mass.

\[\int_{-\infty}^\infty \mathrm{d}x \mathrm{e}^{-x^2} = \sqrt{\pi}\]

There exists also a directive to include images:

.. image:: img/example.png
   :width: 100
   :height: 100
   :align: center

The name of the image file to be included needs to be specified. Here, the file happens to reside in a subdirectory img of the present directory. We have also specified the size and the alignment of the figure, resulting in the following output:

_images/example.png

The figure directive can be used to add a figure caption. The caption text needs to be indented to indicate that it belongs to the figure directive.

.. figure:: img/example.png
   :height: 50
   :width: 100

   A graphics can be distorted by specifying ``height`` and ``width``.

This code results in Figure 6.1, which by means of the Sphinx LaTeX builder is created as a floating object.

_images/example.png

Figure 6.1 A graphics can be distorted by specifying height and width.

Occasionally, one may want to include a link to a web resource. In a documentation, this might be desirable to refer to a publication where an algorithm or the theoretical basis of the code has been described. As an example, we present various ways to link to the seminal paper by Cooley and Tukey on the fast Fourier transformation. The numbering allows us to refer more easily to the three different versions and plays no role with respect to the links.

#. J. W. Cooley and J. W. Tukey, *An algorithm for the machine calculation
   of complex Fourier series*,
   `Math. Comput. 19, 297–301 (1965) <https://doi.org/10.2307/2003354>`_

#. J. W. Cooley and J. W. Tukey, *An algorithm for the machine calculation
   of complex Fourier series*,
   Math. Comput. **19**, 297–301 (1965) `<https://doi.org/10.2307/2003354>`_

#. J. W. Cooley and J. W. Tukey, *An algorithm for the machine calculation
   of complex Fourier series*,
   Math. Comput. **19**, 297–301 (1965) https://doi.org/10.2307/2003354

results in the output

  1. J. W. Cooley and J. W. Tukey, An algorithm for the machine calculation of complex Fourier series, Math. Comput. 19, 297–301 (1965)

  2. J. W. Cooley and J. W. Tukey, An algorithm for the machine calculation of complex Fourier series, Math. Comput. 19, 297–301 (1965) https://doi.org/10.2307/2003354

  3. J. W. Cooley and J. W. Tukey, An algorithm for the machine calculation of complex Fourier series, Math. Comput. 19, 297–301 (1965) https://doi.org/10.2307/2003354

The first case represents the most comprehensive way to represent a link. The pair of back apostrophes encloses the text and the link delimited by a less-than and greater-than sign. The text will be shown in the output with the link associated with it. The underscore at the very end indicates that this is an outgoing link. In contrast to the two other variants, the volume number (19) can be set as boldface as nesting of the markup is not possible.

The second alternative explicitly displays the URL since no text is given. The same effect is obtained in the third variant by simply putting a URL which can be recognized as such.

In addition to external links, reStructuredText also allows to create internal links. An example are footnotes like in the following example.

This is some text. [#myfootnote]_ And more text...

.. [#myfootnote] Some remarks.

It is also possible to refer to titles of chapters or sections. The following example gives an illustration.

Introduction
============

This is an introductory chapter.

Chapter 1
=========

As discussed in the `Introduction`_ ...

Here, the text of the link has to agree with the text of the chapter or section.

The discussion of reStructuredText in this section did not attempt to cover all possibilities provided by this markup language. For more details, it is recommended to consult the documentation.

6.2. Sphinx documentation generator

The Sphinx documentation generator was initially created to produce the documentation for Python. However, it is very flexible and can be employed for many other use cases. In fact, the present lecture notes were also generated by means of Sphinx. As a documentation generator, Sphinx accepts documents written in reStructuredText including a number of extension and provides builders to convert the input into a variety of output formats, among them HTML and PDF, where the latter is obtained through LaTeX as an intermediate format. Sphinx offers the interesting possibility to autogenerate the documentation or part of it on the basis of the docstrings provided by the code being documented.

6.2.1. Setting up a Sphinx project

There is not a unique way to set up a Sphinx documentation project. For a unexperienced user of Sphinx, the probably simplest way is to invoke [4]

$ sphinx-quickstart

Remember that the dollar sign represents the command line prompt and should not be typed. The user will then be asked a number of questions and the answers will allow Sphinx to create the basic setup. For the documentation of a software project, it makes sense to store all documentation related material in a subdirectory doc. Then, sphinx-quickstart should either be run in this directory or the path to this directory should be given as an argument.

The dialog starts with a question about where to place the build directory relative to the source directory. The latter would for example be the directory doc and typically contains a configuration file, reStructuredText files, and possibly images. For a larger documentation, these files can be organized in a subdirectory structure. These source files will usually be put under version control. When creating the documentation in an output format, Sphinx puts intermediate files and the output in a special directory to avoid mixing these files with the source files. There are two ways to do so. A directory named build can be put in parallel to the doc directory or the it can be kept within the doc directory. Then it will be called _build where the underscore indicates its special role. It is not necessary to rerun sphinx-quickstart if you change your mind. One can instead modify the file Makefile and/or make.bat which will be discussed below. It may be useful to add the build directory to the .gitignore file, provided a Git repository is used.

Sphinx now asks the user to choose between the two alternatives. (y/n) in the last line indicates the possible valid answers. [n] indicates the default value which can also be chosen by simply hitting the return key. Per default, Sphinx thus chooses to place build files into a directory _build within the source directory.

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]:

Often, it makes sense to follow the recommendations of Sphinx. Two pieces of information are however mandatory: the name of the project and the author name(s). The default language is English, but for example by choosing de it can be switched to German. This information is relevant when converting to LaTeX in order to choose the correct hyphenation patterns.

sphinx-quickstart offers also to enable a number of extensions. It is possible to change one’s mind later by adapting the configuration file conf.py.

> autodoc: automatically insert docstrings from modules (y/n) [n]:
> doctest: automatically test code snippets in doctest blocks (y/n) [n]:
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]:
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]:
> coverage: checks for documentation coverage (y/n) [n]:
> imgmath: include math, rendered as PNG or SVG images (y/n) [n]:
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]:
> ifconfig: conditional inclusion of content based on config values (y/n) [n]:
> viewcode: include links to the source code of documented Python objects (y/n) [n]:
> githubpages: create .nojekyll file to publish the document on GitHub pages (y/n) [n]:

We briefly comment on a few of the more important extensions. autodoc should be enabled if one wants to generate documentation from the docstrings provided in the code being documented by the Sphinx project. intersphinx is useful if one wants to provide links to other projects. It is for example possible to refer to the NumPy documentation. MathJax is a Javascript package [5] which allows for high-quality typesetting of mathematical material in HTML.

Depending on the operating system(s) on which output is generated for the Sphinx project, one typically chooses either the Makefile for Un*x operating systems or a Windows command file for Windows operating systems or even both if more than one operating system is being used.

> Create Makefile? (y/n) [y]:
> Create Windows command file? (y/n) [y]:

While the conversion to an output format can always be done by means of sphinx-build, the task is facilitated by a Makefile or command file. On a Un*x system, running one of the commands

$ make html
$ make latexpdf

in the directory where the Makefile resides is sufficient to obtain HTML output of PDF output, respectively.

Accepting the default values proposed by Sphinx, the content of the source directory on a Un*x system will typically look as follows:

doc
+-- _build
+-- _static
+-- _templates
+-- conf.py
+-- index.rst
+-- Makefile

As is indicated by the extension, conf.py is a Python file which defines the configuration of the Sphinx project. This file can be modified according to the user’s need as long as the Python syntax is respected. index.rst is the main source file from which reference to other reStructuredText files can be made. Finally, Makefile defines what should be done when invoking make with one of the targets html or latexpdf or any other valid target specified by make help.

6.2.2. Sphinx configuration

As already mentioned, the file conf.py offers the possibility to adapt Sphinx to the needs of the project. Basic information includes the name of the project and of the author(s) as well as copyright information and version numbers. It makes sense to create a corresponding version tag in the project repository.

We have seen that sphinx-quickstart proposes the use of a number of extensions which, if selected, will appear in the list extensions. Here, other extensions may be added. When generating documentation from docstrings, the napoleon extensions is of particular interest. Its usefulness will be discussed in Section 6.2.3. This extension can be enabled by adding sphinx.ext.napoleon to the list of extensions.

The configuration file contains section for different output builders. We restrict ourselves here to HTML output and LaTeX output which can serve to produce a PDF document. Among the options for the HTML output, probably the most interesting variable is html_theme. https://www.sphinx-doc.org/en/stable/theming.html lists a few builtin themes which represent a simple way to change the look and feel of the HTML output. Third-party themes can be found at https://sphinx-themes.org/ and there is also the possibility to create one’s own customized theme.

If the LaTeX output needs to be customized, the dictionary latex_elements is the place to look for. The configuration file created by sphinx-quickstart provides a structure which is commented out, but might be useful if one needs to customize certain aspects. For example, if one wants to typeset for A4 paper and would like to have floats preferentially placed on the top of the page, one might set the dictionary as follows:

latex_elements = {
     # The paper size ('letterpaper' or 'a4paper').
     #
     'papersize': 'a4paper',

     # The font size ('10pt', '11pt' or '12pt').
     #
     # 'pointsize': '10pt',

     # Additional stuff for the LaTeX preamble.
     #
     # 'preamble': '',

     # Latex figure (float) alignment
     #
     'figure_align': 'tbp',
}

An interesting entry is also 'preamble' where all information can be specified which would normally go in the preamble of a LaTeX document, i.e. between the documentclass statement and the \begin{document} line. Note, however, that the use of backslashes common in LaTeX documents might require to specify the string as raw string by placing an r in front of it. A number of parameters specified by the Sphinx style file can be modified in an entry with key 'sphinxsetup'. If the outline of the box enclosing code should be removed and a background color different from white should be used, one might specify:

'sphinxsetup': '''verbatimwithframe=false,
                  VerbatimColor={named}{AliceBlue},
               '''

This definition is used for the present document. Details about which parameters can be changed in this way and about other entries which can be added to the dictionary latex_elements can be found in the section LaTeX customization of the Sphinx documentation. Finally, it may be useful to know that in the list latex_documents several properties of the document are specified like the title and author appearing on the cover page of the documentation.

6.2.3. Autogeneration of a documentation

With Sphinx it is possible to autogenerate documentation from docstrings. Before discussing how docstrings can be formatted for use by Sphinx, we make a few general remarks on docstrings. Recommendations about how a docstring should look like are given in PEP 257. [8] We here focus on the keypoints pertinent to docstrings of methods and functions. The first line of the docstring should be a phrase ending in a period. It should be written as a command like “do something” instead of a description like “does something”. This phrase should not exceed one line and it should be separated from the rest of the docstring by one empty line. Then, in particular the arguments of the function or method and the return value(s) should be explained. Or course, further information deemed useful can be given in addition.

In order to demonstrate the autogeneration of documentation from docstrings, we take as an example the last script for the quantum carpet discussed in Section 5. We have partially supplied the code with docstrings which now looks as follows:

from math import sqrt
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

class InfiniteWell:
    """Quantum carpet for infinitely deep potential well.

    This class allows to determine the time evolution of an
    initial state in an infinitely deep potential well.

    :param func psi0: initial wave function
    :param float width: width of the potential well
    :param int nbase: number of basis states
    :param int nint: number of intervals used in the integration routine
    """

    def __init__(self, psi0, width, nbase, nint):
        self.width = width
        self.nbase = nbase
        self.nint = nint
        self.coeffs = trapezoidal(lambda x: psi0(x)*self.eigenfunction(x),
                                  -0.5*self.width, 0.5*self.width, self.nint)

    def eigenfunction(self, x):
        """Determine set of eigenfunction values at position ``x``.

        The basis set is limited by the number of eigenstates given by
        ``self.nbase``.

        :param x: position at which the eigenfunctions are to be determined
        :type x: float or numpy.ndarray
        :return: array of eigenfunction values
        :rtype: numpy.ndarray
        :raises AssertionError: if the dimension of ``x`` does not equal 1
        """
        assert x.ndim == 1
        normalization = sqrt(2/self.width)
        args = (np.arange(self.nbase)[:, np.newaxis]+1)*np.pi*x/self.width
        result = np.empty((self.nbase, x.size))
        result[0::2, :] = normalization*np.cos(args[0::2])
        result[1::2, :] = normalization*np.sin(args[1::2])
        return result

    def psi(self, x, t):
        coeffs = self.coeffs[:, np.newaxis]
        eigenvals = np.arange(self.nbase)[:, np.newaxis]
        tvals = t[:, np.newaxis, np.newaxis]
        psit = np.sum(coeffs * self.eigenfunction(x)
                      * np.exp(-1j*(eigenvals+1)**2*tvals), axis= -2)
        return psit

def trapezoidal(func, a, b, nint):
    delta = (b-a)/nint
    x = np.linspace(a, b, nint+1)
    integrand = func(x)
    integrand[..., 0] = 0.5*integrand[..., 0]
    integrand[..., -1] = 0.5*integrand[..., -1]
    return delta*np.sum(integrand, axis=-1)

def psi0(x):
    """Determine Gaussian wave function.

    :param float x: position at which the wave function is determined
    :return: value of wave function at position ``x``
    :rtype: float
    """
    sigma = 0.005
    return np.exp(-x**2/(2*sigma))/(np.pi*sigma)**0.25

if __name__ == '__main__':
    w = InfiniteWell(psi0=psi0, width=2, nbase=100, nint=1000)
    x = np.linspace(-0.5*w.width, 0.5*w.width, 500)
    t = np.linspace(0, np.pi/4, 1000)
    z = np.abs(w.psi(x, t))**2
    z = z/np.max(z)
    plt.rc('text', usetex=True)
    plt.imshow(z.T, cmap=cm.hot)
    plt.xlabel('$t$', fontsize=20)
    plt.ylabel('$x$', fontsize=20)
    plt.show()

In addition to the docstrings, this code makes sure that the last part is not executed when this script is imported, because in order to access the docstrings, Sphinx will import the script. Execution of the last part in our case will simply cost time but in general can have more serious side effects. Note that the script can only be imported, if it is in the search path defined in the Sphinx configuration file. This usually requires to uncomment the three lines

import os
import sys
sys.path.insert(0, os.path.abspath('.'))

and to adjust the argument of os.path.abspath according to the place where the script to be imported can be found.

The docstrings are written in reStructuredText and admittedly are not easy to read. We will discuss a solution to this problem shortly. For the moment, however, we will keep this form of the docstrings.

Now let us add the following code in one of our reStructuredText files which are part of the documentation:

.. automodule:: carpet
   :members:
   :undoc-members:

This code will only function correctly, if the autodoc extension is loaded, i.e. the list extensions in the Sphinx configuration file contains the entry 'sphinx.ext.autodoc'. The argument carpet of the automodule directive implies that the file carpet.py will be imported. The autogenerated documentation will list all documented as well as all undocumented members. The generated output will look as follows:

class carpet.InfiniteWell(psi0, width, nbase, nint)

Quantum carpet for infinitely deep potential well.

This class allows to determine the time evolution of an initial state in an infinitely deep potential well.

Parameters:
  • psi0 (func) – initial wave function

  • width (float) – width of the potential well

  • nbase (int) – number of basis states

  • nint (int) – number of intervals used in the integration routine

eigenfunction(x)

Determine set of eigenfunction values at position x.

The basis set is limited by the number of eigenstates given by self.nbase.

Parameters:

x (float or numpy.ndarray) – position at which the eigenfunctions are to be determined

Returns:

array of eigenfunction values

Return type:

numpy.ndarray

Raises:

AssertionError – if the dimension of x does not equal 1

psi(x, t)

carpet.psi0(x)

Determine Gaussian wave function.

Parameters:

x (float) – position at which the wave function is determined

Returns:

value of wave function at position x

Return type:

float

carpet.trapezoidal(func, a, b, nint)

If the line containing :undoc-members: were left out in the automodule directive, the output would contain only the documented class and methods. The listed methods could be restricted by giving the appropriate names after :members:.

As already mentioned, the docstrings given above are not particularly easy to read. There are two standards for docstrings which are handled by Sphinx, provided the extension napoleon is loaded. The list extensions in the Sphinx configuration file then should contain the string 'sphinx.ext.napoleon'. The supported standards for docstrings are the Google style docstring [6] and NumPy style docstring [7]. We will focus our discussion of these two standards to the method eigenfunction in the quantum carpet script.

Applying the NumPy style to the method eigenfunction would result in

def eigenfunction(self, x):
    """Determine set of eigenfunction values at position `x`.

    The basis set is limited by the number of eigenstates given by
    ``self.nbase``.

    Parameters
    ----------
    x : float or numpy.ndarray
        position at which the eigenfunctions are to be determined

    Returns
    -------
    numpy.ndarray
        array of eigenfunction values

    Raises
    ------
    AssertionError
        if the dimension of `x` does not equal 1

    """

where we did not repeat the code of the eigenfunction method. This docstring is nicely formatted in sections. The possible sections are not restricted to the ones used in this example. A complete list is given in the documentation of the napoleon preprocessor. The output obtained from this docstring corresponds to the one given before, possibly with minor differences, so that we do not reproduce it here.

The Google style for docstrings resembles the NumPy style in the sectioning of the docstring even though the details of the format differ. Our example would take the following form where we again leave out the code of the method:

def eigenfunction(self, x):
    """Determine set of eigenfunction values at position `x`.

    The basis set is limited by the number of eigenstates given by
    ``self.nbase``.

    Args:
        x (float or numpy.ndarray): Position at which the eigenfunctions
            are to be determined.

    Returns:
        numpy.ndarray: Array of eigenfunction values.

    Raises:
        AssertionError: The dimension of `x` does not equal 1.

    """

These examples may serve to get the basic idea of how a documentation can be autogenerated from docstrings. When working with the Sphinx documentation generator, questions are likely to come up which have not been addressed in this chapter. A complete description can be found in the extensive online documentation which should be consulted in the case of need.