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 asetup_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