mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-23 07:00:57 +03:00
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
|
.. currentmodule:: dependency_injector.containers
|
||||||
|
|
||||||
:py:class:`DeclarativeContainer` is a collection of the providers defined in the declarative
|
:py:class:`DeclarativeContainer` is a class-based style of the providers definition.
|
||||||
manner. It covers the use cases when your application structure does not change in the runtime.
|
|
||||||
|
|
||||||
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
|
.. literalinclude:: ../../examples/containers/declarative.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
|
|
||||||
Your declarative container has to extend base declarative container class -
|
The declarative container providers should only be used when you have the container instance.
|
||||||
:py:class:`dependency_injector.containers.DeclarativeContainer`.
|
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 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 container class provides next attributes:
|
The container class provides next attributes:
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
Dynamic containers
|
Dynamic container
|
||||||
------------------
|
-----------------
|
||||||
|
|
||||||
.. currentmodule:: dependency_injector.containers
|
.. currentmodule:: dependency_injector.containers
|
||||||
|
|
||||||
:py:class:`DynamicContainer` is an inversion of control container with dynamic
|
:py:class:`DynamicContainer` is a collection of the providers defined in the runtime.
|
||||||
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).
|
|
||||||
|
|
||||||
While :py:class:`DeclarativeContainer` acts on class-level,
|
You create the dynamic container instance and put the providers as attributes.
|
||||||
:py:class:`DynamicContainer` does the same on instance-level.
|
|
||||||
|
|
||||||
Here is an simple example of defining dynamic container with several factories:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/containers/dynamic.py
|
.. literalinclude:: ../../examples/containers/dynamic.py
|
||||||
:language: python
|
:language: python
|
||||||
|
:lines: 3-
|
||||||
|
|
||||||
Next example demonstrates creation of dynamic container based on some
|
The dynamic container is good for the case when your application structure depends on the
|
||||||
configuration:
|
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
|
.. literalinclude:: ../../examples/containers/dynamic_runtime_creation.py
|
||||||
:language: python
|
:language: python
|
||||||
|
:lines: 3-
|
||||||
|
|
||||||
.. disqus::
|
.. disqus::
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,14 @@ class Container(containers.DeclarativeContainer):
|
||||||
factory2 = providers.Factory(object)
|
factory2 = providers.Factory(object)
|
||||||
|
|
||||||
|
|
||||||
container = Container()
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
object1 = container.factory1()
|
object1 = container.factory1()
|
||||||
object2 = container.factory2()
|
object2 = container.factory2()
|
||||||
|
|
||||||
print(container.providers)
|
print(container.providers)
|
||||||
# {
|
# {
|
||||||
# 'factory1': <dependency_injector.providers.Factory(...),
|
# 'factory1': <dependency_injector.providers.Factory(...),
|
||||||
# 'factory2': <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()
|
user_service = container.user_service()
|
||||||
auth_service = container.auth_service()
|
auth_service = container.auth_service()
|
||||||
|
|
||||||
assert user_service.db is auth_service.db is container.database()
|
assert user_service.db is auth_service.db is container.database()
|
||||||
assert isinstance(auth_service.user_service, UserService)
|
assert isinstance(auth_service.user_service, UserService)
|
||||||
|
|
|
@ -11,7 +11,8 @@ class Container(containers.DeclarativeContainer):
|
||||||
database = providers.Singleton(sqlite3.connect, ':memory:')
|
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()
|
database = container.database()
|
||||||
assert isinstance(database, mock.Mock)
|
assert isinstance(database, mock.Mock)
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
"""Dynamic container simple example."""
|
"""Dynamic container example."""
|
||||||
|
|
||||||
import dependency_injector.containers as containers
|
from dependency_injector import containers, providers
|
||||||
import dependency_injector.providers as providers
|
|
||||||
|
|
||||||
|
|
||||||
# Defining dynamic container:
|
if __name__ == '__main__':
|
||||||
container = containers.DynamicContainer()
|
container = containers.DynamicContainer()
|
||||||
container.factory1 = providers.Factory(object)
|
container.factory1 = providers.Factory(object)
|
||||||
container.factory2 = providers.Factory(object)
|
container.factory2 = providers.Factory(object)
|
||||||
|
|
||||||
# Creating some objects:
|
object1 = container.factory1()
|
||||||
object1 = container.factory1()
|
object2 = container.factory2()
|
||||||
object2 = container.factory2()
|
|
||||||
|
|
||||||
# Making some asserts:
|
print(container.providers)
|
||||||
assert object1 is not object2
|
# {
|
||||||
assert isinstance(object1, object) and isinstance(object2, object)
|
# '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
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
import dependency_injector.containers as containers
|
|
||||||
|
|
||||||
|
|
||||||
# Defining several example services:
|
class UserService:
|
||||||
UsersService = collections.namedtuple('UsersService', [])
|
...
|
||||||
AuthService = collections.namedtuple('AuthService', [])
|
|
||||||
|
|
||||||
|
|
||||||
def import_cls(cls_name):
|
class AuthService:
|
||||||
"""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])
|
|
||||||
|
|
||||||
|
|
||||||
# "Parsing" some configuration:
|
def populate_container(container, providers_config):
|
||||||
config = {
|
for provider_name, provider_info in providers_config.items():
|
||||||
'services': {
|
provided_cls = globals().get(provider_info['class'])
|
||||||
'users': {
|
provider_cls = getattr(providers, provider_info['provider_class'])
|
||||||
'class': '__main__.UsersService',
|
setattr(container, provider_name, provider_cls(provided_cls))
|
||||||
'provider_class': 'dependency_injector.providers.Factory',
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
services_config = {
|
||||||
|
'user': {
|
||||||
|
'class': 'UserService',
|
||||||
|
'provider_class': 'Factory',
|
||||||
},
|
},
|
||||||
'auth': {
|
'auth': {
|
||||||
'class': '__main__.AuthService',
|
'class': 'AuthService',
|
||||||
'provider_class': 'dependency_injector.providers.Factory',
|
'provider_class': 'Factory',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
services = containers.DynamicContainer()
|
||||||
}
|
|
||||||
|
|
||||||
# Creating empty container of service providers:
|
populate_container(services, services_config)
|
||||||
services = containers.DynamicContainer()
|
|
||||||
|
|
||||||
# Filling dynamic container with service providers using configuration:
|
user_service = services.user()
|
||||||
for service_name, service_info in config['services'].iteritems():
|
auth_service = services.auth()
|
||||||
# Runtime importing of service and service provider classes:
|
|
||||||
service_cls = import_cls(service_info['class'])
|
|
||||||
service_provider_cls = import_cls(service_info['provider_class'])
|
|
||||||
|
|
||||||
# Binding service provider to the dynamic service providers catalog:
|
assert isinstance(user_service, UserService)
|
||||||
setattr(services, service_name, service_provider_cls(service_cls))
|
assert isinstance(auth_service, AuthService)
|
||||||
|
|
||||||
# Creating some objects:
|
|
||||||
users_service = services.users()
|
|
||||||
auth_service = services.auth()
|
|
||||||
|
|
||||||
# Making some asserts:
|
|
||||||
assert isinstance(users_service, UsersService)
|
|
||||||
assert isinstance(auth_service, AuthService)
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user