Skip to content

Commit

Permalink
update docstrings instructions to numpy
Browse files Browse the repository at this point in the history
  • Loading branch information
vict0rsch committed Feb 21, 2024
1 parent 4ea9ad0 commit 3fff69a
Showing 1 changed file with 168 additions and 70 deletions.
238 changes: 168 additions & 70 deletions docs/contributors/write-docstrings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ In the :doc:`previous section </contributors/write-documentation>`, we learned a

.. note::

There are two main conventions for writing docstrings: `Numpy <https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy>`_ and `Google <https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html#example-google>`_. The latter (Google) is more popular in the Python community, but the former (Numpy) is more popular in the scientific Python community. We recommend the Google style as it is more readable, easier to write and `used by PyTorch <https://pytorch.org/docs/stable/_modules/torch/nn/modules/activation.html#PReLU>`_, but both are fine.
There are two main conventions for writing docstrings: `Numpy <https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy>`_ and `Google <https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html#example-google>`_. The latter (Google) is more popular in the Python community, but the former (Numpy) is more popular in the scientific Python community.

We use the |numpy|_ **convention** for the |gflownet|_ project.

First, start with a one-line summary that gives an overview of the functionality, in Google docstring style:

Expand All @@ -30,25 +32,29 @@ First, start with a one-line summary that gives an overview of the functionality
Extended description of function.
Args:
arg1 (int): Description of arg1
arg2 (str): Description of arg2
Returns:
bool: Description of return value
Parameters
----------
arg1 : int
Description of arg1
arg2 : str
Description of arg2
Returns
-------
bool
Description of return value
"""
return True
The one-line summary should be short and concise. It should not mention the function's arguments or return values, since they are described in more detail in the ``Args`` and ``Returns`` sections.
The one-line summary should be short and concise. It should not mention the function's arguments or return values, since they are described in more detail in the ``Parameters`` and ``Returns`` sections.

The first line should be followed by a blank line. The docstring should describe the function's behavior, not its implementation, *i.e.* **what** it does, not **how**.

The ``Args`` and ``Returns`` sections should list each argument and return value, along with a description of its type and purpose.
The ``Parameters`` and ``Returns`` sections should list each argument and return value, along with a description of its type and purpose.

The ``Returns`` section should also describe the type of the return value, if applicable.

For example:
If there are any exceptions that the function can raise, they should be listed in a ``Raises`` section, along with a description of the circumstances under which they are raised. For example:

.. code-block:: python
Expand All @@ -57,17 +63,28 @@ For example:
Extended description of function.
Args:
arg1 (int): Description of arg1
arg2 (str): Description of arg2
Returns:
bool: Description of return value
Parameters
----------
arg1 : int
Description of arg1
arg2 : str
Description of arg2
Returns
-------
bool
Description of return value
Raises
------
ValueError
If arg1 is equal to arg2
"""
if arg1 == arg2:
raise ValueError('arg1 must not be equal to arg2')
return True
If there are any exceptions that the function can raise, they should be listed in a ``Raises`` section, along with a description of the circumstances under which they are raised. For example:
If there are any examples of how to use the function, they should be listed in an ``Examples`` section. Separate groups of examples with empty lines. For instance:

.. code-block:: python
Expand All @@ -76,87 +93,157 @@ If there are any exceptions that the function can raise, they should be listed i
Extended description of function.
Args:
arg1 (int): Description of arg1
arg2 (str): Description of arg2
Examples
--------
>>> function(1, 'a')
True
>>> function(1, 2)
True
>>> function(1, 1)
Traceback (most recent call last):
...
Returns:
bool: Description of return value
Parameters
----------
arg1 : int
Description of arg1
arg2 : str
Description of arg2
Raises:
ValueError: If arg1 is equal to arg2
Returns
-------
bool
Description of return value
Raises
------
ValueError
If arg1 is equal to arg2
"""
if arg1 == arg2:
raise ValueError('arg1 must not be equal to arg2')
return True
If there are any examples of how to use the function, they should be listed in an ``Examples`` section. For example:
The ``Examples`` section should contain code that can be executed by the user to demonstrate how to use the function.

.. code-block:: python
Importantly, if you need maths in your docstrings, you can use LaTeX to write equations between single `$` for inline equations and between double `$$` for block equations.

def function(arg1, arg2):
"""Summary line.
.. important::

Extended description of function.
If you want to use LaTeX in your docstrings, you need to use raw strings `r"...""` for `\` to be appropriately interpreted. Alternatively you must double them `\\`. For example:

.. code-block:: python
Args:
arg1 (int): Description of arg1
arg2 (str): Description of arg2
r"""
Summary line with inline $1+1=3$ math.
Returns:
bool: Description of return value
$$
\int_0^1 x^2 dx = \frac{1}{3}
$$
Raises:
ValueError: If arg1 is equal to arg2
...
""""
Notes:
Do not use this function if arg1 is equal to arg2.
Or

Examples:
>>> function(1, 'a')
True
.. code-block:: python
"""
if arg1 == arg2:
raise ValueError('arg1 must not be equal to arg2')
return True
Summary line with inline $1+1=3$ math.
$$
\\int_0^1 x^2 dx = \\frac{1}{3}
$$
...
"""
This is because the `r` before the triple quotes tells Python that the string is a raw string, which means that backslashes are treated as literal backslashes and not as escape characters.

The ``Examples`` section should contain code that can be executed by the user to demonstrate how to use the function. The code should be indented by four spaces.
.. _write docstrings-extended:

If there are any references that the user should be aware of, they should be listed in a ``References`` section. For example:
Full Example
------------

The following code renders as: :py:func:`gflownet.utils.common.example_documented_function`.

.. code-block:: python
def function(arg1, arg2):
"""Summary line.
def example_documented_function(arg1, arg2):
r"""Summary line: this function is not used anywhere, it's just an example.
Extended description of function.
Extended description of function from the docstrings tutorial :ref:`write
docstrings-extended`.
Refer to
* functions with :py:func:`gflownet.utils.common.set_device`
* classes with :py:class:`gflownet.gflownet.GFlowNetAgent`
* methods with :py:meth:`gflownet.envs.base.GFlowNetEnv.get_action_space`
* constants with :py:const:`gflownet.envs.base.CMAP`
Prepenend with ``~`` to refer to the name of the object only instead of the full
path -> :py:func:`~gflownet.utils.common.set_device` will display as ``set_device``
instead of the full path.
Great maths:
.. math::
\int_0^1 x^2 dx = \frac{1}{3}
.. important::
A docstring with **math** MUST be a raw Python string (a string prepended with
an ``r``: ``r"raw"``) to avoid backslashes being treated as escape characters.
Args:
arg1 (int): Description of arg1
arg2 (str): Description of arg2
Alternatively, you can use double backslashes.
Returns:
bool: Description of return value
.. warning::
Raises:
ValueError: If arg1 is equal to arg2
Display a warning. See :ref:`learn by example`. (<-- this is a cross reference,
learn about it `here
<https://www.sphinx-doc.org/en/master/usage/referencing.html#ref-rolel>`_)
Notes:
Do not use this function if arg1 is equal to arg2.
Examples:
>>> function(1, 'a')
True
Examples
--------
>>> function(1, 'a')
True
>>> function(1, 2)
True
References:
- https://example.com
- https://example.com
>>> function(1, 1)
Traceback (most recent call last):
...
Notes
-----
This block uses ``$ ... $`` for inline maths -> $e^{\frac{x}{2}}$.
Or ``$$ ... $$`` for block math instead of the ``.. math:`` directive above.
$$\int_0^1 x^2 dx = \frac{1}{3}$$
Parameters
----------
arg1 : int
Description of arg1
arg2 : str
Description of arg2
Returns
-------
bool
Description of return value
"""
if arg1 == arg2:
raise ValueError('arg1 must not be equal to arg2')
raise ValueError("arg1 must not be equal to arg2")
return True
So many rules, how can I check?
Expand All @@ -170,9 +257,20 @@ There's an easy way to check: use a tool called `pydocstyle <https://www.pydocst
$ pip install pydocstyle
``pydocstyle`` checks that your docstrings follow the `Google docstring style <https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html#example-google>`_.
``pydocstyle`` checks that your docstrings follow the `Numpy docstring style <https://numpydoc.readthedocs.io/en/latest/format.html>`_.

.. code-block:: bash
$ pydocstyle --convention=google --add-ignore=D212 gflownet/my_module.py
$ pydocstyle --convention=google --add-ignore=D212 gflownet/
$ pydocstyle --convention=numpy --add-ignore=D212 gflownet/my_module.py
$ pydocstyle --convention=numpy --add-ignore=D212 gflownet/
..
This is a comment.
LINKS SECTION ⬇️

.. |numpy| replace:: **Numpy**
.. _numpy: https://numpydoc.readthedocs.io/en/latest/format.html

.. |gflownet| replace:: ``gflownet``
.. _gflownet: :py:mod:`gflownet`

0 comments on commit 3fff69a

Please sign in to comment.