argparsetree 0.0.6
Package for creating complex command line argument trees using argparse
License: MIT
Keywords: class based argparse

argparsetree
============

Package for creating complex command line argument trees using argparse.

Basic Usage
-----------

You can create a single command by creating a class extending ``argparsetree.BaseCommand``
and overriding the ``add_arguments`` and ``action_methods``. For example::

    from argparsetree import BaseCommand


    class MyCommand(BaseCommand):
        def add_arguments(parser):
            parser.add_arguments('foo', help='Some description of "foo"')

        def action(args):
            print(args.foo)

The ``parser`` argument passed to ``add_arguments`` is an ``argparse.ArgumentParser`` object. Similarly
the ``args`` parameter passed to the ``action`` method is a ``argparse.Namespace`` object generated by
calling ``parse_args`` on the generated argument parser.

Additionally the description property can be set on the command class, this will be used when building
the help message.

If a return value other than ``None`` is returned from ``action`` this will be used as the return code from the
``run`` function. If no value is returned (or the value is ``None``) the value is assumed to be 0.

Once you have created your command you can use it by creating a script similar to::

    #!/usr/bin/env python
    import sys

    from mycli import MyCommand


    if __name__ == '__main__':
        sys.exit(MyCommand().run())

Nested Usage
------------

Child commands can also be added to a command by specifying the ``sub_commands`` property. This is a dictionary
that maps command names to command classes. For example::

    #!/usr/bin/env python

    import sys
    from argparsetree import BaseCommand


    class CleanFooCommand(BaseCommand):
        description = 'Cleans up the foo object'

        def add_args(self, parser):
            parser.add_argument('target', help='The foo file to clean up')
            parser.add_argument('-y', '--yes', help='Automatic answer yes to prompts', action='store_true')

        def action(self, args):
            # do cleaning
            return 0


    class CheckFooCommand(BaseCommand):
        description = 'Checks the integrity of a foo object'

        def add_args(self, parser):
            parser.add_argument('target', help='The foo file to clean up')
            parser.add_argument('-y', '--yes', help='Automatic answer yes to prompts', action='store_true')

        def action(self, args):
            # do cleaning
            return 0


    class FooCommand(BaseCommand):
        description = 'Do things with foos'
        sub_commands = {
            'check': CheckFooCommand,
            'clean': CleanFooCommand,
            # more sub commands here
        }


    class RootCommand(BaseCommand):
        description = 'My fancy CLI'
        sub_commands = {
            'foo': FooCommand,
            # more sub commands here
        }


    if __name__ == '__main__':
        sys.exit(RootCommand().run())

Running ``./example.py`` would give the following output::

    usage: My fancy CLI [-h] {foo} ...

    positional arguments:
      {foo}
        foo       Do things with foos

    optional arguments:
      -h, --help  show this help message and exit

And running ``./example.py foo`` gives::

    usage: Do things with foos [-h] {check,clean} ...

    positional arguments:
      {check,clean}
        check        Checks the integrity of a foo object
        clean        Cleans up the foo object

    optional arguments:
      -h, --help     show this help message and exit

An extended help message for each command (and sub-command) can be printed by adding the ``--help`` flag,
So running ``./example.py foo check --help`` gives::

    usage: My fancy CLI foo check [-h] [-y] target

    Checks the integrity of a foo object

    positional arguments:
      target      The foo file to clean up

    optional arguments:
      -h, --help  show this help message and exit
      -y, --yes   Automatic answer yes to prompts