Skip to main content

A command line helper library for extensible subcommands

Project description

A wrapper for argparse that provides decorator-based subcommand support.

Commands can be defined separately from their actual main functions, enabling faster import times.

Basic Usage

from subparse import CLI

class MyApp(object):
    def __init__(self, quiet=False):
        self.quiet = quiet

    def info(self, *msg):
        if not self.quiet:
            print('[info]', *msg)

def context_factory(cli, args):
    return MyApp(args.quiet)

def generic_options(parser):
    parser.add_argument('--quiet', action='store_true',
                        help='turn of debugging')

cli = CLI(version='0.0', context_factory=context_factory)
cli.add_generic_options(generic_options)

@cli.command(__name__ + ':foo_main')
def foo(parser):
    """
    a short description ending in a period.

    a longer description
    """
    parser.add_argument('--bar', action='store_true',
                        help='turn on bar')

def foo_main(app, args):
    app.info('Hello World!')

result = cli.run()
sys.exit(result)

Lazy Decorators

Commands can be defined lazily and picked up later. This removes ordering restrictions between the commands and the cli object.

A module containing commands can be defined irrespective of the actual CLI instance:

# myapp/info.py

from subparse import command

@command('myapp.info:foo_main')
def foo(parser):
    """perform foo"""

Later, when an instance of a CLI is created, the commands can be loaded and registered:

cli = CLI()
cli.load_commands('myapp.info')

Entry Points

Commands may also be defined in external modules and loaded via entry points.

from subparse import cli

cli = CLI()
cli.load_commands_from_entry_point('myapp.commands')

An extension application would then define the external module that should be searched for commands. Again this allows the commands themselves to be defined independently of the main functions, improving import speed.

An extension package should define a module containing the supported commands:

# barpkg/commands.py

from subparse import command

@command('barpkg.bar')
def bar(parser):
    """perform bar"""

The package should also define the function to be called for each command. Optionally in a separate module to avoid importing run-time dependencies during parsing:

# barpkg/bar.py

def main(app, args):
    pass

The package can then broadcast the module barpkg.commands containing the supported commands:

[myapp.commands]
barpkg = barpkg.commands

Now when your extension package is installed the commands will automatically become available.

Context Factory

Each subcommand, when executed, is passed a context object which defines a reusable API between subcommands. This is really the secret sauce of subparse that makes it really easy to build your own shared CLI features.

The context_factory argument to the subparse.CLI allows for defining an object that is passed to all commands. This factory can also be a generator, allowing it to yield the context object and then cleanup after the command is complete. For example:

import transaction

def context_factory(cli, args):
    tm = transaction.TransactionManager(explicit=True)
    with tm:
        yield tm

In the above example the transaction manager is available to all subcommands and it can commit/abort based on whether the command raises an exception.

Each subcommand can pass custom kwargs to the context factory via the context_kwargs argument. For example, if a single subcommand wishes to opt-out of the transaction manager:

def context_factory(cli, args, without_tm=False):
    if without_tm:
        yield

    tm = transaction.TransactionManager(explicit=True)
    with tm:
        yield tm

@command(..., context_kwargs=dict(without_tm=True))
def foo(parser):
    """" Run a command without the tm enabled."""

0.6 (2022-05-15)

  • Drop Python 2.7, 3.4, 3.5, 3.6, 3.7.

  • Add Python 3.8, 3.9, 3.10.

  • Drop dependency on pkg_resources and use importlib.metadata.

  • 100% test coverage.

0.5.3 (2019-03-09)

  • Output help to sys.stderr when parsing fails.

  • Support passing context_kwargs to the command decorator. These arguments will be passed to the context_factory when the command is executed.

0.5.2 (2019-03-09)

  • Sort subcommands in help output.

0.5.1 (2019-03-08)

  • Use the argparse.RawTextHelpFormatter formatter class.

0.5 (2019-03-08)

  • Add Python 3.7 support.

  • Fix a deprecation warning coming from setuptools.

  • Conform more closely to PEP-257 for docstring parsing.

  • Modify how the help text is displayed using the argparse.RawDescriptionHelpFormatter formatter class.

0.4 (2018-05-03)

  • Drop Python 2.6, 3.2 and 3.3 support.

  • Add Python 3.4, 3.5, 3.6 support.

  • Allow the context_factory to be a generator which yields the context. This allows the context to wrap the full lifecycle of the CLI.

0.3.3 (2013-08-12)

No functional changes from 0.3.2.

  • Improve documentation.

0.3.2 (2013-08-06)

  • Add CLI.run API for simply executing the command line.

0.3.1 (2013-08-06)

  • Improve the help output.

0.3 (2013-08-06)

  • Rename subcommands to commands in the API.

0.2 (2013-08-06)

  • Underscores in function names are converted to dashes in their respective subcommand names.

  • Add CLI.add_generic_options API.

  • Add a new help subcommand, allowing for myapp help foo.

  • Allow relative imports in the subcommand specification.

0.1 (2013-08-05)

  • Initial Commits

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

subparse-0.6.tar.gz (14.6 kB view details)

Uploaded Source

Built Distribution

subparse-0.6-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file subparse-0.6.tar.gz.

File metadata

  • Download URL: subparse-0.6.tar.gz
  • Upload date:
  • Size: 14.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.12

File hashes

Hashes for subparse-0.6.tar.gz
Algorithm Hash digest
SHA256 619c2fd1ca9a3731182c60720b9cc2d601af7b0710834a950b78312616d940e1
MD5 0aa6c90c21e7a76b2c525f09f8c8720b
BLAKE2b-256 6ec815bbaeaf939a2925ff48a474b9790209b1829ec1edc1302137de64bd6984

See more details on using hashes here.

File details

Details for the file subparse-0.6-py3-none-any.whl.

File metadata

  • Download URL: subparse-0.6-py3-none-any.whl
  • Upload date:
  • Size: 8.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.12

File hashes

Hashes for subparse-0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 f5bfe8ed9328b170d294f19bbac70356806802455fd671c75d0182f517fe461b
MD5 1ef9970a82e918e48f596f45b6e3e693
BLAKE2b-256 aa0c28a123892df8b62663c5ffb0a4b616b233f53dd98a29f7cf9a6c59dcef42

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page