DocString: A Class to Format Docstrings for Sphinx and Click¶
The comb_utils.lib.docs.DocString class is used to format docstrings for Sphinx API docs and Click CLI help docs. It’s useful when you have multiple functions that should have the same docstring, such as when you have a public API function and a CLI function that call the same underlying code.
DocString takes an opening docstring, an arg dict, a default dict, a list of returns text, and a list of comb_utils.lib.docs.ErrorDocString objects. It has three important members that you can use:
- api_docstring:
Docstring formatted for Sphinx API docs.
- cli_docstring:
Docstring formatted for Click.
- args:
Simply the arg dict you pass when you initialize the
DocStringobject.
The main difference between api_docstring and cli_docstring is that cli_docstring excludes the args block. CLI args help is picked up by Click in the click.option decorators’ help arguments, to which you can pass the values in args.
Example usage:
from comb_utils import DocString, ErrorDocString
ADD_EM_DOCSTRING = DocString(
opening_docstring="A function to add two numbers.",
args={
"a": "The first number. Must be greater than 0.",
"b": "The second number. Must be less than 100."
},
returns=["The sum of the two numbers."],
error_docstrings=[
ErrorDocString(
error_type="ValueError",
docstring="If `a` is less than 0."
),
ErrorDocString(
error_type="ValueError",
docstring="If `b` is greater than 100."
)
]
defaults={
"a": 1,
"b": 99
},
)
Now you can use docstring.api_docstring in your functions, and docstring.cli_docstring and args in your Click commands.
Using docstring.api_docstring in a function:
def add_em(a: int = ADD_EM_DOCSTRING.defaults["a"], b: int = ADD_EM_DOCSTRING.defaults["b"]) -> int:
if a < 0:
raise ValueError("a must be greater than 0.")
if b > 100:
raise ValueError("b must be less than 100.")
return a + b
add_em.__doc__ = ADD_EM_DOCSTRING.api_docstring
Now your Sphinx API docs will have the correct docstring for add_em.
Using docstring.cli_docstring and args in a Click command:
import click
from my_package import ADD_EM_DOCSTRING, add_em
@click.command(help=ADD_EM_DOCSTRING.cli_docstring)
@click.option("--a", type=int, help=ADD_EM_DOCSTRING.args["a"])
@click.option("--b", type=int, help=ADD_DOADD_EM_DOCSTRINGCSTRING.args["b"])
def main(a: int, b: int):
the_sum = add_em(a=a, b=b)
click.echo(the_sum)
Now your CLI command help will have a docstring and args that match the function’s docstring. Say you created an entry point named add_em in your setup.cfg file:
[options.entry_points]
console_scripts =
add_em = my_package.cli.add_em:main
Then, when you run add_em --help, you’ll see the correct help doc:
$ add_em --help
Usage: add_em [OPTIONS]
A function to add two numbers.
Raises:
ValueError: If `a` is less than 0.
ValueError: If `b` is greater than 100.
Returns:
The sum of the two numbers.
Options:
--a INTEGER The first number. Must be greater than 0.
--b INTEGER The second number. Must be less than 100.
--help Show this message and exit.
You can even use the sphinx-click extension’s click directive to include the Click help doc within the CLI module itself, and it’s not a problem that it’s a circular reference. This is useful for keeping the Sphinx’ CLI docs in sync with the CLI’s help doc. It’s not really a feauture of DocString, but it’s worth mentioning here:
__doc__ = """
.. click:: my_package.cli.add_em:main
:prog: add_em
:nested: full
"""
import click
from my_package import ADD_EM_DOCSTRING, add_em
@click.command(help=ADD_EM_DOCSTRING.cli_docstring)
@click.option("--a", type=int, help=ADD_EM_DOCSTRING.args["a"])
@click.option("--b", type=int, help=ADD_DOADD_EM_DOCSTRINGCSTRING.args["b"])
def main(a: int, b: int):
the_sum = add_em(a=a, b=b)
click.echo(the_sum)