How to write documentation

In this document you will learn how to write good, informative, pretty and actionable documentation.

It’s not hard!

Tip

New to documentation? Start with the Quick Start for Documentation Contributors below, then dive into the details.

Quick Start for Documentation Contributors

Want to contribute but not sure where to start? Here are the most common documentation tasks:

  1. Fix a typo or improve existing text: Just edit the .rst file and submit a PR

  2. Add a new tutorial: Create a new .rst file in docs/source/tutorials/

  3. Improve code documentation: Edit the docstrings in the Python files

  4. Test your changes locally: See Building Documentation Locally below

Building Documentation Locally

To write documentation or test your changes, you’ll want to build the documentation locally on your computer and open the generated HTML files in your browser.

Install documentation dependencies:

pip install -r docs/requirements-docs.txt

Build the documentation:

cd docs/
make html

View the documentation:

Open the generated docs/_build/html/index.html file in your browser:

# On most systems:
open docs/_build/html/index.html

# Or use a simple HTTP server:
cd docs/_build/html
python -m http.server 8000
# Then visit http://localhost:8000

Note

The repository is currently setup to automatically build the documentation on every push to specific branches, including the main branch. Ask the maintainers if you want your branch to be automatically built too.

Overview

There are two major types of documentation:

  1. docstrings: your code’s docstrings will be automatically parsed by the documentation sofware (Sphinx, more in About Sphinx).

  2. Manual documentation such as this document. This can be for instance a detailed installation procedure, a tutorial, a FAQ, a contributor’s guide etc. you name it!

Both are written in ReStructured Text (.rst) format.

In this tutorial, we’ll go over the basics of .rst and Sphinx, and then we’ll look at some of the cool features that are available. To learn about docstrings specifically (what the conventions are, how to write good docstrings etc.), check out the next section.

Some of the great features of using Sphinx is to be able to automatically generate documentation from your code’s docstrings, and to be able to link to other parts of the documentation.

For instance: trajectorybalance_loss() or to an external function torch.cuda.synchronize().

Learn by example

The next section will introduce many of the cool features of .rst + Sphinx + plugins.

Click on “Code for the example” to look at the .rst code that generated what you are reading.

Include code to illustrate how to use the package / module / class / method / function etc.

Remember, this works in docstrings and in stand-alone .rst files.

import gflownet

# Create a new instance of the class
my_class = gflownet.MyClass()

# Call a method of the class
my_class.do_something()

# Get an attribute of the class
my_class.attribute

Note

This is a note. You can use it to add notes to your documentation.

Warning

This is a warning. You can use it to add warnings to your documentation.

Cool features:

Reference code docs of:

An actual tutorial on .rst: ReStructured Text for those who know Markdown

Important

Check out this documentation for more on the specific so-called admonitions like the “note”, “warning”, “important”, etc. coloured boxes in this document: Furo theme documentation

Attention

ReStructured Text is a bit more complicated than Markdown, but it’s worth it. One common mistake is to forget that spaces and new lines matter in .rst. For example, the following will not work:

.. note::
This is a note.

But this will

.. note::

    This is a note.

Same goes for whitespaces: .. code-block::..code-block:: ❌.

Todo

Improving the documentation: Recommendations for Sphinx plugins.

Want to learn more?

You can also have images!

A cute animal

And icons and badges primary, primary-line

Or emphasize a link:

Some Author

Jul 24, 2021

5 min read

This is all documented in sphinx-design.

Include code to illustrate how to use the package / module / class / method / function etc.

Remember, this works in docstrings *and* in stand-alone ``.rst`` files.

.. code-block:: python

    import gflownet

    # Create a new instance of the class
    my_class = gflownet.MyClass()

    # Call a method of the class
    my_class.do_something()

    # Get an attribute of the class
    my_class.attribute

.. note::

    This is a note. You can use it to add notes to your documentation.

.. warning::

    This is a warning. You can use it to add warnings to your documentation.

Cool features:

Reference code docs of:

- A class: :class:`gflownet.envs.grid.Grid` (long format)
- Another class :class:`~gflownet.gflownet.GFlowNetAgent` (short format, by prepending ``~``)
- A method :meth:`~gflownet.gflownet.GFlowNetAgent.trajectorybalance_loss`
- Or even an external function :func:`torch.cuda.synchronize()`

.. note

    External content should be listed in ``docs/conf.py:intersphinx_mapping``.
    More info in the `Read The Docs documentation <https://docs.readthedocs.io/en/stable/guides/intersphinx.html>`_.

An actual tutorial on ``.rst``:
`ReStructured Text for those who know Markdown <https://docs.open-mpi.org/en/v5.0.x/developers/rst-for-markdown-expats.html#hyperlinks-to-urls>`_

.. important::

    Check out this documentation for more on the specific so-called *admonitions* like
    the "note", "warning", "important", etc. coloured boxes in this document:
    `Furo theme documentation <https://pradyunsg.me/furo/reference/admonitions/#supported-types>`_

.. attention::

    ReStructured Text is a bit more complicated than Markdown, but it's worth it.
    **One common mistake** is to forget that spaces and new lines matter in ``.rst``.
    For example, the following will not work:

    .. code-block::

        .. note::
        This is a note.

    But this will

    .. code-block::

        .. note::

            This is a note.

    Same goes for whitespaces: ``.. code-block::````..code-block::`` ❌.


.. todo::

    Improving the documentation: `Recommendations for Sphinx plugins <https://pradyunsg.me/furo/recommendations/>`_.

.. dropdown::  :octicon:`megaphone` Want to learn more?

    You can also have images!

    .. image:: https://source.unsplash.com/200x200/daily?cute+animals
        :alt: A cute animal

    And icons :octicon:`project` and badges :bdg-primary:`primary`, :bdg-primary-line:`primary-line`

    Or emphasize a link:

    .. article-info::
        :avatar: https://raw.githubusercontent.com/tristandeleu/jax-dag-gflownet/master/_assets/dag_gflownet.png
        :avatar-link: https://www.youtube.com/watch?v=dQw4w9WgXcQ
        :avatar-outline: muted
        :author: Some Author
        :date: Jul 24, 2021
        :read-time: 5 min read
        :class-container: sd-p-2 sd-outline-muted sd-rounded-1

    This is all documented in `sphinx-design <https://sphinx-design.readthedocs.io/en/furo-theme>`_.

Note

The above tabulation with “Full-fledged .rst example” and Code for the example was generated using the following code:

.. tab-set::

    .. tab-item:: Full-fledged ``.rst`` example

        .. include:: example.rst

    .. tab-item:: Code for the example

        .. literalinclude:: example.rst
            :language: rst

FAQ

How do I create new manual documentation files.
  • Create a new .rst file in the docs/ folder

  • List it in docs/index.rst file under the .. toctree:: directive

  • Or create a subfolder in docs/ with an index.rst file.
    • This is useful for grouping documentation files together.

    • docs/{your_subfolder}/index.rst should contain a .. toctree:: directive listing the files in the subfolder.

    • It should also be listed in the docs/index.rst under the .. toctree:: directive to appear on the left handside of the documentation.

You can look at the docs/contributors/ folder for an example.

How do I document a sub-package like gflownet.proxy.crystals?

Just add a docstring at the top of the __init__.py file of the sub-package:

"""
This is the docstring of the sub-package.

It can contain any kind of ``.rst`` syntax.

And refer to its members: :meth:`~gflownet.proxy.crystals.crystal.Stage`

.. note::

    This is a note admonition.

"""

You can similarly document a module by adding a docstring at the top of the file

How do I document a module variable?

Add a docstring below the variable to document like

MY_VARIABLE = 42
"""
This is the docstring of the variable.

Again, It can contain any kind of ``.rst`` syntax.
"""
How do I document a class?

Currently, autoapi is setup to consider the documention of a class to be the same as the documentation for the __init__ method of the class.

This can be modified by changing the autoapi_python_class_content = "init" configuration variable in docs/conf.py. See AutoAPI for more details.

( advanced) How do I modify the main API Reference page?

The main page (that lists sub-modules and packages etc.) is generated by autoapi, using a template file docs/_templates/autoapi/index.rst.

Modify this file to change the main API Reference page.

Important

You will notice {% ... %} blocks. These are Jinja2 blocks, a templating language. You can modify them, but be careful not to break the template.

( advanced) How do I modify the structure of the class / method / package / module etc. pages?

The structure of the pages is defined by the autoapi template files in docs/_templates/autoapi/.

Modify these files to change the structure of the pages.

Important

You will notice {% ... %} blocks. These are Jinja2 blocks, a templating language. You can modify them, but be careful not to break the template.

Where is the documentation for those advanced features? (tabs, dropdowns etc.)
  • Sphinx-Design contains many components you can re-use

  • We use the Furo theme, you’ll find the list of available admonitions there

What plugins are used to make the documentation?
  • Todo enables the .. todo:: admonition

  • Intersphinx mapping enables linking to external documentation like in the torch.cuda.synchronize() example above

  • AutoAPI enables the automatic generation of documentation from docstrings & package structure

  • Sphinx Math Dollar enables the $...$ math syntax

  • Sphinx autodoc type ints enables more fine-grained control on how types are displayed in the docs

  • MyST enables the parsing of enhanced Markdown syntax in the .rst documentation.

  • Hover X Ref Enables tooltips to display contents on the hover of links

  • Napoleon enables the parsing of Google-style docstrings

About Sphinx

Sphinx is a documentation generator. It works by parsing .rst files and generating HTML files from them.

It is configured by the docs/conf.py file.

To simplify the generation of documentation, we use the AutoAPI plugin, which automatically generates documentation from the package’s structure and the docstrings of the code.

AutoAPI reads the code, and generates .rst files in the docs/_autoapi folder. These files are then parsed by Sphinx to generate the documentation but to keep the documentation clean, we don’t want to commit these files to the repository so autoapi is configured to delete those .rst files after generating the documentation.

By default, the generated documentation will be put in the API Reference section of the overall documentation.