Python docstring

Main docstring formats

In Python, they are multiple docstring formats.
There is an official format: reStructuredText but there are also not official but very used formats.

reStructuredText:
Official Python documentation standard. It has many features but it is also very verbose and tricky.
Google docstrings:
It is a very simplified docstring format.
NumPy/SciPy docstrings:
It is a simplified docstring format.
Epytext:
A Python adaptation of Epydoc. Similar to javadoc.

reStructuredText docstring examples

Note: The new lines are mandatory between sections.

from pathlib import Path
from typing import Optional
 
from python_utils import timeout_generator
 
 
class BarClass:
    """Summary of BarClass.
    Longer class information...
 
    Attributes:
        name: the name of the instance.
        counter: The current count of rename_image() invocation.
    """
 
    def __init__(self, name: str):
        """Init BarClass with name and counter."""
        self.name = name
        self.counter = 0
 
    def rename_image(self, current_name: str, new_name: str) -> Optional[Path]:
        """
        Rename the image 'current_name' to 'new_name'. 
 
        Args:
            current_name: The current name of the image 
            new_name: The new name of the image
 
        Returns:
            The path of the renamed file
 
        Raises:
          ValueError: If 'current_name' or 'new_name' are missing .
 
        """
        if not current_name:
            raise ValueError('The current_name parameter cannot be none')
        if not new_name:
            raise ValueError('The new_name parameter cannot be none')
        self.counter += 1
        for i in timeout_generator(3):
            try:
                return Path('...')
            except Exception as e:
                print(f'try {i + 1} fails, e={e}')
        return None

Google docstring examples

Note: The new lines are mandatory between sections.

from pathlib import Path
from typing import Optional
 
from python_utils import timeout_generator
 
 
class BarClass:
    """Summary of BarClass.
    Longer class information...
 
    Attributes:
        name: the name of the instance.
        counter: The current count of rename_image() invocation.
    """
 
    def __init__(self, name: str):
        """Init BarClass with name and counter."""
        self.name = name
        self.counter = 0
 
    def rename_image(self, current_name: str, new_name: str) -> Optional[Path]:
        """
        Rename the image 'current_name' to 'new_name'. 
 
        Args:
            current_name: The current name of the image 
            new_name: The new name of the image
 
        Returns:
            The path of the renamed file
 
        Raises:
          ValueError: If 'current_name' or 'new_name' are missing .
 
        """
        if not current_name:
            raise ValueError('The current_name parameter cannot be none')
        if not new_name:
            raise ValueError('The new_name parameter cannot be none')
        self.counter += 1
        for i in timeout_generator(3):
            try:
                return Path('...')
            except Exception as e:
                print(f'try {i + 1} fails, e={e}')
        return None

Sphinx

Overview

Common and powerful library to generate documentation from Docstrings in the code.
Concretely, Sphinx generates two kinds of output:
– it takes as input source code containing docstring and generates .rst files as output.
– it takes as input .rst files and generate as output a documentation in the specified format (.html, .pdf, …).

The docstring formats presented above are all compatible with Sphinx.
But: if we don’t use reStructuredText, we may need to use a sphinx extension (napoleon) to generate .rst files.

Install sphinx inside the virtual environment

If our project use a virtual environment or specific library requirement, we need to install sphinx inside it too to have all dependencies in the path .
pip install sphinx

Setting up the documentation sources

The root directory of a Sphinx collection of plain-text document sources is called the source directory.
The source directory contain (not exhaustive) :
– the configuration file conf.py, where you can configure all aspects of how Sphinx reads your sources and builds your documentation.
– a root document, index.rst. It is a welcome page that contains the root of the « table of contents tree » (or toctree).
Generally, we need to customize it according to our requirements.
make.bat and a makefile : to build HTML docs in the build directory you chose.

To set up a source directory and creates a default configuration, you create a docs directory at the root of the project and go inside it from your shell to execute the next command.

– Interactive mode:
sphinx-quickstart
– Quiet mode (with mandatory options provided):
sphinx-quickstart -q -p sphinx-example -a Davidxxx -v 1.0

By default it doesn’t separate source(rst,conf,makefile…) and build(html,…) for documentation.

Generate sphinx/rst files for all modules with the autodoc extension

To do that, we need to add the autodoc extension and enable it in the conf.py:

    extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
    ]
    autosummary_generate = True # Turn on sphinx.ext.autosummary

Assume you have this layout:
sphinx: the root directory
docs: the documentations directory
sphinx_example: the path to the Python module to document

sphinx_project_layout

From the root project (…sphinx$ ), we can generate the rst files in this way :
sphinx-apidoc -f -o docs ./sphinx_example/

We could have as output something like:

Creating file docs/sphinx_example.rst.
Creating file docs/sphinx_example.app.rst.
Creating file docs/sphinx_example.core.rst.
Creating file docs/modules.rst.

Generate documentation files from modules sources and generated rst files

To do that, we need to do first some modifications:
– modify the index.rst file to render the modules.rst file:

Welcome to sphinx-example's documentation!
==========================================
 
.. toctree::
   :maxdepth: 2
   :caption: Contents:
 
   module

– modify the PYTHON path to have all sources in it and mock any import of our source code that may be annoying during the generation .
Indeed, the generation of the documentation use by default as python path the directory where the conf.rst file is located.
So, generally we need to modify it.
With our layout, we need to do that:

import os
import sys
 
sys.path.insert(0, os.path.abspath('..'))
print(f'sys.path={sys.path}')
autodoc_mock_imports = ["python_utils"]

Now, we are ready to generate the html documentation files.

sphinx-build way:
Here the general syntax:
sphinx-build -b html sourcedir builddir

Where sourcedir is the source directory(That is that contains the rst files), and builddir is the directory in which you want to place the built documentation.
The -b option selects a builder.

In our case, from the root project we do that:
sphinx-build -v -b html docs docs/build/html/

make way:
In our case, from the docs project we need to do that:
make html
Whatever the way, the result is the same. We should see at the end of the execution the writing of modules and submodules documentation:

writing output... [ 20%] index
writing output... [ 40%] modules
writing output... [ 60%] sphinx_example
writing output... [ 80%] sphinx_example.app
writing output... [100%] sphinx_example.core

We can see the documentation for all modules and submodules where generated:

screenshot_sphinx_module_index

We can see in this preview, to modules documentations with the same source code but using to distinct docstring formats.
BarClass uses Google docstring and FooClass uses reStructuredText docstring:

screenshot_sphinx_module_example_with_2_docstring_formats

Ce contenu a été publié dans Non classé. Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *