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
:py:class:`DeclarativeContainer` is inversion of control container that
could be defined in declarative manner. It should cover most of the cases
when list of providers that would be included in container is deterministic
(container will not change its structure in runtime).
: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.
Declarative containers have to extend base declarative container class -
: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
Container has the ``.providers`` attribute. It is a dictionary of the container providers.
.. literalinclude:: ../../examples/containers/declarative.py
: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
:width: 100%
:align: center
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 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
:language: python
:lines: 3-
Example of declarative containers's provider injections:
.. image:: /images/containers/declarative_injections.png
:width: 100%
:align: center
Injections in the declarative container are done the usual way:
.. literalinclude:: ../../examples/containers/declarative_injections.py
: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::

View File

@ -1,21 +1,16 @@
IoC Containers
==============
Containers
==========
Containers are collections of providers. Main purpose of containers is to group
providers.
Containers are collections of the 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.
+ Grouping of providers from the same architectural layer (for example,
+ Keeping all the providers in a single container (most common).
+ Grouping of the providers from the same architectural layer (for example,
``Services``, ``Models`` and ``Forms`` containers).
+ Grouping of providers from the same functional groups (for example,
container ``Users``, that contains all functional parts of ``Users``
component).
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.
container ``Users``, that contains all functional parts of the ``users``
package).
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
import dependency_injector.providers as providers
from dependency_injector import containers, providers
# Defining declarative IoC container:
class Container(containers.DeclarativeContainer):
"""Example IoC container."""
factory1 = providers.Factory(object)
factory2 = providers.Factory(object)
# Creating some objects:
object1 = Container.factory1()
object2 = Container.factory2()
container = Container()
# Making some asserts:
assert object1 is not object2
assert isinstance(object1, object)
assert isinstance(object2, object)
object1 = container.factory1()
object2 = container.factory2()
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
import dependency_injector.providers as providers
from dependency_injector import containers, providers
class ContainerA(containers.DeclarativeContainer):
"""Example IoC container A."""
provider1 = providers.Factory(object)
class ContainerB(ContainerA):
"""Example IoC container B."""
provider2 = providers.Singleton(object)
# Making some asserts for `providers` attribute:
assert ContainerA.providers == dict(provider1=ContainerA.provider1)
assert ContainerB.providers == dict(provider1=ContainerA.provider1,
provider2=ContainerB.provider2)
assert ContainerA.providers == {
'provider1': ContainerA.provider1,
}
assert ContainerB.providers == {
'provider1': ContainerA.provider1,
'provider2': ContainerB.provider2,
}
# Making some asserts for `cls_providers` attribute:
assert ContainerA.cls_providers == dict(provider1=ContainerA.provider1)
assert ContainerB.cls_providers == dict(provider2=ContainerB.provider2)
assert ContainerA.cls_providers == {
'provider1': ContainerA.provider1,
}
assert ContainerB.cls_providers == {
'provider2': ContainerB.provider2,
}
# Making some asserts for `inherited_providers` attribute:
assert ContainerA.inherited_providers == dict()
assert ContainerB.inherited_providers == dict(provider1=ContainerB.provider1)
assert ContainerA.inherited_providers == {}
assert ContainerB.inherited_providers == {
'provider1': ContainerA.provider1,
}

View File

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

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)