Welcome to PyApp’s documentation!

Contents:

PyApp Reference

Contents:

Application

Application with bindings for commands

Quick demo:

>>> import sample
>>> from pyapp.app import CliApplication, add_argument
>>> app = CliApplication(sample)
>>> @add_argument('--verbose', target='verbose', action='store_true')
>>> @app.register_handler()
>>> def hello(opts):
...     if opts.verbose:
...         print("Being verbose!")
...     print("Hello")
>>> if __name__ == '__main__':
...     app.dispatch()

This example provides an application with a command hello that takes an optional verbose flag. The framework also provides help, configures and loads settings (using pyapp.conf), an interface to the checks framework and configures the Python logging framework.

There are however a few more things that are required to get this going. The CliApplication class expects a certain structure of your application to allow for it’s (customisable) defaults to be applied.

Your application should have the following structure:

my_app/__init__.py          # Include a __version__ variable
       __main__.py          # This is where the quick demo is located
       default_settings.py  # The default settings file

CliApplication

class pyapp.app.CliApplication(root_module, name=None, description=None, version=None, application_settings=None, application_checks=None, env_settings_key=None, env_loglevel_key=None, default_handler=None)[source]
Parameters:
  • root_module – The root module for this application (used for discovery of other modules)
  • name – Name of your application; defaults to sys.argv[0]
  • description – A description of your application for –help.
  • version – Specify a specific version; defaults to getattr(root_module, ‘__version__’)
  • application_settings – The default settings for this application; defaults to root_module.default_settings
  • application_checks – Location of application checks file; defaults to root_module.checks if it exists.
dispatch(args=None)[source]

Dispatch command to registered handler.

register_handler(handler=None, cli_name=None)

Decorator for registering handlers.

The description for help is taken from the handlers doc string.

Parameters:
  • handler – Handler function
  • cli_name – Optional name to use for CLI; defaults to the function name.
Return type:

HandlerProxy

Checks

Provides an interface and reports of simple pre-flight sanity checks for your application.

Configuration

Provides a simple woy to add settings to your application.

Management of loading of settings from different file types and merging into a simple easy to use settings object.

Usage:

>>> from pyapp.conf import settings
>>> # Configure default settings
>>> settings.configure('my_app.default_settings')

>>> settings.MY_CONFIG_VALUE
'foo'

The settings object also has helper methods to simplify your testing:

>>> from pyapp.conf import settings
>>> with settings.modify() as patch:
...     patch.MY_CONFIG_VALUE = 'bar'
...     settings.MY_CONFIG_VALUE
'bar'
>>> settings.MY_CONFIG_VALUE
'foo'

In addition to changing values new values can be added or existing values removed using the del keyword. Once the context has been exited all changes are reverted.

Note

All settings must be UPPER_CASE. If a setting is not upper case it will not be imported into the settings object.

Settings

class pyapp.conf.Settings(base_settings=<module 'pyapp.conf.default_settings' from '/home/docs/checkouts/readthedocs.org/user_builds/pyapp/checkouts/support-3.4/pyapp/conf/default_settings.py'>)[source]

Settings container

configure(application_settings, runtime_settings=None, additional_loaders=None, env_settings_key='PYAPP_SETTINGS')[source]

Configure the settings object

Parameters:
  • application_settings (str | unicode) – Your applications default settings file.
  • runtime_settings (str | unicode) – Settings defined for the current runtime (eg from the command line)
  • additional_loaders (list()) – Additional loaders to execute
  • env_settings_key (str | unicode) – Environment variable key used to override the runtime_settings.
is_configured

Settings have been configured.

load(loader, apply_method=<slot wrapper '__setitem__' of 'dict' objects>)[source]

Load settings from a loader instance. A loader is an iterator that yields key/value pairs.

See pyapp.conf.loaders.ModuleLoader as an example.

modify()[source]

Apply changes to settings file using a context manager that will roll back the changes on exit of a with block. Designed to simplify test cases.

This should be used with a context manager:

>>> settings = Settings()
>>> with settings.modify() as patch:
>>>     # Change a setting
>>>     patch.FOO = 'foo'
>>>     # Remove a setting
>>>     del patch.BAR
Return type:ModifySettingsContext

Loaders

Loaders are used to load settings from an external source, eg a Python module (using ModuleLoader).

A loader provides key/value pairs to the settings container to merge into the application settings.

ModuleLoader
class pyapp.conf.loaders.ModuleLoader(module)[source]

Load configuration from an importable module.

Loader will load all upper case attributes from the imported module.

Usage:

>>> loader = ModuleLoader("name.of.module")
>>> settings = dict(loader)
FileLoader
class pyapp.conf.loaders.file_loader.FileLoader(path, encoding='UTF8')[source]

Load settings from a file.

Currently only JSON is supported for settings.

Usage:

>>> loader = FileLoader('/path/to/settings.json')
>>> settings = dict(loader)

Default Settings

pyapp.conf.default_settings.CHECK_LOCATIONS = []

Locations to import to ensure checks are registered.

pyapp.conf.default_settings.DEBUG = False

Enable debug mode

pyapp.conf.default_settings.EXT = []

List of extensions currently in use. Will cause pyapp to import any checks, load default_configuration etc that are supplied by any extension.

Should be a list of modules to import eg:

EXT = (
    'pyapp_sqlalchemy',
    'my_custom_extension',
)
pyapp.conf.default_settings.LOGGING = {}

Logging configuration.

The following configuration is applied by default:

LOGGING = {
    'formatters': {
        'default': {
            'format': '%(asctime)s | %(levelname)s | %(name)s | %(message)s',
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'default',
            'stream': 'ext://sys.stderr',
        },
    },
    'root': {
        # 'level' : 'INFO',  # Set from command line arg parser.
        'handlers': ['console'],
    }
}

Configuration Helpers

The configuration helpers are a collection of tools that simplify building configuration structures. They also provide a set of factory objects for the generation of named instances from configuration.

The root helper is the NamedConfiguration, this object provides a simple interface over configuration eg:

>>> my_values = NamedConfiguration('MY_VALUES')
>>> my_values.get('foo')
'123'

# With the following in your settings file
MY_VALUES = {
    'foo': '123',
    'bar': '456',
}

Simple factories

These factory objects come in three flavours:

  • Basic - returns an instance for each request for a named object
  • Singleton - returns the same instance (lazily created) for each named object
  • ThreadLocalSingleton - returns an instance of each named object per thread

These classes are all ABS classes that the developer must inherit from and provide an implementation of the create_instance method.

class pyapp.conf.helpers.NamedFactory(setting, defaults=None, required_keys=None, optional_keys=None, default_name='default')[source]

Factory for creating instances from a named configuration.

class pyapp.conf.helpers.NamedSingletonFactory(*args, **kwargs)[source]

NamedFactory that provides a single instance of an object.

This instance factory type is useful for instance types that only require a single instance eg database connections, web service agents.

If your instance types are not thread safe it is recommended that the ThreadLocalNamedSingletonFactory is used.

class pyapp.conf.helpers.ThreadLocalNamedSingletonFactory(*args, **kwargs)[source]

NamedFactory that provides a single instance of an object per thread.

This instance factory type is useful for instance types that only require a single instance eg database connections, web service agents and that are not thread safe.

Plugin factories

Similar to simple factories, plugin factories also come in the same three flavours, however they include the additional functionality of supporting the creation of object instances based off configuration. The definition is slightly more complex in your settings file.

class pyapp.conf.helpers.NamedPluginFactory(setting, abc=None, default_name='default')[source]

Factory object that generates a named instance from a definition in settings. Can optionally verify an instance type against a specified ABC (Abstract Base Class). The factory will cache imported types.

Named instances are defined in settings using the following definition:

MY_TYPE = {
    'default': (
        'my.module.MyClass', {
            'param1': 123,
            'param2': 'foo',
        }
    )
}

The NamedPluginFactory is thread safe.

class pyapp.conf.helpers.NamedSingletonPluginFactory(*args, **kwargs)[source]

NamedPluginFactory that provides a single instance of an object.

This instance factory type is useful for instance types that only require a single instance eg database connections, web service agents.

If your instance types are not thread safe it is recommended that the ThreadLocalNamedSingletonPluginFactory is used.

class pyapp.conf.helpers.ThreadLocalNamedSingletonPluginFactory(*args, **kwargs)[source]

NamedPluginFactory that provides a single instance of a plugin per thread.

This instance factory type is useful for instance types that only require a single instance eg database connections, web service agents and that are not thread safe.

Provider factories

Extending from plugin factories providers provide an additional level of dynamic configuration where configuration is obtained from data storage eg a database.

class pyapp.conf.helpers.ProviderFactoryBase[source]

Factory to instantiate and configure a provider.

class pyapp.conf.helpers.ProviderBase[source]

A specific provider type these are created by the provider factory, using stored configuration.

IoC (Inversion of Control) Dependency Injection

Support for automatic resolution of dependencies from factories.

These methods are built around data annotations and the abc module.

Usage:

>>> from pyapp.injection import register_factory, inject, Arg
>>> register_factory(FooObject, foo_factory)
# Markup methods for injection
>>> @inject
>>> def my_function(foo=Arg(FooObject)):
...     ...

When my_function is called foo_factory is used to instantiate a concrete instance of a FooObject.

Extensions

Provides extensions to PyApp that allows other modules to register checks and default settings.

Extensions are registered with PyApp via the settings file pyapp.conf.default_settings.EXT setting. Usually extensions will be a python package that contains at least default_settings.py and checks.py files.

Details of the package can be declared in the __init__.py file using the following attributes:

__name__ = 'Name of the Extension`
__version__ = '0.1.0'
__checks__ = '.checks'  # This can be a relative path or fully qualified
__default_settings__ = '.default_settings'  # This can be a relative path or fully qualified
The __checks__ and __default_settings__ attributes tell PyApp to include these when loading
settings or determining what checks are available.

Use the extensions command provided by the PyApp CLI to list the extensions (and version) installed in your application.

Ready State

Once settings have been loaded, logging configured etc a ready callback is triggered to let the extension perform any initialisation that is required:

def ready(**_):
    # Do any initialise
    pass

Indices and tables