Update the declarative container docs

This commit is contained in:
Roman Mogylatov 2020-08-14 16:27:17 -04:00
parent 925801c73f
commit e479e2cb94
9 changed files with 105 additions and 95 deletions

View File

@ -3,53 +3,42 @@ Declarative containers
.. currentmodule:: dependency_injector.containers .. currentmodule:: dependency_injector.containers
:py:class:`DeclarativeContainer` is inversion of control container that :py:class:`DeclarativeContainer` is a collection of the providers defined in the declarative
could be defined in declarative manner. It should cover most of the cases manner. It covers the use cases when your application structure does not change in the runtime.
when list of providers that would be included in container is deterministic
(container will not change its structure in runtime).
Declarative containers have to extend base declarative container class - Container has the ``.providers`` attribute. It is a dictionary of the container providers.
:py:class:`dependency_injector.containers.DeclarativeContainer`.
Declarative container's providers have to be defined like container's class
attributes. Every provider in container has name. This name should follow
``some_provider`` convention, that is standard naming convention for
attribute names in Python.
.. note::
Declarative containers have several features that could be useful
for some kind of operations on container's providers, please visit API
documentation for getting full list of features -
:py:class:`dependency_injector.containers.DeclarativeContainer`.
Here is an simple example of defining declarative container with several
factories:
.. image:: /images/containers/declarative.png
:width: 85%
:align: center
.. literalinclude:: ../../examples/containers/declarative.py .. literalinclude:: ../../examples/containers/declarative.py
:language: python :language: python
:lines: 3-
Example of declarative containers inheritance: Your declarative container has to extend base declarative container class -
:py:class:`dependency_injector.containers.DeclarativeContainer`.
.. image:: /images/containers/declarative_inheritance.png Declarative container classes can not have any methods or any other attributes then providers.
:width: 100%
:align: center The declarative container providers should only be used after the container is initialized.
The container class provides next attributes:
- ``providers`` - the dictionary of all the container providers
- ``cls_providers`` - the dictionary of the container providers of the current container
- ``inherited_providers`` - the dictionary of all the inherited container providers
.. literalinclude:: ../../examples/containers/declarative_inheritance.py .. literalinclude:: ../../examples/containers/declarative_inheritance.py
:language: python :language: python
:lines: 3-
Example of declarative containers's provider injections: Injections in the declarative container are done the usual way:
.. image:: /images/containers/declarative_injections.png
:width: 100%
:align: center
.. literalinclude:: ../../examples/containers/declarative_injections.py .. literalinclude:: ../../examples/containers/declarative_injections.py
:language: python :language: python
:lines: 3-
You can override the container providers when you create the container instance:
.. literalinclude:: ../../examples/containers/declarative_override_providers.py
:language: python
:lines: 3-
.. disqus:: .. disqus::

View File

@ -1,21 +1,16 @@
IoC Containers Containers
============== ==========
Containers are collections of providers. Main purpose of containers is to group Containers are collections of the providers.
providers.
There are, actually, several popular cases of containers usage: There are several use cases how you can use containers:
+ Keeping all providers in a single container. + Keeping all the providers in a single container (most common).
+ Grouping of providers from the same architectural layer (for example, + Grouping of the providers from the same architectural layer (for example,
``Services``, ``Models`` and ``Forms`` containers). ``Services``, ``Models`` and ``Forms`` containers).
+ Grouping of providers from the same functional groups (for example, + Grouping of providers from the same functional groups (for example,
container ``Users``, that contains all functional parts of ``Users`` container ``Users``, that contains all functional parts of the ``users``
component). package).
Also, for both of these and some other cases, it might be useful to attach
some init / shutdown functionality or something else, that deals with group
of providers.
Containers package API docs - :py:mod:`dependency_injector.containers`. Containers package API docs - :py:mod:`dependency_injector.containers`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

View File

@ -1,23 +1,22 @@
"""Declarative IoC container simple example.""" """Declarative container example."""
import dependency_injector.containers as containers from dependency_injector import containers, providers
import dependency_injector.providers as providers
# Defining declarative IoC container:
class Container(containers.DeclarativeContainer): class Container(containers.DeclarativeContainer):
"""Example IoC container."""
factory1 = providers.Factory(object) factory1 = providers.Factory(object)
factory2 = providers.Factory(object) factory2 = providers.Factory(object)
# Creating some objects: container = Container()
object1 = Container.factory1()
object2 = Container.factory2()
# Making some asserts: object1 = container.factory1()
assert object1 is not object2 object2 = container.factory2()
assert isinstance(object1, object)
assert isinstance(object2, object) print(container.providers)
# {
# 'factory1': <dependency_injector.providers.Factory(...),
# 'factory2': <dependency_injector.providers.Factory(...),
# }

View File

@ -1,30 +1,34 @@
"""Declarative IoC containers inheritance example.""" """Declarative containers inheritance example."""
import dependency_injector.containers as containers from dependency_injector import containers, providers
import dependency_injector.providers as providers
class ContainerA(containers.DeclarativeContainer): class ContainerA(containers.DeclarativeContainer):
"""Example IoC container A."""
provider1 = providers.Factory(object) provider1 = providers.Factory(object)
class ContainerB(ContainerA): class ContainerB(ContainerA):
"""Example IoC container B."""
provider2 = providers.Singleton(object) provider2 = providers.Singleton(object)
# Making some asserts for `providers` attribute: assert ContainerA.providers == {
assert ContainerA.providers == dict(provider1=ContainerA.provider1) 'provider1': ContainerA.provider1,
assert ContainerB.providers == dict(provider1=ContainerA.provider1, }
provider2=ContainerB.provider2) assert ContainerB.providers == {
'provider1': ContainerA.provider1,
'provider2': ContainerB.provider2,
}
# Making some asserts for `cls_providers` attribute: assert ContainerA.cls_providers == {
assert ContainerA.cls_providers == dict(provider1=ContainerA.provider1) 'provider1': ContainerA.provider1,
assert ContainerB.cls_providers == dict(provider2=ContainerB.provider2) }
assert ContainerB.cls_providers == {
'provider2': ContainerB.provider2,
}
# Making some asserts for `inherited_providers` attribute: assert ContainerA.inherited_providers == {}
assert ContainerA.inherited_providers == dict() assert ContainerB.inherited_providers == {
assert ContainerB.inherited_providers == dict(provider1=ContainerB.provider1) 'provider1': ContainerA.provider1,
}

View File

@ -1,35 +1,41 @@
"""Declarative IoC container's provider injections example.""" """Declarative container injections example."""
import sqlite3 import sqlite3
import collections
import dependency_injector.containers as containers from dependency_injector import containers, providers
import dependency_injector.providers as providers
UsersService = collections.namedtuple('UsersService', ['db']) class UserService:
AuthService = collections.namedtuple('AuthService', ['db', 'users_service']) def __init__(self, db: sqlite3.Connection):
self.db = db
class Services(containers.DeclarativeContainer): class AuthService:
"""IoC container of service providers.""" def __init__(self, db: sqlite3.Connection, user_service: UserService):
self.db = db
self.user_service = user_service
class Container(containers.DeclarativeContainer):
database = providers.Singleton(sqlite3.connect, ':memory:') database = providers.Singleton(sqlite3.connect, ':memory:')
users = providers.Factory(UsersService, user_service = providers.Factory(
db=database) UserService,
db=database,
)
auth = providers.Factory(AuthService, auth_service = providers.Factory(
db=database, AuthService,
users_service=users) db=database,
user_service=user_service,
)
# Retrieving service providers from container: container = Container()
users_service = Services.users()
auth_service = Services.auth()
# Making some asserts: user_service = container.user_service()
assert users_service.db is auth_service.db is Services.database() auth_service = container.auth_service()
assert isinstance(auth_service.users_service, UsersService)
assert users_service is not Services.users() assert user_service.db is auth_service.db is container.database()
assert auth_service is not Services.auth() assert isinstance(auth_service.user_service, UserService)

View File

@ -0,0 +1,17 @@
"""Declarative container provider override example."""
import sqlite3
from unittest import mock
from dependency_injector import containers, providers
class Container(containers.DeclarativeContainer):
database = providers.Singleton(sqlite3.connect, ':memory:')
container = Container(database=mock.Mock(sqlite3.Connection))
database = container.database()
assert isinstance(database, mock.Mock)