Edit providers delegation section

This commit is contained in:
Roman Mogylatov 2020-08-30 22:01:24 -04:00
parent 1bd0abb897
commit 46935b3152
6 changed files with 35 additions and 109 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@ -77,48 +77,20 @@ If ``<dependency>`` is found the underlying provider will receive the
.. _factory_providers_delegation: .. _factory_providers_delegation:
Factory providers delegation Passing providers to the objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:py:class:`Factory` provider could be delegated to any other provider via any When you need to inject the provider itself, but not the result of its call, use the ``.provider``
kind of injection. attribute of the provider that you're going to inject.
As it was mentioned earlier, if :py:class:`Factory` is .. image:: images/factory_delegation.png
injectable value, it will be called every time when injection needs to be
done. But sometimes there is a need to inject :py:class:`Factory` provider
itself (not a result of its call) as a dependency. Such injections are called
- *delegated provider injections*.
Saying in other words, delegation of factories - is a way to inject factories
themselves, instead of results of their calls.
:py:class:`Factory` delegation is performed by wrapping delegated
:py:class:`Factory` into special provider type - :py:class:`Delegate`, that
just returns wrapped :py:class:`Factory`.
Actually, there are three ways for creating factory delegates:
+ ``DelegatedFactory(...)`` - use special type of factory -
:py:class:`DelegatedFactory`. Such factories are always injected as
delegates ("as is").
+ ``Delegate(Factory(...))`` - obviously wrapping factory into
:py:class:`Delegate` provider.
+ ``Factory(...).delegate()`` - calling factory :py:meth:`Factory.delegate`
method, that returns delegate wrapper for current factory.
+ ``Factory(...).provider`` - getting factory :py:attr:`Factory.provider`
attribute, that returns delegate wrapper for current factory (alias of
``Factory(...).delegate()`` method).
Example:
.. image:: /images/providers/factory_delegation.png
:width: 85%
:align: center
.. literalinclude:: ../../examples/providers/factory_delegation.py .. literalinclude:: ../../examples/providers/factory_delegation.py
:language: python :language: python
:lines: 3-
:emphasize-lines: 25
.. _factory_providers_specialization: .. note:: Any provider has a ``.provider`` attribute.
Factory providers specialization Factory providers specialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,82 +1,37 @@
"""`Factory` providers delegation example.""" """`Factory` providers delegation example."""
import collections from typing import Callable, List
import dependency_injector.providers as providers from dependency_injector import providers
Photo = collections.namedtuple('Photo', [])
class User: class User:
"""Example user model.""" def __init__(self, uid: int) -> None:
self.uid = uid
def __init__(self, photos_factory):
"""Initialize instance."""
self.photos_factory = photos_factory
self._main_photo = None
@property
def main_photo(self):
"""Return user's main photo."""
if not self._main_photo:
self._main_photo = self.photos_factory()
return self._main_photo
# Defining User and Photo factories using DelegatedFactory provider: class UserRepository:
photos_factory = providers.DelegatedFactory(Photo) def __init__(self, user_factory: Callable[..., User]) -> None:
users_factory = providers.Factory( self.user_factory = user_factory
User,
photos_factory=photos_factory,
)
# or using Delegate(Factory(...)) def get_all(self) -> List[User]:
return [
self.user_factory(**user_data)
for user_data in [{'uid': 1}, {'uid': 2}]
]
photos_factory = providers.Factory(Photo)
users_factory = providers.Factory( user_factory = providers.Factory(User)
User, user_repository_factory = providers.Factory(
photos_factory=providers.Delegate(photos_factory), UserRepository,
user_factory=user_factory.provider,
) )
# or using Factory(...).delegate() if __name__ == '__main__':
user_repository = user_repository_factory()
photos_factory = providers.Factory(Photo) user1, user2 = user_repository.get_all()
users_factory = providers.Factory(
User,
photos_factory=photos_factory.delegate(),
)
assert user1.uid == 1
# Creating several User objects: assert user2.uid == 2
user1 = users_factory()
user2 = users_factory()
# Same as:
# user1 = User(photos_factory=photos_factory)
# user2 = User(photos_factory=photos_factory)
# Making some asserts:
assert isinstance(user1.main_photo, Photo)
assert isinstance(user2.main_photo, Photo)
# or using Factory(...).provider
photos_factory = providers.Factory(Photo)
users_factory = providers.Factory(
User,
photos_factory=photos_factory.provider,
)
# Creating several User objects:
user1 = users_factory()
user2 = users_factory()
# Same as:
# user1 = User(photos_factory=photos_factory)
# user2 = User(photos_factory=photos_factory)
# Making some asserts:
assert isinstance(user1.main_photo, Photo)
assert isinstance(user2.main_photo, Photo)

View File

@ -8,8 +8,7 @@ class Photo:
class User: class User:
def __init__(self, uid: int, main_photo: Photo) -> None:
def __init__(self, uid: int, main_photo: Photo):
self.uid = uid self.uid = uid
self.main_photo = main_photo self.main_photo = main_photo

View File

@ -4,22 +4,22 @@ from dependency_injector import providers
class Regularizer: class Regularizer:
def __init__(self, alpha: float): def __init__(self, alpha: float) -> None:
self.alpha = alpha self.alpha = alpha
class Loss: class Loss:
def __init__(self, regularizer: Regularizer): def __init__(self, regularizer: Regularizer) -> None:
self.regularizer = regularizer self.regularizer = regularizer
class ClassificationTask: class ClassificationTask:
def __init__(self, loss: Loss): def __init__(self, loss: Loss) -> None:
self.loss = loss self.loss = loss
class Algorithm: class Algorithm:
def __init__(self, task: ClassificationTask): def __init__(self, task: ClassificationTask) -> None:
self.task = task self.task = task