create subcommand-based CLI programs with docopt
Project description
docopt-subcommands
A simple implementation of subcommands for docopt.
docopt-subcommands
allows you to create subcommand-based programs
using docopt. A subcommand-based program is
one in which the main program uses a "subcommand" argument to tell it what to
do.
The classic example of such a program is git. The git
command with no arguments doesn't do much of anything. Instead, it's the first
argument to git
- the subcommand - that tells it what to actually do. For
example:
git log
will give you the log for your repository. Likewise:
git rebase
is the subcommand for rebasing.
docopt-subcommands
is here to help you create similar kinds of command-line
tools with docopt
'.
Quickstart
The basic idea behind docopt-subcommands
is simple:
- You provide a separate handler function for each subcommand.
- The docstring for each handler function defines the docopt definition for that subcommand.
- You register your handler functions with the names of the subcommands which will invoke them.
- You provide a program name and (optionally) a top-level documentation string.
Then docopt-subcommands
does the work of stitching everything together into a
subcommand-driven program. Here's how it looks (from the included
exampels/basic_example.py
):
# Basic, most common usage of docopt_subcommands
import docopt_subcommands as dsc
# 1. Use the `command` decorator to add subcommands functions.
@dsc.command()
def foo_handler(precommand_args, args):
"""usage: {program} foo <name>
Apply foo to a name.
"""
print("Foo, {}".format(args['<name>']))
@dsc.command()
def bar_handler(precommand, args):
"""usage: {program} bar <name>
Apply bar to a name.
"""
print("Bar, {}".format(args['<name>']))
# 2. Pass a program name and version string to `main` to run a program with the
# subcommands you defined with the decorators above.
dsc.main(program='docopt-subcommand-example')
If you run this program at the command line you'll see that you have a nice, subcommand-based CLI program:
$ python basic_example.py
Usage: docopt-subcommand-example [options] <command> [<args> ...]
$ python basic_example.py -h
docopt-subcommand-example
Usage: docopt-subcommand-example [options] <command> [<args> ...]
Options:
-h --help Show this screen.
Available commands:
bar
foo
See 'docopt-subcommand-example help <command>' for help on specific commands.
$ python basic_example.py foo
usage: docopt-subcommand-example foo <name>
$ python basic_example.py foo -h
usage: docopt-subcommand-example foo <name>
Apply foo to a name.
$ python basic_example.py foo Bubba
Foo, Bubba
For more examples, see the examples
directory.
Common options
Many subcommand-based programs have a set of options that are common to all commands. A common example is --verbose
which causes the program to print more information not matter which command is executed. With docopt_subcommands
you specify these common options in the top-level docstring like this::
TOP_LEVEL_DOC = """{program}
Usage: {program} [options] [ ...]
Options: -h --help Show this screen --verbose Use verbose output
Available commands: {available_commands} """
With this docstring, you can provide the --verbose
flag for any subcommand. Critically, common options must be provided before the subcommand name. So if bar
was a subcommand in your program, you would write::
my_program --verbose bar
but not::
my_program bar --verbose
docopt_subcommands
parses the complete command line in two passes. The first pass parses it with the top-level
docstring while the second pass uses the docstring for the specific command and only parses the part of the command line
after the common options. It then provides both of the parsed dicts to the subcommand handler: the first argument to the
handler is the result of the first pass, and the second argument is the result of the second pass.
With this system, you can then use a single set of code to do "common configuration" for you program. For example, here's how a handler might look:
.. code-block:: python
@dsc.command() def bar_handler(precommand_args, args): """usage: {program} bar
Apply bar to a name.
"""
handle_common_option(precommand_args)
name = args['<name>']
print('Bar {}'.format(name))
Advanced usage
For most users the basic usage described in "Quickstart" should be all you need,
but some users will need more control of docopt_subcommands
. The
docopt_subcommands.main()
that we used earlier is really just a convenience
layer on top of the real workhorse, docopt_subcommands.Subcommands
. You can
instantiate this class directly, bypassing main()
, and interact with it as you
need before actually invoke command-line processing.
For the most part, the arguments to the Subcommands
initializer are very
similar to those to main()
. This reflects the fact that main()
really just
instantiates a Subcommands
instance (if you don't provide one), populates it
with commands, and calls it with the command line arguments. You can do all of
these steps yourself if you need to.
As an example, here's what the basic example above looks like if you construct a
Subcommands
instance directly.:
import docopt_subcommands as dsc
import sys
sc = dsc.Subcommands(program='docopt-subcommand-example')
@sc.command('foo')
def foo_handler(args):
"""usage: {program} {command} <name>
Apply foo to a name.
"""
print("Foo, {}".format(args['<name>']))
@sc.command('bar')
def bar_handler(args):
"""usage: {program} {command} <name>
Apply bar to a name.
"""
print("Bar, {}".format(args['<name>']))
sc(sys.argv[1:])
As you can see, it's not substantially different from the basic example.
main()
primarily just adds a layer of convenience - mostly by choosing
reasonable default values for some things - that you lose with this approach.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file docopt_subcommands-4.0.0.tar.gz
.
File metadata
- Download URL: docopt_subcommands-4.0.0.tar.gz
- Upload date:
- Size: 8.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e511c33f96474d754333617009443b1641c24e7614d051f8c0d5746670d2243a |
|
MD5 | 91e4472a7e28f8094d684e53ff9a76ad |
|
BLAKE2b-256 | 599f90aa411d8d599b7e5c5d68742a03922242d576b770837a7517309fde14c6 |
File details
Details for the file docopt_subcommands-4.0.0-py2.py3-none-any.whl
.
File metadata
- Download URL: docopt_subcommands-4.0.0-py2.py3-none-any.whl
- Upload date:
- Size: 7.4 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5cbad12756b8429b8d5069306881fe87d3f135c71d8e85088deb64a13229e908 |
|
MD5 | 11b5c1a9e8c6e726d7d067fc2183ac3c |
|
BLAKE2b-256 | 20e3493d0a477e0b15a77d1e92d97a4447bde79280082b507bb57f3e68e4e064 |