Dispatching to multiple functions

So far the previous part of the tutorial showed you how to use clize to run a single function. Sometimes your program will need to perform different related actions that involve different parameters. For instance, git offers all kinds of commands related to managing a versioned code repository under the git command. Alternatively, your program could have one main function and a few auxiliary ones, for instance for verifying the format of a config file, or simply for displaying the program’s version.

Alternate actions

These allow you to provide auxiliary functions to your program while one remains the main function. Let’s write a program with an alternate command triggered by --version that prints the version.

Here are the two functions we could have: do_nothing will be the main function while version will be provided as an alternate command.

VERSION = "0.2"

def do_nothing():
    """Does nothing"""
    return "I did nothing, I swear!"

def version():
    """Show the version"""
    return 'Do Nothing version {0}'.format(VERSION)

You use run as usual for the main function, but specify the alternate command in the alt= parameter:

from clize import run

run(do_nothing, alt=version)

The version function will be available as --version:

$ python3 examples/altcommands.py --help
Usage: examples/altcommands.py

Does nothing

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

You can specify more alternate commands in a list. For instance,

def build_date(*, show_time=False):
    """Show the build date for this version"""
    print("Build date: 17 August 1979", end='')
    if show_time:
        print(" afternoon, about tea time")

run(do_nothing, alt=[version, build_date])

You can instead use a dict to specify their names if those automatically drawn from the function names don’t suit you:

run(do_nothing, alt={
    'totally-not-the-version': version,
    'birthdate': build_date
$ python3 examples/altcommands.py --help
Usage: examples/altcommands.py

Does nothing

Other actions:
  --birthdate   Show the build date for this version
  -h, --help    Show the help
                Show the version

Using a collections.OrderedDict instance rather than dict will guarantee the order they appear in the help is the same as in the source.

Multiple commands

This allows you to keep multiple commands under a single program without singling one out as the main one. They become available by naming the subcommand directly after the program’s name on the command line.

Let’s see how we can use it in a mock todo list application:

def add(*text):
    """Adds an entry to the to-do list.

    :param text: The text associated with the entry.
    return "OK I will remember that."

def list_():
    """Lists the existing entries."""
    return "Sorry I forgot it all :("

You can specify multiple commands to run by passing each function as an argument to run:

from clize import run

run(add, list_)
$ python3 examples/multicommands.py add A very important note.
OK I will remember that.
$ python3 examples/multicommands.py list
Sorry I forgot it all :(

Alternatively, as with alternate commands, you can pass in an iterable of functions, a dict or an OrderedDict. If you pass an iterable of functions, name conversion will apply.

run({ 'add': add, 'list': list_, 'show': list_ })

Because it isn’t passed a regular function with a docstring, Clize can’t determine an appropriate description from a docstring. You can explicitly give it a description with the description= parameter. Likewise, you an add footnotes with the footnotes= parameter. The format is the same as with other docstrings, just without documentation for parameters.

run(add, list_, description="""
    A reliable to-do list utility.

    Store entries at your own risk.
$ python3 examples/multicommands.py --help
Usage: examples/multicommands.py command [args...]

A reliable to-do list utility.

Store entries at your own risk.

  add    Adds an entry to the to-do list.
  list   Lists the existing entries.

Often, you will need to share a few characteristics, for instance a set of parameters, between multiple functions. See how Clize helps you do that in Function compositing.