diff --git a/docs/images/providers/factory_delegation.png b/docs/images/providers/factory_delegation.png deleted file mode 100644 index e9a741dc..00000000 Binary files a/docs/images/providers/factory_delegation.png and /dev/null differ diff --git a/docs/providers/factory.rst b/docs/providers/factory.rst index af45fc5a..88dd68f8 100644 --- a/docs/providers/factory.rst +++ b/docs/providers/factory.rst @@ -77,48 +77,20 @@ If ```` is found the underlying provider will receive the .. _factory_providers_delegation: -Factory providers delegation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Passing providers to the objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`Factory` provider could be delegated to any other provider via any -kind of injection. +When you need to inject the provider itself, but not the result of its call, use the ``.provider`` +attribute of the provider that you're going to inject. -As it was mentioned earlier, if :py:class:`Factory` is -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 +.. image:: images/factory_delegation.png .. literalinclude:: ../../examples/providers/factory_delegation.py :language: python + :lines: 3- + :emphasize-lines: 25 -.. _factory_providers_specialization: +.. note:: Any provider has a ``.provider`` attribute. Factory providers specialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/providers/images/factory_delegation.png b/docs/providers/images/factory_delegation.png new file mode 100644 index 00000000..4def0d08 Binary files /dev/null and b/docs/providers/images/factory_delegation.png differ diff --git a/examples/providers/factory_delegation.py b/examples/providers/factory_delegation.py index 0aee54d3..f6bc02d1 100644 --- a/examples/providers/factory_delegation.py +++ b/examples/providers/factory_delegation.py @@ -1,82 +1,37 @@ """`Factory` providers delegation example.""" -import collections +from typing import Callable, List -import dependency_injector.providers as providers - - -Photo = collections.namedtuple('Photo', []) +from dependency_injector import providers class User: - """Example user model.""" - - 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 + def __init__(self, uid: int) -> None: + self.uid = uid -# Defining User and Photo factories using DelegatedFactory provider: -photos_factory = providers.DelegatedFactory(Photo) -users_factory = providers.Factory( - User, - photos_factory=photos_factory, -) +class UserRepository: + def __init__(self, user_factory: Callable[..., User]) -> None: + self.user_factory = user_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, - photos_factory=providers.Delegate(photos_factory), + +user_factory = providers.Factory(User) +user_repository_factory = providers.Factory( + UserRepository, + user_factory=user_factory.provider, ) -# or using Factory(...).delegate() +if __name__ == '__main__': + user_repository = user_repository_factory() -photos_factory = providers.Factory(Photo) -users_factory = providers.Factory( - User, - photos_factory=photos_factory.delegate(), -) + user1, user2 = user_repository.get_all() - -# 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) - -# 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) + assert user1.uid == 1 + assert user2.uid == 2 diff --git a/examples/providers/factory_init_injections.py b/examples/providers/factory_init_injections.py index ed37fd09..682ace80 100644 --- a/examples/providers/factory_init_injections.py +++ b/examples/providers/factory_init_injections.py @@ -8,8 +8,7 @@ class Photo: class User: - - def __init__(self, uid: int, main_photo: Photo): + def __init__(self, uid: int, main_photo: Photo) -> None: self.uid = uid self.main_photo = main_photo diff --git a/examples/providers/factory_init_injections_underlying.py b/examples/providers/factory_init_injections_underlying.py index 98a386a7..cf49388e 100644 --- a/examples/providers/factory_init_injections_underlying.py +++ b/examples/providers/factory_init_injections_underlying.py @@ -4,22 +4,22 @@ from dependency_injector import providers class Regularizer: - def __init__(self, alpha: float): + def __init__(self, alpha: float) -> None: self.alpha = alpha class Loss: - def __init__(self, regularizer: Regularizer): + def __init__(self, regularizer: Regularizer) -> None: self.regularizer = regularizer class ClassificationTask: - def __init__(self, loss: Loss): + def __init__(self, loss: Loss) -> None: self.loss = loss class Algorithm: - def __init__(self, task: ClassificationTask): + def __init__(self, task: ClassificationTask) -> None: self.task = task