cliapp — Framework for command-line applications

class cliapp.CliApp

CliApp is an abstract class that must be subclassed in order to create a command line application. It contains some functionality common in pthelma’s command line applications. At a minimum, a subclass must define the name and description properties and the execute() method; usually it will also define the config_file_options and cmdline_arguments properties, and it may extend the read_configuration() method.

A minimal example of a command line application is thus this:

from pthelma.cliapp import CliApp


class MyApp(CliApp):
    name = 'myapp'
    description = 'Do something extremely important'

    def execute(self):
        do_something()


if __name__ == '__main__':
    myapp = MyApp()
    myapp.run()

whereas a more complicated example would be roughly like this:

from pthelma.cliapp import CliApp


class MyApp(CliApp):
    name = 'myapp'
    description = 'Do something extremely important'
                           # Section    Option    Default
    config_file_options = {'General': {'option1': None,
                                       'option2': 18,
                                       },
                           'other':   {'option1': 'hello, world!',
                                       'option2': None,
                                       },
                           }
    cmdline_arguments = {
        '--explode': {'action': 'store_true',
                      'help': 'Explode the system'},
        '--explode-delay': {'action': 'store',
                            'help': 'Delay in seconds before exploding',
                           },
    }

    def read_configuration(self):
        super(MyApp, self).read_configuration()
        self.do_some_more_things_with_the_configuration()

    def execute(self):
        do_something()


if __name__ == '__main__':
    myapp = MyApp()
    myapp.run()
name
description

These two class attributes are informational and will be used in error, log and help messages.

config_file_options

A dictionary of configuration file options. Each key is a section, and each value is a dictionary of options and their defaults; None as a default means that the option is compulsory. config_file_options['other'] does not refer to a configuration file section “other”, but to any configuration file section appart from those listed in config_file_options.

CliApp already contains some base configuration file options in section General: logfile (default empty string, meaning log to standard output), and loglevel (default warning). In order to log messages to the logging system, use self.logger, which is a logging.Logger object.

If an application defines only the General section, then in configuration files the [General] line may be omitted.

In the config_file_options dictionary, a key’s value can be the string 'nocheck' instead of a dictionary; this signals to not check the contents of that section for validity.

cmdline_arguments

A dictionary the keys of which are command line arguments and the values are a dictionary of arguments to provide to argparse.ArgumentParser.add_argument().

config

At the start of execution, we read the configuration file (which is in INI format), and we store the results in config, which is a dictionary similar to Python 3’s configparser.ConfigParser. This attribute is meant to be read-only.

read_configuration()

You should override this method either in order to make additional sanity checks of the configuration or in order to transfer data from config to data structures that are more convenient. First call the inherited method; this will read the configuration into config and check for the existence of compulsory options and everything else it can check. Then do anything else you want to do with the configuration. Any exception you raise will be caught, logged, and shown to the user.

execute()

You must specify this method. This does all the work. It is called after the command line and configuration file are read and checked and after the logging system is setup and an informational message for program start is logged.

run(dry=False)

You should not redefine this method, but call it in your main program.

If the optional dry argument is True, then run() does not run execute(); it only does everything else. (This is mainly useful in unit tests, to see if configuration reading and checking works properly).

exception cliapp.InvalidOptionError
exception cliapp.WrongValueError

These two exceptions derive from configparser.Error. InvalidOptionError is raised whenever the configuration file contains an invalid option, and WrongValueError whenever an option contains an invalid value.