Sphinx Docstring Best Practices
Tags: python
Published: 2020-09-14 10:52:56

I would like to briefly cover how Docstrings for use by Sphinx are recommended to look like. It is handy to know how to make docstrings that display properly in generated Sphinx webpages and convey the maximum amount of information about your functions in a standardized way.

In Python, function, classes, methods and even entire modules can have a triple-quoted string immediately under it. Normally if you put constants on a line by themselves, they have no effect and are just ignored. But the triple quote string immediately below one of these Python constructs is special, because it is treated like documentation. It is processed by external tools to be displayed on the `help()` console, and documentation generators like Sphinx.

Docstrings are defined in [PEP 257](https://www.python.org/dev/peps/pep-0257/). It is recommended to use double quotes instead of single quotes when forming the docstring. Docstrings can come in one line like this:

```python
def foo():
   """This is a one-line summary of foo()"""
   # function contents here
```

Or, as a multi-line docstring with a summary and description:


```python
def foo():
   """This is a one-line summary of foo()
   
   This is a longer description of what foo()
   does that can span several lines.
   """
   # function contents here
```

While PEP 257 defines how docstrings look, it doesn't define the exact format you define your functions in docstrings, especially parameters, return values and exceptions thrown. That is contained in [PEP 287](https://www.python.org/dev/peps/pep-0287/). 

## What is reStructedText

Before we continue, it is necessary for you to know what reStructuredText is. It is a markup language the Python community developed for typing richly formatted text, so not limited to solely documentation. It has similar syntax as Markdown, but with a few key differences:

- Nested numbered lists are supported:

```rst
- A bullet list item
- Second item

  - A sub item

- Spacing between items separates list items

* Different bullet symbols create separate lists

- Third item

1) An enumerated list item

2) Second item

   a) Sub item that goes on at length and thus needs
      to be wrapped. Note the indentation that must
      match the beginning of the text, not the 
      enumerator.

      i) List items can even include

         paragraph breaks.

3) Third item

#) Another enumerated list item

#) Second item
```

- Images use the `.. image::` qualifier instead of brackets:
`.. image:: /path/to/image.jpg`

- Similarly, links have two dots followed by space, the link name and the URL:
`.. _Wikipedia: https://www.wikipedia.org/`

- Links with no name have two underscores at the beginning:
`__ https://www.python.org/`

- And finally, block quotes are indented, have two dashes followed by the author's name:

```rst
This is an ordinary paragraph, introducing a block quote.

    "It is my business to know things.  That is my trade."

    -- Sherlock Holmes
```

## Sphinx Docstring conventions in reStructuredText

Armed with the flexibility of reStructuredText, several additional directives in docstrings that Python can view specially is possible, because it's implemented in Docutils that's used by Python and Python-based modules to generate documentation.

There are five docstring reStructuredText directives, which I will list here. These directives are recognized by the [Sphinx](https://www.sphinx-doc.org/en/master/) documentation generator.

- `:param:`: indicates a function parameter, with a name, what it's used for, and default value.
`:param [ParamName]: [ParamDescription], defaults to [DefaultParamVal]` 

- `:type:`: indicates the type of a parameter, and must be immediately below its associated `:param:` directive. It also lets you indicate whether a parameter is optional. Simply exclude the `, optional` part to indicate that a parameter is required.
`:type [ParamName]: [ParamType], optional`

- `:raises:`: Indicates that an exception is raised, its type, and its description.
`:raises [ErrorType]: [ErrorDescription]`

- `:return:`: Lets you indicate what is returned by the function.
`:return: [ReturnDescription]`

- `:rtype:` Indicates the type of the return value.
`:rtype: [ReturnType]`

It is a convention that each directive line in the docstring spans 110 characters or less. If the directive overflows to serveral lines, they are indented by four spaces relative to the beginning of the first line.

## And we're done

If you see any errors in this post, please let me know so I can correct them.

---
Sources:
https://en.wikipedia.org/wiki/ReStructuredText
https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html
https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html