Skip to content
This repository was archived by the owner on May 3, 2020. It is now read-only.

Commit 5d146f5

Browse files
committed
flask_registry: refactoring
Signed-off-by: Yoan Blanc <[email protected]>
1 parent 7e2eea5 commit 5d146f5

File tree

9 files changed

+339
-342
lines changed

9 files changed

+339
-342
lines changed

flask_registry/__init__.py

Lines changed: 32 additions & 241 deletions
Original file line numberDiff line numberDiff line change
@@ -21,263 +21,54 @@
2121
## granted to it by virtue of its status as an Intergovernmental Organization
2222
## or submit itself to any jurisdiction.
2323

24-
"""
25-
Flask extension
26-
===============
24+
"""Flask extension.
2725
2826
Flask-Registry is initialized like this:
2927
30-
>>> from flask import Flask
31-
>>> from flask_registry import Registry, ListRegistry
32-
>>> app = Flask('myapp')
33-
>>> r = Registry(app=app)
34-
35-
A simple usage example of ``ListRegistry`` looks like this:
36-
37-
>>> app.extensions['registry']['my.namespace'] = ListRegistry()
38-
>>> len(app.extensions['registry'])
39-
1
40-
>>> app.extensions['registry']['my.namespace'].register("something")
41-
>>> app.extensions['registry']['my.namespace'].register("something else")
42-
>>> len(app.extensions['registry']['my.namespace'])
43-
2
44-
>>> for obj in app.extensions['registry']['my.namespace']:
45-
... print(obj)
46-
something
47-
something else
48-
"""
49-
50-
from __future__ import absolute_import
51-
52-
from werkzeug.local import LocalProxy
53-
from flask import current_app
54-
55-
try:
56-
from collections import MutableMapping
57-
except ImportError:
58-
from collection.abc import MutableMapping
59-
60-
61-
class RegistryError(Exception):
62-
"""
63-
Exception class raised for user errors (e.g. creating two registries in
64-
the same namespace)
65-
"""
66-
pass
67-
68-
69-
class Registry(MutableMapping):
70-
"""
71-
Flask extension
72-
73-
Initialization of the extension:
28+
.. code-block:: pycon
7429
7530
>>> from flask import Flask
76-
>>> from flask_registry import Registry
31+
>>> from flask_registry import Registry, ListRegistry
7732
>>> app = Flask('myapp')
78-
>>> r = Registry(app)
79-
>>> app.extensions['registry']
80-
<Registry ()>
81-
82-
or alternatively using the factory pattern:
83-
84-
>>> app = Flask('myapp')
85-
>>> r = Registry()
86-
>>> r.init_app(app)
87-
>>> r
88-
<Registry ()>
89-
90-
"""
91-
92-
def __init__(self, app=None):
93-
"""
94-
Initialize the Registry.
95-
96-
:param app: Flask application
97-
:type app: flask.Flask
98-
"""
99-
super(MutableMapping, self).__init__()
100-
self._registry = {}
101-
self.app = app
102-
if app is not None:
103-
self.init_app(app)
104-
105-
def init_app(self, app):
106-
"""
107-
Initialize a Flask application.
108-
109-
Only one Registry per application is allowed.
110-
111-
:param app: Flask application
112-
:type app: flask.Flask
113-
:raise RegistryError: if the registry is already initialized
114-
"""
115-
# Follow the Flask guidelines on usage of app.extensions
116-
if not hasattr(app, 'extensions'):
117-
app.extensions = {}
118-
if 'registry' in app.extensions:
119-
raise RegistryError("Flask application already initialized")
120-
app.extensions['registry'] = self
121-
122-
def __iter__(self):
123-
"""Get iterator over registries."""
124-
return iter(self._registry)
125-
126-
def __len__(self):
127-
"""Get length of registries."""
128-
return len(self._registry)
129-
130-
def __getitem__(self, key):
131-
"""
132-
Get a registry with a given namespace.
133-
134-
:param key: Namespace
135-
"""
136-
return self._registry[key]
137-
138-
def __delitem__(self, key):
139-
"""
140-
Remove a registry
141-
142-
:param key: Namespace
143-
"""
144-
self._registry[key].namespace = None
145-
del self._registry[key]
146-
147-
def __setitem__(self, key, value):
148-
"""
149-
Register a registry in the Flask application registry.
150-
151-
:param key: Namespace
152-
:param value: Instance of RegistryBase or subclass
153-
:raise RegistryError: if the key is already present
154-
"""
155-
if key in self._registry:
156-
raise RegistryError("Namespace %s already taken." % key)
157-
value.namespace = key
158-
self._registry[key] = value
159-
160-
def __repr__(self):
161-
"""Get the string representation."""
162-
return "<{0} ({1})>".format(self.__class__.__name__,
163-
", ".join(self._registry.keys()))
164-
165-
166-
# pylint: disable=R0921
167-
class RegistryBase(object):
168-
"""
169-
Abstract base class for all registries.
170-
171-
Each subclass must implement the ``register()`` method.
172-
Each subclass may implement the ``unregister()`` method.
173-
174-
Once a registry is registered in the Flask application, the namespace
175-
under which it is available is injected into it self.
176-
177-
Please see ``flask_registry.registries.core`` for simple examples of
178-
subclasses.
179-
"""
180-
_namespace = None
181-
182-
@property
183-
def namespace(self):
184-
"""
185-
Namespace. Used only by the Flask extension to inject the namespace
186-
under which this instance is registered in the Flask application.
187-
Defaults to ``None`` if not registered in a Flask application.
188-
"""
189-
return self._namespace
190-
191-
@namespace.setter
192-
def namespace(self, value):
193-
""" Setter for namespace property. """
194-
if self._namespace and value is not None:
195-
raise RegistryError("Namespace cannot be changed.")
196-
self._namespace = value
197-
198-
def register(self, *args, **kwargs):
199-
"""
200-
Abstract method which MUST be overwritten by subclasses. A subclass
201-
does not need to take the same number of arguments as the abstract
202-
base class.
203-
"""
204-
raise NotImplementedError()
205-
206-
def unregister(self, *args, **kwargs):
207-
"""
208-
Abstract method which MAY be overwritten by subclasses. A subclass
209-
does not need to take the same number of arguments as the abstract
210-
base class.
211-
"""
212-
raise NotImplementedError()
213-
214-
215-
class RegistryProxy(LocalProxy):
216-
"""
217-
Lazy proxy object to a registry in the ``current_app``
218-
219-
Allows you to define a registry in your local module without needing to
220-
initialize it first. Once accessed the first time, the registry will be
221-
initialized in the current_app, thus you must be working in either
222-
the Flask application context or request context.
223-
224-
>>> from flask import Flask
225-
>>> app = Flask('myapp')
226-
>>> from flask_registry import Registry, RegistryProxy, RegistryBase
22733
>>> r = Registry(app=app)
228-
>>> proxy = RegistryProxy('myns', RegistryBase)
229-
>>> 'myns' in app.extensions['registry']
230-
False
231-
>>> with app.app_context():
232-
... print(proxy.namespace)
233-
...
234-
myns
235-
>>> 'myns' in app.extensions['registry']
236-
True
23734
238-
:param namespace: Namespace for registry
239-
:param registry_class: The registry class - i.e. a sublcass of
240-
``RegistryBase``.
241-
:param args: Arguments passed to ``registry_class`` on initialization.
242-
:param kwargs: Keyword arguments passed to ``registry_class`` on
243-
initialization.
244-
"""
35+
A simple usage example of ``ListRegistry`` looks like this:
24536
246-
# pylint: disable=W0142, C0111, E1002
247-
def __init__(self, namespace, registry_class, *args, **kwargs):
248-
def _lookup():
249-
if not 'registry' in getattr(current_app, 'extensions', {}):
250-
raise RegistryError('Registry is not initialized.')
251-
if namespace not in current_app.extensions['registry']:
252-
# pylint: disable=W0142
253-
current_app.extensions['registry'][namespace] = \
254-
registry_class(
255-
*args, **kwargs
256-
)
257-
return current_app.extensions['registry'][namespace]
258-
super(RegistryProxy, self).__init__(_lookup)
37+
.. code-block:: pycon
38+
39+
>>> app.extensions['registry']['my.namespace'] = ListRegistry()
40+
>>> len(app.extensions['registry'])
41+
1
42+
>>> app.extensions['registry']['my.namespace'].register("something")
43+
>>> app.extensions['registry']['my.namespace'].register("something else")
44+
>>> len(app.extensions['registry']['my.namespace'])
45+
2
46+
>>> for obj in app.extensions['registry']['my.namespace']:
47+
... print(obj)
48+
something
49+
something else
50+
"""
25951

52+
from .base import Registry, RegistryError, RegistryProxy, RegistryBase
53+
from .registries.core import (ListRegistry, DictRegistry,
54+
ImportPathRegistry, ModuleRegistry,
55+
SingletonRegistry)
56+
from .registries.modulediscovery import (ModuleDiscoveryRegistry,
57+
ModuleAutoDiscoveryRegistry)
58+
from .registries.pkgresources import (EntryPointRegistry,
59+
PkgResourcesDirDiscoveryRegistry)
60+
from .registries.appdiscovery import (PackageRegistry,
61+
ExtensionRegistry,
62+
ConfigurationRegistry,
63+
BlueprintAutoDiscoveryRegistry)
26064

261-
# Version information
26265
from .version import __version__
26366

264-
#
265-
# API of registries
266-
#
267-
from .registries.core import ListRegistry, DictRegistry, \
268-
ImportPathRegistry, ModuleRegistry, SingletonRegistry
269-
from .registries.modulediscovery import \
270-
ModuleDiscoveryRegistry, ModuleAutoDiscoveryRegistry
271-
from .registries.pkgresources import EntryPointRegistry, \
272-
PkgResourcesDirDiscoveryRegistry
273-
from .registries.appdiscovery import PackageRegistry, \
274-
ExtensionRegistry, ConfigurationRegistry, BlueprintAutoDiscoveryRegistry
275-
276-
__all__ = [
67+
__all__ = (
27768
'Registry', 'RegistryError', 'RegistryProxy', 'RegistryBase',
27869
'ListRegistry', 'DictRegistry', 'ImportPathRegistry', 'ModuleRegistry',
27970
'ModuleDiscoveryRegistry', 'ModuleAutoDiscoveryRegistry',
28071
'EntryPointRegistry', 'PkgResourcesDirDiscoveryRegistry',
28172
'PackageRegistry', 'ExtensionRegistry', 'ConfigurationRegistry',
28273
'BlueprintAutoDiscoveryRegistry', 'SingletonRegistry', '__version__'
283-
]
74+
)

0 commit comments

Comments
 (0)