User Guide

Flask extension to dynamically assemble your Flask application from packages.

Flask-Registry is initialized like this:

>>> from flask import Flask
>>> from flask_registry import Registry, ListRegistry
>>> app = Flask('myapp')
>>> r = Registry(app=app)

A simple usage example of ListRegistry looks like this:

>>> app.extensions['registry']['my.namespace'] = ListRegistry()
>>> len(app.extensions['registry'])
1
>>> app.extensions['registry']['my.namespace'].register("something")
>>> app.extensions['registry']['my.namespace'].register("something else")
>>> len(app.extensions['registry']['my.namespace'])
2
>>> for obj in app.extensions['registry']['my.namespace']:
...     print(obj)
something
something else

Module Discovery

The module discovery registries.

They provide discovery functionality useful for searching a list of Python packages for a specific module name, and afterwards registering the module. This is used to e.g. load and register Flask blueprints by BlueprintAutoDiscoveryRegistry.

Assume e.g. we want to discover the helpers module from the tests package. First we initialize the registry:

>>> from flask import Flask
>>> from flask_registry import Registry, ModuleDiscoveryRegistry
>>> from flask_registry import ImportPathRegistry
>>> app = Flask('myapp')
>>> r = Registry(app=app)

We then create the list of packages to search through using an ImportPathRegistry:

>>> r['mypackages'] = ImportPathRegistry(initial=['registry_module'])

Then, initialize the ModuleDiscoveryRegistry and run the discovery:

>>> r['mydiscoveredmodules'] = ModuleDiscoveryRegistry(
...     'helpers', registry_namespace='mypackages')
>>> len(r['mydiscoveredmodules'])
0
>>> r['mydiscoveredmodules'].discover(app=app)
>>> len(r['mydiscoveredmodules'])
1

Lazy discovery

Using RegistryProxy you may lazily discover modules. Above example using lazy loading looks like this:

>>> from flask_registry import RegistryProxy
>>> app = Flask('myapp')
>>> r = Registry(app=app)
>>> pkg_proxy = RegistryProxy('mypackages', ImportPathRegistry,
...     initial=['registry_module'])
>>> mod_proxy = RegistryProxy('mydiscoveredmodules',
...     ModuleDiscoveryRegistry,
...     'helpers',
...     registry_namespace=pkg_proxy)
>>> 'mypackages' in r
False
>>> 'mydiscoveredmodules' in r
False
>>> with app.app_context():
...     mod_proxy.discover(app=app)
>>> 'mypackages' in r
True
>>> 'mydiscoveredmodules' in r
True

Application Discovery

Application discovery registries.

They provide discovery functionality useful for dynamically constructing Flask applications based on configuration variables. This allows a developer to package config, blueprints and extensions into isolated and reusable packages which a framework can dynamically install into a Flask application.

Such a package (named registry_module) could look like and it is located in tests directory:

  • registry_module.views – contains blueprints which should be registered on the application object.
  • registry_module.mockext – contains a setup_app() method which be used to install any Flask extensions on the application object.
  • registry_module.config – contains configuration variables specific for this module.

Following is a simplified example of a Flask application factory, that will load config, extensions and blueprints:

>>> from flask import Flask, Blueprint
>>> from flask_registry import Registry, PackageRegistry
>>> from flask_registry import ExtensionRegistry
>>> from flask_registry import ConfigurationRegistry
>>> from flask_registry import BlueprintAutoDiscoveryRegistry
>>> class Config(object):
...     PACKAGES = ['registry_module']
...     EXTENSIONS = ['registry_module.mockext']
...     USER_CFG = True
>>> def create_app(config):
...     app = Flask('myapp')
...     app.config.from_object(config)
...     r = Registry(app=app)
...     r['packages'] = PackageRegistry(app)
...     r['extensions'] = ExtensionRegistry(app)
...     r['config'] = ConfigurationRegistry(app)
...     r['blueprints'] = BlueprintAutoDiscoveryRegistry(app=app)
...     return app
>>> config = Config()
>>> app = create_app(config)

Packages

The config variable PACKAGES specifies the list of Python packages, which ConfigurationRegistry and BlueprintAutoDiscoveryRegistry will search for config.py and views.py modules inside.

>>> for pkg in app.extensions['registry']['packages']:
...     print(pkg)
registry_module

Extensions

The config variable EXTENSIONS specifies the list of Python packages, which the ExtensionRegistry will load and call setup_app(app) on, to dynamically initialize Flask extensions.

>>> for pkg in app.extensions['registry']['extensions']:
...     print(pkg)
registry_module.mockext

Configuration

The ConfigurationRegistry will merge any package defined config, with the application config without overwriting already set variables in the application config:

>>> config.USER_CFG
True
>>> import registry_module.config
>>> registry_module.config.USER_CFG
False
>>> app.config['USER_CFG']
True

Blueprints

The BlueprintAutoDiscoveryRegistry will search for blueprints defined inside a views module in each package defined in PACKAGES. It will also register the discovered blueprints on the Flask application. Each views module should define either a single blueprint in the variable blueprint and/or multiple blueprints in the variable blueprints:

>>> from registry_module import views
>>> isinstance(views.blueprint, Blueprint)
True
>>> len(views.blueprints)
2
>>> for k in sorted(app.blueprints.keys()):
...     print(k)
test
test1
test2

Package Resources

Package Resources

Package resource registries may be used to discover e.g. package resources as well as loading entry points.

Entry points

setuptools entry points are a simple way for packages to “advertise” Python objects, so that frameworks can search for these entry points. setup.py files for instance allows you to specify console_scripts entry points, which will install scripts into system path for you.

The EntryPointRegistry allows you to easily register these entry points into your Flask application:

>>> from flask import Flask
>>> from flask_registry import Registry, EntryPointRegistry
>>> app = Flask('myapp')
>>> r = Registry(app=app)
>>> r['scripts'] = EntryPointRegistry('console_scripts')
>>> 'easy_install' in r['scripts']
True

Entry points are specified in you setup.py, e.g.:

setup(
    # ...
    entry_points={
        'flask_registry.test_entry': [
            'testcase = flask_registry:RegistryBase',
        ]
    },
    # ...
)
>>> r['entrypoints'] = EntryPointRegistry(
...     'flask_registry.test_entry', load=True)
>>> 'testcase' in r['entrypoints']
True
>>> from flask_registry import RegistryBase
>>> r['entrypoints']['testcase'][0] == RegistryBase
True

See http://pythonhosted.org/setuptools/pkg_resources.html#entry-points for more information on entry points.

Resource files

The PkgResourcesDirDiscoveryRegistry will search a list of Python packages for a specific resource directory and register all files found in the directories.

Assume e.g. a package tests have a directory resources with one file in it called testresource.cfg. This file can be discovered in the following manner:

>>> import os
>>> app = Flask('myapp')
>>> r = Registry(app=app)
>>> from flask_registry import ImportPathRegistry
>>> from flask_registry import PkgResourcesDirDiscoveryRegistry
>>> r['packages'] = ImportPathRegistry(initial=['registry_module'])
>>> r['res'] = PkgResourcesDirDiscoveryRegistry('resources', app=app)
>>> os.path.basename(r['res'][0]) == 'testresource.cfg'
True

Extending Flask-Registry

Flask-Registry extensions.

Extending Flask-Registry

You can easily create your own type of registries by subclassing one of the existing registries found in the modules under flask_registry.registries.

If you for instance want to create a list registry that only accepts integers, you could create it like this:

>>> from flask import Flask
>>> from flask_registry import Registry, RegistryError, ListRegistry
>>> class IntListRegistry(ListRegistry):
...     def register(self, item):
...         if not isinstance(item, int):
...             raise ValueError("Object must be of type int")
>>> app = Flask('myapp')
>>> r = Registry(app=app)
>>> r['myns'] = IntListRegistry()
>>> r['myns'].register(1)
>>> r['myns'].register("some string")
Traceback (most recent call last):
  File "/usr/lib/python2.7/doctest.py", line 1289, in __run
    compileflags, 1) in test.globs
  File "<doctest default[7]>", line 1, in <module>
    r['myns'].register("some string")
  File "<doctest default[2]>", line 4, in register
    raise ValueError("Object must be of type int")
ValueError: Object must be of type int