Add DynamicCatalog docs

This commit is contained in:
Roman Mogilatov 2015-11-26 13:39:42 +02:00
parent 7c3daf4c64
commit ab3e901d7e
7 changed files with 120 additions and 2 deletions

View File

@ -123,6 +123,13 @@ class CatalogBundle(object):
class DynamicCatalog(object): class DynamicCatalog(object):
"""Dynamic catalog of providers. """Dynamic catalog of providers.
:py:class:`DynamicCatalog` is a catalog of providers that could be created
in application's runtime. It should cover most of the cases when list of
providers that would be included in catalog is non-deterministic in terms
of apllication code (catalog's structure could be determined just after
application will be started and will do some initial work, like parsing
list of catalog's providers from the configuration).
.. code-block:: python .. code-block:: python
services = DynamicCatalog(auth=providers.Factory(AuthService), services = DynamicCatalog(auth=providers.Factory(AuthService),

View File

@ -32,7 +32,8 @@ attribute names in Python.
contains some callable object, that returns particular instance as a contains some callable object, that returns particular instance as a
result of its call. result of its call.
Here is an simple example of declarative catalog with several factories: Here is an simple example of defining declarative catalog with several
factories:
.. image:: /images/catalogs/declarative.png .. image:: /images/catalogs/declarative.png
:width: 85% :width: 85%

View File

@ -2,3 +2,28 @@ Dynamic catalogs
---------------- ----------------
.. module:: dependency_injector.catalogs .. module:: dependency_injector.catalogs
:py:class:`DynamicCatalog` is a catalog of providers that could be created in
application's runtime. It should cover most of the cases when list of
providers that would be included in catalog is non-deterministic in terms of
apllication code (catalog's structure could be determined just after
application will be started and will do some initial work, like parsing list
of catalog's providers from the configuration).
:py:class:`DeclarativeCatalog` and :py:class:`DynamicCatalog` have
100% API parity.
Main difference between :py:class:`DeclarativeCatalog` and
:py:class:`DynamicCatalog` is that :py:class:`DeclarativeCatalog` acts on
class-level, while :py:class:`DynamicCatalog` do the same on
instance-level.
Here is an simple example of defining dynamic catalog with several factories:
.. literalinclude:: ../../examples/catalogs/dynamic.py
:language: python
Next one example demonstrates creation and runtime filling of dynamic catalog:
.. literalinclude:: ../../examples/catalogs/dynamic_runtime_creation.py
:language: python

View File

@ -4,6 +4,7 @@ from dependency_injector import catalogs
from dependency_injector import providers from dependency_injector import providers
# Defining declarative catalog:
class Catalog(catalogs.DeclarativeCatalog): class Catalog(catalogs.DeclarativeCatalog):
"""Providers catalog.""" """Providers catalog."""

View File

@ -39,7 +39,7 @@ class Services(catalogs.DeclarativeCatalog):
""":type: providers.Provider -> AuthService""" """:type: providers.Provider -> AuthService"""
# Retrieving catalog providers: # Retrieving service providers from catalog:
users_service = Services.users() users_service = Services.users()
auth_service = Services.auth() auth_service = Services.auth()

View File

@ -0,0 +1,18 @@
"""Dynamic catalog simple example."""
from dependency_injector import catalogs
from dependency_injector import providers
# Defining dynamic catalog:
catalog = catalogs.DynamicCatalog(factory1=providers.Factory(object),
factory2=providers.Factory(object))
# Creating some objects:
object1 = catalog.factory1()
object2 = catalog.factory2()
# Making some asserts:
assert object1 is not object2
assert isinstance(object1, object)
assert isinstance(object2, object)

View File

@ -0,0 +1,66 @@
"""Dynamic catalog creation and runtime filling of it example."""
from dependency_injector import catalogs
# Defining several example services:
class UsersService(object):
"""Example users service."""
class AuthService(object):
"""Example auth service."""
def import_cls(cls_name):
"""Import class by its fully qualified name.
In terms of current example it is just a small helper function. Please,
don't use it in production approaches.
"""
path_components = cls_name.split('.')
if len(path_components) == 1:
path_components.insert(0, '__main__')
module = __import__('.'.join(path_components[0:-1]),
locals(),
globals(),
fromlist=path_components[-1:])
return getattr(module, path_components[-1])
# "Parsing" some configuration:
config = {
'services': {
'users': {
'class': 'UsersService',
'provider_class': 'dependency_injector.providers.Factory',
},
'auth': {
'class': 'AuthService',
'provider_class': 'dependency_injector.providers.Factory',
}
}
}
# Defining dynamic service providers catalog:
services = catalogs.DynamicCatalog()
# Filling dynamic service providers catalog according to the configuration:
for service_name, service_info in config['services'].iteritems():
# Runtime importing of service and service provider classes:
service_cls = import_cls(service_info['class'])
service_provider_cls = import_cls(service_info['provider_class'])
# Creating service provider:
service_provider = service_provider_cls(service_cls)
# Binding service provider to the dynamic service providers catalog:
services.bind_provider(service_name, service_provider)
# Creating some objects:
users_service = services.users()
auth_service = services.auth()
# Making some asserts:
assert isinstance(users_service, UsersService)
assert isinstance(auth_service, AuthService)