Including descriptions and documentation
When we have a useful script, we often need to leave notes for ourselves—and others—on what it does, how it solves some particular problem, and when it should be used.
Because clarity is important, there are some formatting recipes that can help make the documentation very clear. This recipe also contains a suggested outline so that the documentation will be reasonably complete.
Getting ready
If we've used the Writing Python script and module files – syntax basics recipe to build a script file, we'll have to put a small documentation string in our script file. We'll expand on this documentation string in this recipe.
There are other places where documentation strings should be used. We'll look at these additional locations in Chapter 3, Function Definitions, and Chapter 7, Basics of Classes and Objects.
We have two general kinds of modules for which we'll be writing summary docstrings:
- Library modules: These files will contain mostly function definitions as well as class definitions. In this case, the docstring summary can focus on what the module is more than what it does. The docstring can provide examples of using the functions and classes that are defined in the module. In Chapter 3, Function Definitions, and Chapter 7, Basics of Classes and Objects, we'll look more closely at this idea of a package of functions or classes.
- Scripts: These are files that we generally expect will do some real work. In this case, we want to focus on doing rather than being. The docstring should describe what it does and how to use it. The options, environment variables, and configuration files are important parts of this docstring.
We will sometimes create files that contain a little of both. This requires some careful editing to strike a proper balance between doing and being. In most cases, we'll provide both kinds of documentation.
How to do it...
The first step in writing documentation is the same for both library modules and scripts:
- Write a brief summary of what the script or module is or does. The summary doesn't dig too deeply into how it works. Like a lede in a newspaper article, it introduces the who, what, when, where, how, and why of the module. Details will follow in the body of the docstring.
The way the information is displayed by tools like Sphinx
and pydoc
suggests a specific style for the summaries we write. In the output from these tools, the context is pretty clear, therefore it's common to omit a subject in the summary sentence. The sentence often begins with the verb.
For example, a summary like this: This script downloads and decodes the current Special Marine Warning (SMW) for the area AKQ has a needless This script. We can drop that and begin with the verb phrase Downloads and decodes....
We might start our module docstring like this:
"""
Downloads and decodes the current Special Marine Warning (SMW)
for the area 'AKQ'.
"""
We'll separate the other steps based on the general focus of the module.
Writing docstrings for scripts
When we document a script, we need to focus on the needs of a person who will use the script.
- Start as shown earlier, creating a summary sentence.
- Sketch an outline for the rest of the docstring. We'll be using ReStructuredText (RST) markup. Write the topic on one line, then put a line of
=
under the topic to make it a proper section title. Remember to leave a blank line between each topic.Topics may include:
- SYNOPSIS: A summary of how to run this script. If the script uses the
argparse
module to process command-line arguments, the help text produced byargparse
is the ideal summary text. - DESCRIPTION: A more complete explanation of what this script does.
- OPTIONS: If
argparse
is used, this is a place to put the details of each argument. Often, we'll repeat theargparse
help parameter. - ENVIRONMENT: If
os.environ
is used, this is the place to describe the environment variables and what they mean. - FILES: Names of files that are created or read by a script are very important pieces of information.
- EXAMPLES: Some examples of using the script are always helpful.
- SEE ALSO: Any related scripts or background information.
Other topics that might be interesting include EXIT STATUS, AUTHOR, BUGS, REPORTING BUGS, HISTORY, or COPYRIGHT. In some cases, advice on reporting bugs, for instance, doesn't really belong in a module's docstring, but belongs elsewhere in the project's GitHub or SourceForge pages.
- SYNOPSIS: A summary of how to run this script. If the script uses the
- Fill in the details under each topic. It's important to be accurate. Since we're embedding this documentation within the same file as the code, it needs to be correct, complete, and consistent.
- For code samples, there's a cool bit of RST markup we can use. Recall that all elements are separated by blank lines. In one paragraph, use
::
by itself. In the next paragraph, provide the code example indented by four spaces.
Here's an example of a docstring for a script:
"""
Downloads and decodes the current Special Marine Warning (SMW)
for the area 'AKQ'
SYNOPSIS
========
::
python3 akq_weather.py
DESCRIPTION
===========
Downloads the Special Marine Warnings
Files
=====
Writes a file, ''AKW.html''.
EXAMPLES
========
Here's an example::
slott$ python3 akq_weather.py
<h3>There are no products active at this time.</h3>
"""
In the Synopsis
section, we used ::
as a separate paragraph. In the Examples
section, we used ::
at the end of a paragraph. Both versions are hints to the RST processing tools that the indented section that follows should be typeset as code.
Writing docstrings for library modules
When we document a library module, we need to focus on the needs of a programmer who will import the module to use it in their code:
- Sketch an outline for the rest of the docstring. We'll be using RST markup. Write the topic on one line. Include a line of = under each topic to make the topic into a proper heading. Remember to leave a blank line between each paragraph.
- Start as shown previously, creating a summary sentence:
- DESCRIPTION: A summary of what the module contains and why the module is useful
- MODULE CONTENTS: The classes and functions defined in this module
- EXAMPLES: Examples of using the module
- Fill in the details for each topic. The module contents may be a long list of class or function definitions. This should be a summary. Within each class or function, we'll have a separate docstring with the details for that item.
- For code examples, see the previous examples. Use
::
as a paragraph or the ending of a paragraph. Indent the code example by four spaces.
How it works...
Over the decades, the man page outline has evolved to contain a complete description of Linux commands. This general approach to writing documentation has proven useful and resilient. We can capitalize on this large body of experience, and structure our documentation to follow the man page model.
These two recipes for describing software are based on summaries of many individual pages of documentation. The goal is to leverage the well-known set of topics. This makes our module documentation mirror the common practice.
We want to prepare module docstrings that can be used by the Sphinx Python Documentation Generator (see http://www.sphinx-doc.org/en/stable/). This is the tool used to produce Python's documentation files. The autodoc
extension in Sphinx will read the docstring headers on our modules, classes, and functions to produce the final documentation that looks like other modules in the Python ecosystem.
There's more...
RST markup has a simple, central syntax rule: paragraphs are separated by blank lines.
This rule makes it easy to write documents that can be examined by the various RST processing tools and reformatted to look extremely nice.
When we want to include a block of code, we'll have some special paragraphs:
- Separate the code from the text with blank lines.
- Indent the code by four spaces.
- Provide a prefix of
::
. We can either do this as its own separate paragraph or as a special double-colon at the end of the lead-in paragraph:Here's an example:: more_code()
- The
::
is used in the lead-in paragraph.
There are places for novelty and art in software development. Documentation is not really the place to push the envelope.
A unique voice or quirky presentation isn't fun for users who simply want to use the software. An amusing style isn't helpful when debugging. Documentation should be commonplace and conventional.
It can be challenging to write good software documentation. There's a broad chasm between too little information and documentation that simply recapitulates the code. Somewhere, there's a good balance. What's important is to focus on the needs of a person who doesn't know too much about the software or how it works. Provide this semi-knowledgeable user with the information they need to describe what the software does and how to use it.
In many cases, we need to separate two parts of the use cases:
- The intended use of the software
- How to customize or extend the software
These may be two distinct audiences. There may be users who are distinct from developers. Each has a unique perspective, and different parts of the documentation need to respect these two perspectives.
See also
- We look at additional techniques in Writing better RST markup in docstrings.
- If we've used the Writing Python script and module files – syntax basics recipe, we'll have put a documentation string in our script file. When we build functions in Chapter 3, Function Definitions, and classes in Chapter 7, Basics of Classes and Objects, we'll look at other places where documentation strings can be placed.
- See http://www.sphinx-doc.org/en/stable/ for more information on Sphinx.
- For more background on the man page outline, see https://en.wikipedia.org/wiki/Man_page