ufzLogo rdmLogo

Documentation Guide#

We document our code via docstrings in numpy-style. Features, install and usage instructions and other more text intense stuff, is written in extra documents. The documents and the docstrings then are collected and rendered using sphinx.

Documentation Strings#

  • Write docstrings for all public modules, functions, classes, and methods. Docstrings are not necessary for non-public methods, but you should have a comment that describes what the method does. This comment should appear after the def line. [PEP8]

  • Note that most importantly, the """ that ends a multiline docstring should be on a line by itself [PEP8] :

    """Return a foobang
    
    Optional plotz says to frobnicate the bizbaz first.
    """
    
  • For one liner docstrings, please keep the closing """ on the same line. [PEP8]

Pandas Style#

We use Pandas-style docstrings:

Flagger, data, field, etc.#

use this:

def foo(data, field, flagger):
    """
    data : saqc.DictOfSeries
    A saqc-data object.

    field : str
    A field denoting a column in data.

    flagger : saqc.flagger.BaseFlagger
    A saqc-flagger object.
    """

IDE helper#

In pycharm one can activate autogeneration of numpy doc style like so:

  1. File->Settings...

  2. Tools->Python Integrated Tools

  3. Docstrings->Docstring format

  4. Choose NumPy

Docstring formatting pitfalls#

  • Latex is included via:

    :math:`<latex_code>`
    
  • Latex commands need to be signified with double backlash! (\\mu)

  • Nested lists need to be all of the same kind (either numbered or marked - otherwise result is salad)

  • List items covering several lines in the docstring have to be all aligned - (so, not only the superfluent ones, but ALL, including the first one - otherwise result is salad)

  • Start of a list has to be seperated from preceding docstring code by one blank line - (otherwise list items get just chained in one line and result is salad)

  • Most formatting signifiers are not allowed to start or end with a space.

  • Do not include lines only containing two or more - signs, except it is the underscore line of the section heading (otherwise resulting html representation could be messed up)

hyperlinking docstrings#

  • Link code content/modules via python roles.

  • Cite/link via the py domain roles. Link content bar, that is registered to the API with the adress foo.bar and shall be represented by the name link_name, via:

    :py:role:`link_name <foo.bar>`
    
  • Check out the _api folder in the repository to get an overview of already registered paths. Most important may be:

  • Constants are available via saqc.constants - for example:

    :py:const:`~saqc.constants.BAD`
    
  • The ~ is a shorthand for hiding the module path and only displaying BAD.

  • Functions are available via the “simulated” module Functions.saqc - for example:

    :py:func:`coolMethod <saqc.SaQC.flagRange>`
    
  • The saqc object and/or its content is available via:

    :py:class:`saqc.SaQC`
    :py:meth:`saqc.SaQC.flagRange`
    
  • The Flags object and/or its content is available via:

    :py:class:`saqc.Flags`
    
  • You can add .rst files containing automodapi directives to the modulesAPI folder to make available more modules via pyroles

  • The Environment table, including variables available via config files is available as restfile located in the environment folder. (Use include directive to include, or linking syntax to link it.

Integrating doctested code snippets#

code-block#

If you want to ONLY RENDER code blocks, use the common code-block directive:

.. code-block:: python

   a = 1
   b = 2
   a + b

This results in:

a = 1
b = 2
a + b

testcode#

If you want code to be RENDERED and TESTED, use the testcode directive. You can specify a group, where assignments and imports will be stored to, and available for later testcode directives of the same group and same document. Code is executed, and the doctest will fail, if execution causes an exception to be thrown.

.. testcode:: group1

   a = 1
   b = 2
   a + b

This will be rendered as:

a = 1
b = 2
a + b

Assignments (and imports) will be available in any other testcode directive, that has the same group assigned. So the following wont fail, since a is known in group1:

.. testcode:: group1

   a - 4

testsetup#

If you want to setup the example environment in a hidden manor, you can use the testsetup directive:

.. testsetup:: group1

   import scipy

Will import scipy into the group environment, omitting rendering/display of the code.

testoutput#

If you want to additionally check the final std_out output of a testcode block, you can use the testoutput directive:

.. testcode:: group1

   a - 4

.. testoutput::

   -3

This will be rendered as follows:

a - 4
-3

You can omit displaying of the testoutput, by adding the hidden option.

doctest#

If you want to have code tested and rendered in the doctest style rendering, (including >>>), you can use doctest syntax:

>>> 1+1
2

This will be rendered as:

>>> 1+1
2

It can be a little tricky, to match complexer std_out strings, like DictOfSeries or DataFrames. There are some doctest flags that can mitigate frustration:

  1. NORMALIZE_WHITESPACE will map all whitespace/tab combos onto a single whitespace. Use like:

    >>> 'ab  c' #doctest:+NORMALIZE_WHITESPACE
    'ab c'
    
  2. ELLIPSIS will allow usage of the ‘…’-Wildcard in the expected output. (Usefull, if output contains unpredictable substrings, like memory adresses or filepaths

    >>> 'abcdefg' #doctest:+ELLIPSIS
    'a...b'
    
  3. SKIP skips the check (and execution of the line) all together. (usually used, if display is demanded, but testing would somehow be unstable, due to random/unpredictable components)

    >>> time #doctest:+SKIP
    CPU times: user 5 µs, sys: 3 µs, total: 8 µs
    Wall time: 13.8 µs
    

    Caution

    Skipped lines are NOT tested! The execution of the line is skipped all together with the check against the expected output.

To assign a group to doctest snippets, use the more verbose doctest directive:

.. doctest:: group1

   >>> time #doctest:+SKIP
   CPU times: user 5 µs, sys: 3 µs, total: 8 µs
   Wall time: 13.8 µs

Will be rendered, as:

>>> time 
CPU times: user 5 µs, sys: 3 µs, total: 8 µs
Wall time: 13.8 µs

Run doctest locally#

Since doctest checks guard the push to the develop branch, you might wish to chek if your local modification passes all doctests beforehand.

There for go to the docs directory and run:

make test

To only run the doctests.