Quick Start#

So you need to create a command-line interface? decree-tree can help with that!

Installation#

Install decree-tree from PyPI via pip:

pip install decree-tree

If you are using a different package manager, such as Poetry, use its appropriate installation command for the decree-tree package on PyPI.

Basic Usage#

To create a basic command, subclass decree_tree.DecreeTree to define command-line arguments and its behavior.

basic.py#
from decree_tree import DecreeTree

class BasicCommand(DecreeTree):
    """Echo and optionally up-case input."""

    def add_arguments(self, parser):
        super().add_arguments(parser)
        parser.add_argument('--upper', action='store_true')
        parser.add_argument('value', help='the value to echo')

    def execute(self):
        super().execute()
        output = self.options.value
        if self.options.upper:
            output = output.upper()
        print(output)

if __name__ == '__main__':
    BasicCommand().run()

Invoking the script in the expected way yields output like the following:

$ python basic.py "foo bar"
foo bar

Options can be specified:

$ python basic.py --upper "foo bar"
FOO BAR

If there is missing input, the command fails:

$ python basic.py
usage: basic.py [-h] [--upper] value
basic.py: error: the following arguments are required: value

There is also a built-in help option:

$ python basic.py --help
usage: basic.py [-h] [--upper] value

Echo and optionally up-case input.

positional arguments:
  value       the value to echo

options:
  -h, --help  show this help message and exit
  --upper

Many aspects of the command can be configured. See Configuration and Nesting Commands.

Nested Commands#

To create a tree of subcommands, create additional classes. Instantiate the root and add each to their parent.

basic_tree.py#
from basic import BasicCommand
from decree_tree import DecreeTree

class Root(DecreeTree):
    """An example command tree."""

    def add_arguments(self, parser):
        super().add_arguments(parser)
        parser.add_argument('-e', '--extra', action='store_true')

    def execute(self):
        super().execute()
        if self.options.extra:
            print("Extra output")

class Double(DecreeTree):
    """Doubly-echo the input."""

    def add_arguments(self, parser):
        super().add_arguments(parser)
        parser.add_argument('second', help='the input to double')

    def execute(self):
        super().execute()
        print(1, self.options.second)
        print(2, self.options.second)

root = Root()
root.add(BasicCommand)
double = root.add(Double)
# `double.add(...)` could be used for sub-sub-commands

if __name__ == '__main__':
    root.run()

Either subcommand can be invoked, and processing of the parent command is inherited by default. For example:

$ python basic_tree.py basic_command -e --upper "foo bar"
Extra output
FOO BAR

The built-in help can be displayed at the root level…

$ python basic_tree.py -h
usage: basic_tree.py [-h] [-e] {basic_command,double} ...

An example command tree.

options:
  -h, --help            show this help message and exit
  -e, --extra

subcommands:
  {basic_command,double}
    basic_command       Echo and optionally up-case input.
    double              Doubly-echo the input.

… or at any subcommand level.

$ python basic_tree.py basic_command --help
usage: basic_tree.py basic_command [-h] [-e] [--upper] value

Echo and optionally up-case input.

positional arguments:
  value       the value to echo

options:
  -h, --help   show this help message and exit
  -e, --extra
  --upper

Commands can be nested to an arbitrary depth, and the nesting can be configured in a variety of ways. See Nesting Commands for details.