Documenting a Python function with a docstring that is both readable in raw form and produces good sphinx output

StackOverflow https://stackoverflow.com/questions/23448807

  •  14-07-2023
  •  | 
  •  

Question

I have a Python application. I am using Sphinx with the autodoc extension to generate docs for it. In documenting function arguments, I see two main options:

Option 1

def makeBaby(mommy, daddy):
  """Execute the miracle of life.

  Args:
    mommy: description of mommy
    daddy: description of daddy
  """

enter image description here

Option 2

def makeBaby(mommy, daddy):
  """Execute the miracle of life.

  :param mommy: description of mommy
  :param daddy: description of daddy
  """

enter image description here

Note that option 2 cannot be nested under a header like "Args", as in option 1, without breaking the rendered output. Option 2 has much better rendered output than option 1, but makes the actual docstrings much less readable. Why should param need to be written a trillion times? Option 1 (from Google's Python style guide) provides much better docstrings, but the rendered output is poor. Does there exist a standard for function docstrings that produces both a clean raw docstring and good rendered output?

Was it helpful?

Solution

You can use the numpy docstrings format and numpydoc to have clear readable docstrings, plus a nice sphinx output.

Install numpydoc:

pip install numpydoc

Add 'numpydoc' to your conf.py in extensions.

extensions = ['sphinx.ext.autodoc',
              'numpydoc']

Then your docstrings would follow the numpy format. You can read more about the layout in the docs. For your example:

def makeBaby(mommy, daddy):
   """Execute the miracle of life.

   Parameters
   ----------
   mommy : description of mommy
   daddy : description of daddy

   Returns
   -------
   baby : mommy + daddy

   """
   return mommy + daddy

And in sphinx:

enter image description here

OTHER TIPS

I'm not sure I understand what you mean by

Note that option 2 cannot be nested under a header like "Args"

But actually Option 2 is the standard. It provides everything you need to document your functions/methods etc and, what most importantly, it's syntax is the part of the Sphinx documenting tool and it will be rendered correctly and similarly by any compliant parser. For example, consider how we can document this big class method with Option 2 (this is a copy'n'paste from a rst file but you can easily adapt it to paste in a docstring):

.. py:method:: create(**fields)
    :module: redmine.managers.ResourceManager
    :noindex:

    Creates new issue resource with given fields and saves it to the Redmine.

    :param project_id: (required). Id or identifier of issue's project.
    :type project_id: integer or string
    :param string subject: (required). Issue subject.
    :param integer tracker_id: (optional). Issue tracker id.
    :param string description: (optional). Issue description.
    :param integer status_id: (optional). Issue status id.
    :param integer priority_id: (optional). Issue priority id.
    :param integer category_id: (optional). Issue category id.
    :param integer fixed_version_id: (optional). Issue version id.
    :param boolean is_private: (optional). Whether issue is private.
    :param integer assigned_to_id: (optional). Issue will be assigned to this user id.
    :param watcher_user_ids: (optional). User ids who will be watching this issue.
    :type watcher_user_ids: list or tuple
    :param integer parent_issue_id: (optional). Parent issue id.
    :param start_date: (optional). Issue start date.
    :type start_date: string or date object
    :param due_date: (optional). Issue end date.
    :type due_date: string or date object
    :param integer estimated_hours: (optional). Issue estimated hours.
    :param integer done_ratio: (optional). Issue done ratio.
    :param list custom_fields: (optional). Custom fields in the form of [{'id': 1, 'value': 'foo'}].
    :param uploads:
      .. raw:: html

          (optional). Uploads in the form of [{'': ''}, ...], accepted keys are:

      - path (required). Absolute path to the file that should be uploaded.
      - filename (optional). Name of the file after upload.
      - description (optional). Description of the file.
      - content_type (optional). Content type of the file.

    :type uploads: list or tuple
    :return: Issue resource object

Which will be rendered as:

screenshot

I hope you can agree that it produces very similar and readable results in both raw and rendered form.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top