Customizing the help using the docstring

Clize draws the text of the --help output from your function’s docstring. In addition, it will draw documenation for parameters added by decorators from the function that defined it.

The recommended way of formatting parameters is just like you would when using Sphinx’s autodoc. The format is explained with examples below. For those who are already familiar with it, there are a few notable differences:

  • Formatting (bold, italics, etc), tables and bullet points are ignored. Instead, the text will appear plainly.
  • Clize will follow the order of parameters you provide in the docstring, except for positional parameters which will always be in the function’s order.
  • Free text between parameters becomes attached to the parameter just before it.
  • You can group parameters together using a paragraph ending in :. These groups are merged together when multiple functions (e.g. decorators) have parameters in the CLI.

There is also a legacy format used by Clize up until version 3.1. Please check Clize 3.1’s documentation documentation for specifics.

Regardless of which format you use to format docstrings, Clize will format the docstring to look consistent with typical CLIs.

Documenting parameters

Parameters are documented using the field list syntax:

from clize import run

def func(one, and_two):
    """
    :param one: This documents the parameter called one.
    :param and_two: Documentation for the 'and_two' parameter.
        It may continue on a second line.
    """

run(func)

Begin a line with :param NAME: and contiue with a description for the parameter. You can continue over more lines by indenting the additional lines.

$ python docstring.py --help
Usage: docstring.py one and-two

Arguments:
  one          This documents the parameter called one.
  and-two      Documentation for the 'and_two' parameter.  It may
               continue on a second line.

Other actions:
  -h, --help   Show the help

Clize will show parameter help in the same order as your docstring. However, positional parameters always remain in their original order:

from clize import run

def func(one, two, *, red, green, blue):
    """
    :param two: Two always appears after one
    :param one: One always appears before two
    :param blue: However, you may order keyword parameters any way you like
    :param red: Red is also a keyword parameter
    :param green: And so is green
    """

run(func)
$ python docstring.py --help
Usage: docstring.py [OPTIONS] one two

Arguments:
  one           One always appears before two
  two           Two always appears after one

Options:
  --blue=STR    However, you may order keyword parameters any way you like
  --red=STR     Red is also a keyword parameter
  --green=STR   And so is green

Other actions:
  -h, --help    Show the help

You may add new paragraphs in the parameter descriptions. They will appear as plain paragraphs after the parameter in the output:

from clize import run

def func(one, and_two):
    """
    :param one: Documentation for the first parameter.

        More information about the first parameter.

    :param and_two: Documentation for the second parameter.

        More information about the second parameter.
    """

run(func)
$ python docstring.py --help
Usage: docstring.py one and-two

This is a description of the program.

Arguments:
  one          Documentation for the first parameter.

More information about the first parameter.

  and-two      Documentation for the second parameter.

More information about the second parameter.

Other actions:
  -h, --help   Show the help

These are footnotes about the program.

Description and footnotes

In your CLI’s main function, you can also add paragraphs before and after all the parameter descriptions. They will be used as a description and footnotes for your command:

from clize import run

def func(one, and_two):
    """
    This is a description of the program.

    :param one: Documentation for the first parameter.
    :param and_two: Documentation for the second parameter.

    These are footnotes about the program.
    """

run(func)

It is used to briefly describe what the command does.

Note that you must separate parameter descriptions (:param ...:) away from regular paragraphs. Simply leave a blank line around them.

$ python docstring.py --help
Usage: docstring.py one and-two

This is a description of the program.

Arguments:
  one          Documentation for the first parameter.
  and-two      Documentation for the second parameter.

Other actions:
  -h, --help   Show the help

These are footnotes about the program.

Creating sections

Named parameters can be grouped into sections. You can create a section by having a paragraph end with a colon (:) before a parameter definition:

from clize import run

def func(*, one, and_two, three):
    """
    Great parameters:

    :param and_two: Documentation for the second parameter.
    :param one: Documentation for the first parameter.

    Greater parameters:

    :param three: Documentation for the third parameter.
    """

run(func)
$ python docstring.py --help
Usage: docstring.py [OPTIONS]

Great parameters:
  --and-two=STR   Documentation for the second parameter.
  --one=STR       Documentation for the first parameter.

Greater parameters:
  --three=STR     Documentation for the third parameter.

Other actions:
  -h, --help      Show the help

Unformatted paragraphs

You can insert unformatted text (for instance, code examples) by finishing a paragraph with two colons (::) and indenting the unformatted text:

from clize import run

def func():
    """

    This        text
    is      automatically  formatted.
    However, you may present code blocks like this:

        Unformatted              text

        More    unformatted
        text.

    """
$ python docstring.py --help
Usage: docstring.py

This text is automatically formatted.  However, you may present code blocks
like this::

    Unformatted              text

    More    unformatted
    text.

Other actions:
  -h, --help   Show the help

run(func)

A paragraph with just the double-colon will be omitted from the output, but still trigger unformatted text.

Documentation for composed functions

Clize lets you compose functions with ease through seamless handling of decorators and other Python idioms. As such, parameters in a single CLI (i.e. not in separate commands), may originate from different functions. Clize will search for a parameter’s description in whichever function the parameter comes from.

In short, document every parameter for your CLI exactly where it appears in the source:

from sigtools.wrappers import decorator
from clize import run

def my_decorator(factor):
    """Adds a ``super_number`` parameter to the decorated function.
    The value will be multiplied and passed as ``number`` to the wrapped
    function.

    :param factor: The factor by which to multiply ``super_number``

    Clize will not look at this docstring at all.
    """
    @decorator
    def _decorator(function, *args, super_number, **kwargs):
        """
        :param super_number: A super number.

        Clize will look at the parameter descriptions but ignore the
        description and footnotes.
        """
        return function(*args, number=super_number*factor, **kwargs)
    return _decorator


@my_decorator(3)
def func(number, *, name):
    """Greets someone and gives them a number

    :param name: A name.
    :param number: The number to print.
    """
    return number


run(func)
$ python docstring.py --help
Usage: docstring.py [OPTIONS]

Greets someone and gives them a number

Options:
  --name=STR           A name.
  --super-number=STR   A super number.

Other actions:
  -h, --help           Show the help

This example showcases the use of sigtools.wrappers.decorator. It lets you create decorators without having to worry about the decoration logic. In the example above, _decorator receives func as its function parameter.

Warning

If you’re using your own means to create decorators, be careful to preserve the docstring of the function where the new parameters come from. functools.wraps is especially dangerous in that regard.

You can maintain the advantages of functools.wraps (namely exposing the name and docstring of the inner function on the outer object) by using functools.partial to replicate the same structure as in the previous example:

import functools
from clize import run


def my_decorator(factor):
    """Adds a ``super_number`` parameter to the decorated function.
    The value will be multiplied and passed as ``number`` to the wrapped
    function.

    :param factor: The factor by which to multiply ``super_number``

    Clize will not look at this docstring at all.
    """
    def _decorate(function):
        def _wrapper(function, *args, super_number, **kwargs):
            """
            :param super_number: A super number.

            Clize will look at the parameter descriptions but ignore the
            description and footnotes.
            """
            return function(*args, number=super_number*factor, **kwargs)
        ret = functools.partial(_wrapper, function)
        # update_wrapper does the same thing as wraps
        functools.update_wrapper(ret, function)
        return ret
    return _decorate


@my_decorator(3)
def func(number, *, name):
    """Greets someone and gives them a number

    :param name: A name.
    :param number: The number to print.
    """
    return number


run(func)

Overriding the documentation for decorators

The main function can override the description for parameters in any of its decorators:

from sigtools.wrappers import decorator
from clize import run


@decorator
def my_decorator(function, *args, option, other_opt, **kwargs):
    """
    :param other_opt: option is documented in my_decorator
    :param option: option is also documented in my_decorator
    :param arg: my_decorator cannot override parameters from func
    """
    return function(*args, **kwargs)


@my_decorator
def func(arg):
    """
    :param arg: arg is documented in the main function
    :param option: option is overriden in the main function
    """
    return arg


run(func)
Usage: docstring.py [OPTIONS] arg

Arguments:
  arg               arg is documented in the main function

Options:
  --option=STR      option is overriden in the main function
  --other-opt=STR   option is documented in my_decorator

Other actions:
  -h, --help        Show the help

Order of parameters in composed functions

Clize displays parameter descriptions in the following order:

  1. Parameters documented (or overriden) in the main function, i.e. the deepest function that has the name of the outermost object.
  2. Parameters from the other functions, from outermost decorator to innermost decorator.
  3. Parameters from functions called by the main function, from outermost to innermost.

Parameter sections are ordered according to their first parameter, with the default section first.

from sigtools.wrappers import decorator
from clize import run


@decorator
def decorator_1(function, *args, opt_1, opt_override, **kwargs):
    """
    :param opt_1: option 1
    :param opt_override: will be overriden in func
    """
    return function(*args, **kwargs)


@decorator
def decorator_2(function, *args, opt_2, **kwargs):
    """
    :param opt_2: option 2
    """
    return function(*args, **kwargs)


@decorator
def decorator_3(function, *args, opt_3, **kwargs):
    """
    :param opt_3: option 3
    """
    return function(*args, **kwargs)


def called_by_main(*, delegate_opt):
    """
    :param delegate_opt: option in function called by main function
    """
    pass


@decorator_1
@decorator_2
@decorator_3
def func(*args, main, **kwargs):
    """
    main function

    :param main: parameter in main function
    :param opt_override: parameter overriden in main function
    """
    return called_by_main(*args, **kwargs)


run(func)
$ python docstring.py --help
Usage: docstring.py [OPTIONS]

main function

Options:
  --main=STR           parameter in main function
  --opt-override=STR   parameter overriden in main function
  --opt-1=STR          option 1
  --opt-2=STR          option 2
  --opt-3=STR          option 3
  --delegate-opt=STR   option in function called by main function

Other actions:
  -h, --help           Show the help