Extensions

Extensions provide additional functionality to applications. Configuration management is shared between applications and extensions in a central location.

Using Extensions

from henson import Application
from henson_sqlite import SQLite

app = Application(__name__)
db = SQLite(app)

db.connection.execute('SELECT 1;')

Developing Extensions

Henson provides an Extension base class to make extension development easier.

from henson import Extension

class SQLite(Extension):
    DEFAULT_SETTINGS = {'SQLITE_CONNECTION_STRING': ':memory:'}

    def __init__(self, app=None):
        self._connection = None
        super().__init__(app)

    @property
    def connection(self):
        if not self._connection:
            conn_string = self.app.settings['SQLITE_CONNECTION_STRING']
            self._connection = sqlite3.connect(conn_string)
        return self._connection

The Extension class provides two special attributes that are meant to be overridden:

  • DEFAULT_SETTINGS provides default values for an extension’s settings during the init_app() step. When a value is used by an extension and has a sensible default, it should be stored here (e.g., a database hostname).
  • REQUIRED_SETTINGS provides a list of keys that are checked for existence during the init_app() step. If one or more required settings are not set on the application instance assigned to the extension, a KeyError is raised. Extensions should set this when a value is required but has no default (e.g., a database password).

Extending the Command Line

Henson offers an extensible command line interface. To register your own commands, use register_commands(). Any function passed to it will have its usage created directly from its signature. During the course of initializing the application for use with the extension (i.e., init_app()), Henson will check for a method on the extension’s instance named register_cli and call it. If you place any calls to register_commands() inside it, the command line interface will be extended automatically.

In order to access the new commands, the henson command line utility must be given a reference to an Application. This is done through the --app argument:

$ henson --app APP_PATH

Note

For details about the syntax to use when passing a reference to an Application, see Running Applications.

A positional argument in the Python function will result in a required positional argument in the command:

def trash(grouch):
    pass
$ henson --app APP_PATH NAMESPACE trash GROUCH

A keyword argument in the Python function will result in a positional argument in the command with a default value to be used when the argument is omitted:

def trash(grouch='oscar'):
    pass
$ henson --app APP_PATH NAMESPACE trash [GROUCH]

A keyword-only argument in the Python function will result in an optional argument in the command:

def trash(*, grouch='oscar'):
    pass
$ henson --app APP_PATH NAMESPACE trash [--grouch GROUCH]

By default, all optional arguments will have a flag that matches the function argument’s name. When no other optional arguments start with the same character, a single-character abbreviated flag can also be used.

$ henson --app APP_PATH NAMESPACE trash [-g GROUCH]

The trash function can then be registered with the CLI:

register_commands('sesame', [trash])
$ henson --app APP_PATH sesame trash --help

Additionally, if a command includes a quiet or verbose argument, it will automatically receive the count of the number of times it was specified (e.g., -v will have the value 1, -vv will have the value 2). When both arguments are included, they will be added as a mutually exclusive group.

Note

Due to how argparse handles argument counts, quiet and verbose will be set to None rather than 0 when the flag isn’t specified when the command is invoked.

$ henson --app APP_PATH sesame trash -vvvv
$ henson --app APP_PATH sesame trash --quiet

Available Extensions

Several extensions are available for use: