Writing documentation

Aaron Meurer edited this page Jun 17, 2017 · 30 revisions

General

Sympy documentation found at docs.sympy.org is generated from docstrings in the source code and dedicated files in /doc/src directory. Both are written in reStructuredText format extended by Sphinx. Sphinx is also used to compile documentation to various formats (e.g. html, latex,...).

Building docs

The documentation can be built by running the Makefile in the doc subdirectory. For example, to build the HTML documentation, run:

( cd doc && make html )

This builds the documentation in doc/_build/html.

Note: it seems that some of the doc scripts are broken for Python 3, so if your system defaults to Python 3 you will need to run it using the Python 2 variant of sphinx-build. For example, on Arch Linux this is called sphinx-build2, so you'll need to override the SPHINXBUILD variable like this:

( cd doc && make SPHINXBUILD='PYTHONPATH=..:$(PYTHONPATH) sphinx-build2' html )

Some notes about documentation

  • Docstrings should contain information aimed for users of the function. Comments specific to the code, or other notes that would only distract users should go in comments in the code, not in docstrings.

  • If you want to write more extensive documentation, or documentation that is not centered around an API reference, write a document in the Sphinx docs (located in doc/).

  • All public functions, classes, and methods should have docstrings with doctests. You can use the ./bin/coverage_doctest.py script to test the docstring/doctest coverage of a file or module.

  • All public functions, classes, and methods should be imported into the Sphinx docs. We presently do not have an easy way to check this, but there is an issue to create one.

  • The best way to tell if you've formatted your docstring correctly is to first make sure that it is imported into Sphinx, then build the Sphinx docs (cd doc; make html). First, make sure that Sphinx doesn't output any errors. Second, open the page in _build/html and make sure that it is formatted correctly.

  • Don't think of doctests as tests. Think of them as examples that happen to be tested. They should demonstrate the API of the function to the user, i.e., what the input parameters look like, what the output looks like, and what it does. If you just want to test something, add a test to the relevant test_*.py file.

  • Doctests should be complicated enough that they fully demonstrate the API and functionality of the function, but simple enough that a user can understand them without too much thought. The perfect doctest tells the user exactly what he needs to know about the function without him reading any other part of the docstring.

  • Run the doctests with ./bin/doctest.

Docstrings

Every public function and method should have a docstring that describes what it does. It also often helps to have docstrings on private functions to help other SymPy developers understand how to use the function.

Furthermore, every docstring should have examples that show how the function works (these are called doctests). Doctests are the most important part of a docstring. A single example showing input and output to a function can be more helpful than a paragraph of descriptive text.

Remember that the primary consumer of docstrings is other human beings, not machines, so the most important part is to describe what the function does in plain English, and to show examples of how to use it. With that being said, there are some formatting guidelines to follow, so that Sphinx will render the docstrings nicely in the HTML documentation.

Docstrings should follow PEP 257 - Docstring conventions and PEP 287 - reStructuredText docstring format. For legibility purposes, module docstrings should not exceed column 73 and function docstrings should not exceed column 77. When wrapped at these lengths, the text (in a console window of width 81) will have the same right margin (4 columns) as on the left. (Python automatically indents module docstrings; that's why its wrapping width is shorter.)

In order to make section underlining work nicely in docstrings, numpydoc Sphinx extension is used. Sympy docstring also more or less conform to the rules of the Numpy/Scipy docstring standard. More or less means that you should use only constructs supported by the standard (e.g. use only supported sections, respect section order,...), but on the other hand you don't have to comply with all the requirements (you don't have to use all the sections that the standard requires,...).

Notes

  • Function and method docstrings can be made up of the following sections:

    1. Short summary
    2. Deprecation warning
    3. Extended summary
    4. Parameters
    5. Returns
    6. Other parameters
    7. Raises
    8. Examples
    9. See Also
    10. Notes
    11. References

    Not all sections are required, although every docstring should have some examples. Do not use unsupported sections -- use "Examples" as the section even if there is only one example. (TODO: Add support for variant section names). The above is a suggested order for the sections. Use this if you are not sure what order to put the sections in, but also use your best judgment.

    For more details see A guide to NumPy/SciPy documentation. There is also a guide to documenting classes and modules on the same page.

    • Not all sections start with underlined section header. Summary and Extended summary sections don't use any additional formatting mechanism, while the Deprecation warning section uses just note Sphinx directive,
	.. note:: Deprecated in Sympy 0.7.1.
  • Don't use sections that are not necessary. Avoid cluttered docstrings. Sometimes extra sections will just obfuscate the docstring and make function harder to understand.

  • For section underlining use equals sign, =======.

  • Text that should be printed verbatim should be surrounded by two backticks (``). Text that is surrounded by only one set of backticks will be rendered as LaTeX math by MathJax.

  • In the past the doctest runner didn't work if there was no blank line before the docstring's closing quotes. This bug has since been fixed. The blank line is nevertheless recommended in the PEPs.

Examples

prime's docstring is an example of a well formatted docstring.

"""
Return the nth prime.

Primes are indexed as prime(1) = 2, prime(2) = 3, etc.... The nth prime is
approximately n*log(n) and can never be larger than 2**n.

Examples
========

>>> from sympy import prime
>>> prime(10)
29
>>> prime(1)
2

See Also
========

sympy.ntheory.primetest.isprime, primerange, primepi

References
==========

.. [1] http://primes.utm.edu/glossary/xpage/BertrandsPostulate.html

"""

Testing of an example can be skipped by adding a special comment,

>>> import sympy
>>> sympy.doctest()      # doctest: +SKIP

Notes about the Summary section.

The styleguide at http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring suggests that the Summary (if short) is a phrase ending in a period. It prescribes the function or method's effect as a command ("Do this", "Return that") not "Returns the pathname..." Again quoting about multi-line docstrings: they "consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description." Also, for the multi-line summary it is recommended that "a blank line [be inserted before] its closing quotes." Regarding quotes, also: For consistency, always use """triple double quotes""" around docstrings. Use r"""raw triple double quotes""" if you use any backslashes in your docstrings. For Unicode docstrings, use u"""Unicode triple-quoted strings""".

Notes about See Also section

Note that in the See Also section, isprime is referenced by absolute path while primerange and primepi just by their names. The reason for this is that the later two functions and prime are all in the same file (sympy/ntheory/generate.py) and they are all imported relative to that file in doc/src/modules/ntheory.txt. On the other hand, isprime is from sympy/ntheory/primetest.py and is imported relative to sympy.ntheory.primetest. Relative imports in ntheory.txt are achieved with .. module:: directive.

If description spans more than one line, subsequent lines must be indented. Here is an example from sympy.matrices.rot_axis3 function docstring:

See Also
========

rot_axis1: returns a rotation matrix for a rotation of theta (in radians)
    about the 1-axis
rot_axis2: returns a rotation matrix for a rotation of theta (in radians)
    about the 2-axis

In this particular case the entire description is probably not even necessary because it is obvious that rot_axis1 and rot_axis2 have the same functionnality as rot_axis3. Nevertheless, the format is correct. Try to make the description a concise fragment (not a full sentence). Think of it more of a hint; if the reader wants to know more they will look at the function described.

A common mistake is to reference classes with class:Classname, class:`Classname` or :class:`Classname`. That is wrong. Classes must be referenced the same way functions are - by their name if they are in the same file as the See Also section or by full path if they are in some other file.

TOCs and indexes

In tables of content (TOC), e.g. on the documentation front page, modules (classes, functions) must be listed in alphabetical order.

Importing docstrings into documentation

Here is a part of the doc/src/modules/geometry.txt file that imports the relevant docstrings from geometry module into documentation:

~~~~~
Utils
~~~~~

.. module:: sympy.geometry.util

.. autofunction:: intersection

.. autofunction:: convex_hull

.. autofunction:: are_similar

~~~~~~
Points
~~~~~~

.. module:: sympy.geometry.point

.. autoclass:: Point
   :members:

~~~~~
Lines
~~~~~

.. module:: sympy.geometry.line

.. autoclass:: LinearEntity
   :members:

.. autoclass:: Line
   :members:

.. autoclass:: Ray
   :members:

.. autoclass:: Segment
   :members:

~~~~~~
Curves
~~~~~~

.. module:: sympy.geometry.curve

.. autoclass:: Curve
   :members:

~~~~~~~~
Ellipses
~~~~~~~~

.. module:: sympy.geometry.ellipse

.. autoclass:: Ellipse
   :members:

.. autoclass:: Circle
   :members:

~~~~~~~~
Polygons
~~~~~~~~

.. module:: sympy.geometry.polygon

.. autoclass:: Polygon
   :members:

.. autoclass:: RegularPolygon
   :members:

.. autoclass:: Triangle
   :members:

First namespace is set to particular submodule (file) with .. module:: directive, then docstrings are imported with .. autoclass:: or .. autofunction:: relative to that submodule (file). Other methods are either cumbersome to use (using full paths for all objects) or break something (importing relative to main module using .. module:: sympy.geometry breaks viewcode Sphinx extension).

All files in doc/src/modules/ should use this format.

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.