Improve declarative and dynamic container docs
This commit is contained in:
parent
e0fa746d7f
commit
cfdcbaa77a
|
@ -1,23 +1,22 @@
|
|||
Declarative containers
|
||||
----------------------
|
||||
Declarative container
|
||||
---------------------
|
||||
|
||||
.. currentmodule:: dependency_injector.containers
|
||||
|
||||
:py:class:`DeclarativeContainer` is a collection of the providers defined in the declarative
|
||||
manner. It covers the use cases when your application structure does not change in the runtime.
|
||||
:py:class:`DeclarativeContainer` is a class-based style of the providers definition.
|
||||
|
||||
Container has the ``.providers`` attribute. It is a dictionary of the container providers.
|
||||
You create the declarative container subclass, put the providers as attributes and create the
|
||||
container instance.
|
||||
|
||||
.. literalinclude:: ../../examples/containers/declarative.py
|
||||
:language: python
|
||||
:lines: 3-
|
||||
|
||||
Your declarative container has to extend base declarative container class -
|
||||
:py:class:`dependency_injector.containers.DeclarativeContainer`.
|
||||
The declarative container providers should only be used when you have the container instance.
|
||||
Working with the providers of the container on the class level will influence all further
|
||||
instances.
|
||||
|
||||
Declarative container classes can not have any methods or any other attributes then providers.
|
||||
|
||||
The declarative container providers should only be used after the container is initialized.
|
||||
The declarative container can not have any methods or any other attributes then providers.
|
||||
|
||||
The container class provides next attributes:
|
||||
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
Dynamic containers
|
||||
------------------
|
||||
Dynamic container
|
||||
-----------------
|
||||
|
||||
.. currentmodule:: dependency_injector.containers
|
||||
|
||||
:py:class:`DynamicContainer` is an inversion of control container with dynamic
|
||||
structure. It should cover most of the cases when list of providers that
|
||||
would be included in container is non-deterministic and depends on
|
||||
application's flow or its configuration (container's structure could be
|
||||
determined just after application will be started and will do some initial
|
||||
work, like parsing list of container's providers from the configuration).
|
||||
:py:class:`DynamicContainer` is a collection of the providers defined in the runtime.
|
||||
|
||||
While :py:class:`DeclarativeContainer` acts on class-level,
|
||||
:py:class:`DynamicContainer` does the same on instance-level.
|
||||
|
||||
Here is an simple example of defining dynamic container with several factories:
|
||||
You create the dynamic container instance and put the providers as attributes.
|
||||
|
||||
.. literalinclude:: ../../examples/containers/dynamic.py
|
||||
:language: python
|
||||
:lines: 3-
|
||||
|
||||
Next example demonstrates creation of dynamic container based on some
|
||||
configuration:
|
||||
The dynamic container is good for the case when your application structure depends on the
|
||||
configuration file or some other source that you can reach only after application is already
|
||||
running (database, api, etc).
|
||||
|
||||
In this example we use the configuration to fill in the dynamic container with the providers:
|
||||
|
||||
.. literalinclude:: ../../examples/containers/dynamic_runtime_creation.py
|
||||
:language: python
|
||||
|
||||
:lines: 3-
|
||||
|
||||
.. disqus::
|
||||
|
||||
|
|
|
@ -10,13 +10,14 @@ class Container(containers.DeclarativeContainer):
|
|||
factory2 = providers.Factory(object)
|
||||
|
||||
|
||||
container = Container()
|
||||
if __name__ == '__main__':
|
||||
container = Container()
|
||||
|
||||
object1 = container.factory1()
|
||||
object2 = container.factory2()
|
||||
object1 = container.factory1()
|
||||
object2 = container.factory2()
|
||||
|
||||
print(container.providers)
|
||||
# {
|
||||
# 'factory1': <dependency_injector.providers.Factory(...),
|
||||
# 'factory2': <dependency_injector.providers.Factory(...),
|
||||
# }
|
||||
print(container.providers)
|
||||
# {
|
||||
# 'factory1': <dependency_injector.providers.Factory(...),
|
||||
# 'factory2': <dependency_injector.providers.Factory(...),
|
||||
# }
|
||||
|
|
|
@ -32,10 +32,11 @@ class Container(containers.DeclarativeContainer):
|
|||
)
|
||||
|
||||
|
||||
container = Container()
|
||||
if __name__ == '__main__':
|
||||
container = Container()
|
||||
|
||||
user_service = container.user_service()
|
||||
auth_service = container.auth_service()
|
||||
user_service = container.user_service()
|
||||
auth_service = container.auth_service()
|
||||
|
||||
assert user_service.db is auth_service.db is container.database()
|
||||
assert isinstance(auth_service.user_service, UserService)
|
||||
assert user_service.db is auth_service.db is container.database()
|
||||
assert isinstance(auth_service.user_service, UserService)
|
||||
|
|
|
@ -11,7 +11,8 @@ class Container(containers.DeclarativeContainer):
|
|||
database = providers.Singleton(sqlite3.connect, ':memory:')
|
||||
|
||||
|
||||
container = Container(database=mock.Mock(sqlite3.Connection))
|
||||
if __name__ == '__main__':
|
||||
container = Container(database=mock.Mock(sqlite3.Connection))
|
||||
|
||||
database = container.database()
|
||||
assert isinstance(database, mock.Mock)
|
||||
database = container.database()
|
||||
assert isinstance(database, mock.Mock)
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
"""Dynamic container simple example."""
|
||||
"""Dynamic container example."""
|
||||
|
||||
import dependency_injector.containers as containers
|
||||
import dependency_injector.providers as providers
|
||||
from dependency_injector import containers, providers
|
||||
|
||||
|
||||
# Defining dynamic container:
|
||||
container = containers.DynamicContainer()
|
||||
container.factory1 = providers.Factory(object)
|
||||
container.factory2 = providers.Factory(object)
|
||||
if __name__ == '__main__':
|
||||
container = containers.DynamicContainer()
|
||||
container.factory1 = providers.Factory(object)
|
||||
container.factory2 = providers.Factory(object)
|
||||
|
||||
# Creating some objects:
|
||||
object1 = container.factory1()
|
||||
object2 = container.factory2()
|
||||
object1 = container.factory1()
|
||||
object2 = container.factory2()
|
||||
|
||||
# Making some asserts:
|
||||
assert object1 is not object2
|
||||
assert isinstance(object1, object) and isinstance(object2, object)
|
||||
print(container.providers)
|
||||
# {
|
||||
# 'factory1': <dependency_injector.providers.Factory(...),
|
||||
# 'factory2': <dependency_injector.providers.Factory(...),
|
||||
# }
|
||||
|
|
|
@ -1,59 +1,40 @@
|
|||
"""Creation of dynamic container based on some configuration example."""
|
||||
"""Creation of dynamic container based on the configuration example."""
|
||||
|
||||
import collections
|
||||
|
||||
import dependency_injector.containers as containers
|
||||
from dependency_injector import containers, providers
|
||||
|
||||
|
||||
# Defining several example services:
|
||||
UsersService = collections.namedtuple('UsersService', [])
|
||||
AuthService = collections.namedtuple('AuthService', [])
|
||||
class UserService:
|
||||
...
|
||||
|
||||
|
||||
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('.')
|
||||
module = __import__('.'.join(path_components[:-1]),
|
||||
locals(),
|
||||
globals(),
|
||||
fromlist=path_components[-1:])
|
||||
return getattr(module, path_components[-1])
|
||||
class AuthService:
|
||||
...
|
||||
|
||||
|
||||
# "Parsing" some configuration:
|
||||
config = {
|
||||
'services': {
|
||||
'users': {
|
||||
'class': '__main__.UsersService',
|
||||
'provider_class': 'dependency_injector.providers.Factory',
|
||||
def populate_container(container, providers_config):
|
||||
for provider_name, provider_info in providers_config.items():
|
||||
provided_cls = globals().get(provider_info['class'])
|
||||
provider_cls = getattr(providers, provider_info['provider_class'])
|
||||
setattr(container, provider_name, provider_cls(provided_cls))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
services_config = {
|
||||
'user': {
|
||||
'class': 'UserService',
|
||||
'provider_class': 'Factory',
|
||||
},
|
||||
'auth': {
|
||||
'class': '__main__.AuthService',
|
||||
'provider_class': 'dependency_injector.providers.Factory',
|
||||
}
|
||||
'class': 'AuthService',
|
||||
'provider_class': 'Factory',
|
||||
},
|
||||
}
|
||||
}
|
||||
services = containers.DynamicContainer()
|
||||
|
||||
# Creating empty container of service providers:
|
||||
services = containers.DynamicContainer()
|
||||
populate_container(services, services_config)
|
||||
|
||||
# Filling dynamic container with service providers using 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'])
|
||||
user_service = services.user()
|
||||
auth_service = services.auth()
|
||||
|
||||
# Binding service provider to the dynamic service providers catalog:
|
||||
setattr(services, service_name, service_provider_cls(service_cls))
|
||||
|
||||
# Creating some objects:
|
||||
users_service = services.users()
|
||||
auth_service = services.auth()
|
||||
|
||||
# Making some asserts:
|
||||
assert isinstance(users_service, UsersService)
|
||||
assert isinstance(auth_service, AuthService)
|
||||
assert isinstance(user_service, UserService)
|
||||
assert isinstance(auth_service, AuthService)
|
||||
|
|
Loading…
Reference in New Issue