Are there any real alternatives to reStructuredText for Python documentation?

Question:

I’m starting an open source Python project shortly and I’m trying to decide in advance how to write my docstrings. The obvious answer would be using reStructuredText and Sphinx with autodoc, because I really like the idea of simply properly documenting my code in my docstrings then have Sphinx automatically construct an API doc for me.

The problem is the reStructuredText syntax it uses – I think it’s completely unreadable before it’s rendered. For instance:

:param path: The path of the file to wrap
:type path: str
:param field_storage: The :class:`FileStorage` instance to wrap
:type field_storage: FileStorage
:param temporary: Whether or not to delete the file when the File instance
    is destructed
:type temporary: bool

You have to really slow down and take a minute to make any sense out of that syntactic jumble. I like much more the Google way (Google Python Style Guide), which counterpart to the above looks like this:

Args:
    path (str): The path of the file to wrap
    field_storage (FileStorage): The FileStorage instance to wrap
    temporary (bool): Whether or not to delete the file when the File
        instance is destructed

Way nicer! But of course, Sphinx will have none of that and renders all the text after Args: in one long line.

So to summarize – before I go and defile my code base with this reStructuredText syntax I would like to know if there are any real alternatives to using it and Sphinx, short of just writing my own API doc. For instance, is there an extension for Sphinx that handles Google Style Guide’s docstring style?

Asked By: Hubro

||

Answers:

Python makes the contents of the docstrings available as a __doc__ attribute attached to the function/class/variable object.

So, you could trivially write a Python program which converts the documentation from whatever format you like into whatever format you like. You could even use Javadoc styling, or XML, or whatever.

Incidentally, since Sphinx is written in Python, making it take non-RST input is just a matter of writing a small amount of Python code.

Answered By: Borealid

Actually, reStructuredText as well as the style guide from PEP8 apply mostly for coding the Python’s standard library itself, albeit a lot of third party programmers conform to that as well.

I agree with you that the Google’s style for arguments is much better from an in-code perspective. But you should be able to generate such docstring with sphinx as well, with the new lines and indentation preserved. It doesn’t output as nice as with a more sphinxy formatting though.

Anyway, you don’t have to use sphinx, and by the way, the autodoc module of sphinx is definitely just a small part of it. You can virtually use any documentation generator which is capable of retrieving the content of docstrings, like Epydoc (which support epytext as well as reStructuredText, Javadoc or Plaintext) or pydoctor, or even a more universal one like Doxygen.

But definitely, sphinx is quite pythonic, very convenient to use with Python, and make your code consistent with the Python’s ecosystem. I think you are not the only one who think this is a “lack”. Maybe they will take these complaints into account in the future, or maybe you might even consider modyfying the autodoc module by yourself, should not be very difficult, it’s in Python, it would be a good exercise.

Answered By: cedbeu

You can write docstrings in any format you like. However, for the sake of every other Python programmer, it’s best to use markup and tools that they already know. Their lives is easier if you stick to reST and Sphinx.

Answered By: user25148

I use epydoc and not sphinx, so this answer may not apply.

The reStructuredText syntax you describe for documenting methods and functions is not the only possible one. By far, I prefer describing parameters using a consolidated definition list, which is very similar to the Google way:

:Parameters:
  path : str
     The path of the file to wrap
  field_storage: FileStorage
     The FileStorage instance to wrap
  temporary: bool
     Whether or not to delete the file when the File instance is destructed

I would try out if sphix supports it. If it doesn’t you may also consider using epydoc just for that (although it is not that actively maintaned right now).

I don’t think that there is something better than sphinx for documenting python projects at the moment.

To have a clearer docstring my favorite choice is using sphinx together with numpydoc. Based on your example this would look like:

def foo(path, field_storage, temporary):
    """This is function foo

    Parameters
    ----------
    path : str
        The path of the file to wrap
    field_storage : :class:`FileStorage`
        The :class:`FileStorage` instance to wrap
    temporary : bool
        Whether or not to delete the file when the File instance
        is destructed

    Returns
    -------
    describe : type
        Explanation
    ...

    Examples
    --------
    These are written in doctest format, and should illustrate how to
    use the function.

    >>> a=[1,2,3]
    >>> print [x + 3 for x in a]
    [4, 5, 6]
    ...
    """

    pass

(a full example is Here),
HTML output will look like this

I think the structure of the rst-file is clearer and more readable. The guide gives some more information and conventions. The numpydoc extension works with autodoc as well.

Answered By: bmu

you just need to start a new line and add a tap after each variable name. Then it is rendered in several lines with consucutive bold variable names:

Args:
    path (str):
        The path of the file to wrap
    field_storage (FileStorage):
        The FileStorage instance to wrap
    temporary (bool):
        Whether or not to delete the file when the File
        instance is destructed

I have created a Sphinx extension that parses both Google style and NumPy style docstrings, and converts them to standard reStructuredText.

To use it, simply install it:

$ pip install sphinxcontrib-napoleon 

And enable it in conf.py:

# conf.py

# Add autodoc and napoleon to the extensions list
extensions = ['sphinx.ext.autodoc', 'sphinxcontrib.napoleon']

More documentation on napoleon here.

Answered By: Relentless Idiot