Improve declarative and dynamic container docs

This commit is contained in:
Roman Mogylatov 2020-08-15 22:09:41 -04:00
parent e0fa746d7f
commit cfdcbaa77a
7 changed files with 80 additions and 100 deletions

View File

@ -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:

View File

@ -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::

View File

@ -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(...),
# }

View File

@ -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)

View File

@ -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)

View File

@ -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(...),
# }

View File

@ -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)