diff --git a/docs/images/factory_delegation.png b/docs/images/factory_delegation.png new file mode 100644 index 00000000..3aa65279 Binary files /dev/null and b/docs/images/factory_delegation.png differ diff --git a/docs/providers/delegation.rst b/docs/providers/delegation.rst deleted file mode 100644 index cde345a3..00000000 --- a/docs/providers/delegation.rst +++ /dev/null @@ -1,76 +0,0 @@ -Providers delegation --------------------- - -Example: - -.. code-block:: python - - """Providers delegation example.""" - - from objects.providers import Factory - from objects.providers import Singleton - from objects.providers import Delegate - - from objects.injections import KwArg - - - class User(object): - - """Example class User.""" - - def __init__(self, id, name): - """Initializer. - - :param id: int - :param name: str - :return: - """ - self.id = id - self.name = name - - - class UserService(object): - - """Example class UserService. - - UserService has dependency on users factory. - """ - - def __init__(self, users_factory): - """Initializer. - - :param users_factory: (objects.providers.Factory) -> User - :return: - """ - self.users_factory = users_factory - - def get_by_id(self, id): - """Return user info by user id.""" - return self.users_factory(id=id, name=self._get_name_from_db(id)) - - def _get_name_from_db(self, id): - """Return user's name from database by his id. - - Main purpose of this method is just to show the fact of retrieving - some user's data from database, so, actually, it simulates work - with database just by merging constant string with provided user's id. - """ - return ''.join(('user', str(id))) - - - # Users factory and UserService provider: - users_factory = Factory(User) - users_service = Singleton(UserService, - KwArg('users_factory', Delegate(users_factory))) - - - # Creating several User objects: - user1 = users_service().get_by_id(1) - user2 = users_service().get_by_id(2) - - # Making some asserts: - assert user1.id == 1 - assert user1.name == 'user1' - - assert user2.id == 2 - assert user2.name == 'user2' diff --git a/docs/providers/factory.rst b/docs/providers/factory.rst index 24a78ca2..d8e13cb1 100644 --- a/docs/providers/factory.rst +++ b/docs/providers/factory.rst @@ -20,7 +20,6 @@ Nothing could be better than brief example: """Example class User.""" - # Factory provider creates new instance of specified class on every call. users_factory = Factory(User) @@ -98,7 +97,6 @@ provided by another factories: """Example class Photo.""" - # User and Photo factories: photos_factory = Factory(Photo) users_factory = Factory(User, @@ -118,7 +116,6 @@ provided by another factories: assert user1 is not user2 assert user1.main_photo is not user2.main_photo - Next example shows how ``Factory`` provider deals with positional and keyword ``__init__`` context arguments. In few words, ``Factory`` provider fully passes positional context arguments to class's ``__init__`` method, but @@ -172,7 +169,6 @@ So, please, follow the example below: """Example class CreditCard.""" - # User, Photo and CreditCard factories: credit_cards_factory = Factory(CreditCard) photos_factory = Factory(Photo) @@ -181,12 +177,14 @@ So, please, follow the example below: KwArg('credit_card', credit_cards_factory)) # Creating several User objects: - user1 = users_factory(1) # Same as: user1 = User(1, - # main_photo=Photo(), - # credit_card=CreditCard()) - user2 = users_factory(2) # Same as: user2 = User(2, - # main_photo=Photo(), - # credit_card=CreditCard()) + user1 = users_factory(1) + # Same as: user1 = User(1, + # main_photo=Photo(), + # credit_card=CreditCard()) + user2 = users_factory(2) + # Same as: user2 = User(2, + # main_photo=Photo(), + # credit_card=CreditCard()) # Making some asserts: assert user1.id == 1 @@ -211,7 +209,6 @@ So, please, follow the example below: assert user3.main_photo is main_photo_mock assert user3.credit_card is credit_card_mock - Factory providers and attribute injections ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -250,7 +247,6 @@ Example: """Example class CreditCard.""" - # User, Photo and CreditCard factories: credit_cards_factory = Factory(CreditCard) photos_factory = Factory(Photo) @@ -259,12 +255,14 @@ Example: Attribute('credit_card', credit_cards_factory)) # Creating several User objects: - user1 = users_factory() # Same as: user1 = User() - # user1.main_photo = Photo() - # user1.credit_card = CreditCard() - user2 = users_factory() # Same as: user2 = User() - # user2.main_photo = Photo() - # user2.credit_card = CreditCard() + user1 = users_factory() + # Same as: user1 = User() + # user1.main_photo = Photo() + # user1.credit_card = CreditCard() + user2 = users_factory() + # Same as: user2 = User() + # user2.main_photo = Photo() + # user2.credit_card = CreditCard() # Making some asserts: assert user1 is not user2 @@ -278,7 +276,6 @@ Example: assert user1.main_photo is not user2.main_photo assert user1.credit_card is not user2.credit_card - Factory providers and method injections ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -330,7 +327,6 @@ Example: """Example class CreditCard.""" - # User, Photo and CreditCard factories: credit_cards_factory = Factory(CreditCard) photos_factory = Factory(Photo) @@ -339,12 +335,14 @@ Example: Method('set_credit_card', credit_cards_factory)) # Creating several User objects: - user1 = users_factory() # Same as: user1 = User() - # user1.set_main_photo(Photo()) - # user1.set_credit_card(CreditCard()) - user2 = users_factory() # Same as: user2 = User() - # user2.set_main_photo(Photo()) - # user2.set_credit_card(CreditCard()) + user1 = users_factory() + # Same as: user1 = User() + # user1.set_main_photo(Photo()) + # user1.set_credit_card(CreditCard()) + user2 = users_factory() + # Same as: user2 = User() + # user2.set_main_photo(Photo()) + # user2.set_credit_card(CreditCard()) # Making some asserts: assert user1 is not user2 @@ -358,3 +356,75 @@ Example: assert user1.main_photo is not user2.main_photo assert user1.credit_card is not user2.credit_card +Factory providers delegation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``Factory`` provider could be delegated to any other provider via any kind of +injection. Saying in other words, delegation of factories - is a way to inject +factories themselves, instead of results of their calls. + +As it was mentioned earlier, ``Injection`` calls ``Factory`` if ``Factory`` is +injectable value. ``Factory`` delegation is performed by wrapping delegated +``Factory`` into special provider type - ``Delegate``, that just returns +``Factory`` itself. + +Another one, more *convenient*, method of creating ``Delegate`` for ``Factory`` +is just calling ``Factory.delegate()`` method that returns delegate for current +factory. + +Example: + +.. image:: /images/factory_delegation.png + +.. code-block:: python + + """`Factory` providers delegation example.""" + + from objects.providers import Factory + from objects.injections import KwArg + + + class User(object): + + """Example class User.""" + + def __init__(self, photos_factory): + """Initializer. + + :param photos_factory: objects.providers.Factory + :return: + """ + self.photos_factory = photos_factory + self._main_photo = None + super(User, self).__init__() + + @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 + + + class Photo(object): + + """Example class Photo.""" + + # User and Photo factories: + photos_factory = Factory(Photo) + users_factory = Factory(User, + KwArg('photos_factory', photos_factory.delegate())) + + # Creating several User objects: + user1 = users_factory() + user2 = users_factory() + + # Making some asserts: + assert isinstance(user1, User) + assert isinstance(user1.main_photo, Photo) + + assert isinstance(user2, User) + assert isinstance(user2.main_photo, Photo) + + assert user1 is not user2 + assert user1.main_photo is not user2.main_photo diff --git a/docs/providers/index.rst b/docs/providers/index.rst index 352d73e7..aa0b2eba 100644 --- a/docs/providers/index.rst +++ b/docs/providers/index.rst @@ -13,5 +13,4 @@ All providers are callable. They describe how particular objects are provided. static callable external_dependency - delegation extending diff --git a/examples/providers/delegation.py b/examples/providers/delegation.py deleted file mode 100644 index 2d8501d4..00000000 --- a/examples/providers/delegation.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Providers delegation example.""" - -from objects.providers import Factory -from objects.providers import Singleton -from objects.providers import Delegate - -from objects.injections import KwArg - - -class User(object): - - """Example class User.""" - - def __init__(self, id, name): - """Initializer. - - :param id: int - :param name: str - :return: - """ - self.id = id - self.name = name - - -class UserService(object): - - """Example class UserService. - - UserService has dependency on users factory. - """ - - def __init__(self, users_factory): - """Initializer. - - :param users_factory: (objects.providers.Factory) -> User - :return: - """ - self.users_factory = users_factory - - def get_by_id(self, id): - """Return user info by user id.""" - return self.users_factory(id=id, name=self._get_name_from_db(id)) - - def _get_name_from_db(self, id): - """Return user's name from database by his id. - - Main purpose of this method is just to show the fact of retrieving - some user's data from database, so, actually, it simulates work - with database just by merging constant string with provided user's id. - """ - return ''.join(('user', str(id))) - - -# Users factory and UserService provider: -users_factory = Factory(User) -users_service = Singleton(UserService, - KwArg('users_factory', Delegate(users_factory))) - - -# Creating several User objects: -user1 = users_service().get_by_id(1) -user2 = users_service().get_by_id(2) - -# Making some asserts: -assert user1.id == 1 -assert user1.name == 'user1' - -assert user2.id == 2 -assert user2.name == 'user2' diff --git a/examples/providers/factory.py b/examples/providers/factory.py index 35532b4b..f1a48df2 100644 --- a/examples/providers/factory.py +++ b/examples/providers/factory.py @@ -7,7 +7,6 @@ class User(object): """Example class User.""" - # Factory provider creates new instance of specified class on every call. users_factory = Factory(User) diff --git a/examples/providers/factory_attribute_injections.py b/examples/providers/factory_attribute_injections.py index 1e5f1e79..f28c179e 100644 --- a/examples/providers/factory_attribute_injections.py +++ b/examples/providers/factory_attribute_injections.py @@ -23,7 +23,6 @@ class CreditCard(object): """Example class CreditCard.""" - # User, Photo and CreditCard factories: credit_cards_factory = Factory(CreditCard) photos_factory = Factory(Photo) @@ -32,12 +31,14 @@ users_factory = Factory(User, Attribute('credit_card', credit_cards_factory)) # Creating several User objects: -user1 = users_factory() # Same as: user1 = User() - # user1.main_photo = Photo() - # user1.credit_card = CreditCard() -user2 = users_factory() # Same as: user2 = User() - # user2.main_photo = Photo() - # user2.credit_card = CreditCard() +user1 = users_factory() +# Same as: user1 = User() +# user1.main_photo = Photo() +# user1.credit_card = CreditCard() +user2 = users_factory() +# Same as: user2 = User() +# user2.main_photo = Photo() +# user2.credit_card = CreditCard() # Making some asserts: assert user1 is not user2 diff --git a/examples/providers/factory_delegation.py b/examples/providers/factory_delegation.py new file mode 100644 index 00000000..d9fc33e0 --- /dev/null +++ b/examples/providers/factory_delegation.py @@ -0,0 +1,50 @@ +"""`Factory` providers delegation example.""" + +from objects.providers import Factory +from objects.injections import KwArg + + +class User(object): + + """Example class User.""" + + def __init__(self, photos_factory): + """Initializer. + + :param photos_factory: objects.providers.Factory + :return: + """ + self.photos_factory = photos_factory + self._main_photo = None + super(User, self).__init__() + + @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 + + +class Photo(object): + + """Example class Photo.""" + +# User and Photo factories: +photos_factory = Factory(Photo) +users_factory = Factory(User, + KwArg('photos_factory', photos_factory.delegate())) + +# Creating several User objects: +user1 = users_factory() +user2 = users_factory() + +# Making some asserts: +assert isinstance(user1, User) +assert isinstance(user1.main_photo, Photo) + +assert isinstance(user2, User) +assert isinstance(user2.main_photo, Photo) + +assert user1 is not user2 +assert user1.main_photo is not user2.main_photo diff --git a/examples/providers/factory_init_injections.py b/examples/providers/factory_init_injections.py index 9d068ed3..18755eb9 100644 --- a/examples/providers/factory_init_injections.py +++ b/examples/providers/factory_init_injections.py @@ -22,7 +22,6 @@ class Photo(object): """Example class Photo.""" - # User and Photo factories: photos_factory = Factory(Photo) users_factory = Factory(User, diff --git a/examples/providers/factory_init_injections_and_contexts.py b/examples/providers/factory_init_injections_and_contexts.py index a43e5f5a..dcc39f35 100644 --- a/examples/providers/factory_init_injections_and_contexts.py +++ b/examples/providers/factory_init_injections_and_contexts.py @@ -39,7 +39,6 @@ class CreditCard(object): """Example class CreditCard.""" - # User, Photo and CreditCard factories: credit_cards_factory = Factory(CreditCard) photos_factory = Factory(Photo) @@ -48,12 +47,14 @@ users_factory = Factory(User, KwArg('credit_card', credit_cards_factory)) # Creating several User objects: -user1 = users_factory(1) # Same as: user1 = User(1, - # main_photo=Photo(), - # credit_card=CreditCard()) -user2 = users_factory(2) # Same as: user2 = User(2, - # main_photo=Photo(), - # credit_card=CreditCard()) +user1 = users_factory(1) +# Same as: user1 = User(1, +# main_photo=Photo(), +# credit_card=CreditCard()) +user2 = users_factory(2) +# Same as: user2 = User(2, +# main_photo=Photo(), +# credit_card=CreditCard()) # Making some asserts: assert user1.id == 1 diff --git a/examples/providers/factory_method_injections.py b/examples/providers/factory_method_injections.py index 83897a52..67acc041 100644 --- a/examples/providers/factory_method_injections.py +++ b/examples/providers/factory_method_injections.py @@ -31,7 +31,6 @@ class CreditCard(object): """Example class CreditCard.""" - # User, Photo and CreditCard factories: credit_cards_factory = Factory(CreditCard) photos_factory = Factory(Photo) @@ -40,12 +39,14 @@ users_factory = Factory(User, Method('set_credit_card', credit_cards_factory)) # Creating several User objects: -user1 = users_factory() # Same as: user1 = User() - # user1.set_main_photo(Photo()) - # user1.set_credit_card(CreditCard()) -user2 = users_factory() # Same as: user2 = User() - # user2.set_main_photo(Photo()) - # user2.set_credit_card(CreditCard()) +user1 = users_factory() +# Same as: user1 = User() +# user1.set_main_photo(Photo()) +# user1.set_credit_card(CreditCard()) +user2 = users_factory() +# Same as: user2 = User() +# user2.set_main_photo(Photo()) +# user2.set_credit_card(CreditCard()) # Making some asserts: assert user1 is not user2