mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
Refactor factory of factories pattern example
This commit is contained in:
parent
8284d1f169
commit
e1844a3040
|
@ -13,7 +13,7 @@ additional arguments.
|
||||||
base_argument=1,
|
base_argument=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
factory = providers.Factory(
|
concrete_factory = providers.Factory(
|
||||||
base_factory,
|
base_factory,
|
||||||
extra_argument=2,
|
extra_argument=2,
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,6 @@ additional arguments.
|
||||||
instance = concrete_factory()
|
instance = concrete_factory()
|
||||||
# Same as: # instance = SomeClass(base_argument=1, extra_argument=2)
|
# Same as: # instance = SomeClass(base_argument=1, extra_argument=2)
|
||||||
|
|
||||||
|
|
||||||
Sample code
|
Sample code
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -37,8 +36,6 @@ Arguments priority
|
||||||
|
|
||||||
Passing of the arguments works the same way like for any other :ref:`factory-provider`.
|
Passing of the arguments works the same way like for any other :ref:`factory-provider`.
|
||||||
|
|
||||||
Explanation & some more examples:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# 1. Keyword arguments of upper level factory are added to lower level factory
|
# 1. Keyword arguments of upper level factory are added to lower level factory
|
||||||
|
@ -55,7 +52,7 @@ Explanation & some more examples:
|
||||||
)
|
)
|
||||||
print(chained_dict_factory()) # prints: {'arg1': 2}
|
print(chained_dict_factory()) # prints: {'arg1': 2}
|
||||||
|
|
||||||
# 3. Keyword arguments provided from context have most priority
|
# 3. Keyword arguments provided from context have the most priority
|
||||||
chained_dict_factory = providers.Factory(
|
chained_dict_factory = providers.Factory(
|
||||||
providers.Factory(dict, arg1=1),
|
providers.Factory(dict, arg1=1),
|
||||||
arg1=2,
|
arg1=2,
|
||||||
|
|
74
docs/examples-other/factory-of-factories.rst
Normal file
74
docs/examples-other/factory-of-factories.rst
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
Factory of Factories pattern
|
||||||
|
============================
|
||||||
|
|
||||||
|
This example demonstrates "Factory of Factories" pattern.
|
||||||
|
|
||||||
|
The idea of the pattern is in creating a ``Factory`` that creates another ``Factory`` and adds
|
||||||
|
additional arguments.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
base_factory = providers.Factory(
|
||||||
|
providers.Factory
|
||||||
|
SomeClass,
|
||||||
|
base_argument=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
concrete_factory = providers.Factory(
|
||||||
|
OtherClass,
|
||||||
|
instance=base_factory(extra_argument=1),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
instance = concrete_factory()
|
||||||
|
# Same as: # instance = SomeClass(base_argument=1, extra_argument=2)
|
||||||
|
|
||||||
|
Sample code
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Listing of the pattern example:
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/miniapps/factory-patterns/factory_of_factories.py
|
||||||
|
:language: python
|
||||||
|
|
||||||
|
Arguments priority
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Passing of the arguments works the same way like for any other :ref:`factory-provider`.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# 1. Keyword arguments of upper level factory are added to lower level factory
|
||||||
|
factory_of_dict_factories = providers.Factory(
|
||||||
|
providers.Factory,
|
||||||
|
dict,
|
||||||
|
arg1=1,
|
||||||
|
)
|
||||||
|
dict_factory = factory_of_dict_factories(arg2=2)
|
||||||
|
print(dict_factory()) # prints: {'arg1': 1, 'arg2': 2}
|
||||||
|
|
||||||
|
# 2. Keyword arguments of upper level factory have priority
|
||||||
|
factory_of_dict_factories = providers.Factory(
|
||||||
|
providers.Factory,
|
||||||
|
dict,
|
||||||
|
arg1=1,
|
||||||
|
)
|
||||||
|
dict_factory = factory_of_dict_factories(arg1=2)
|
||||||
|
print(dict_factory()) # prints: {'arg1': 2}
|
||||||
|
|
||||||
|
# 3. Keyword arguments provided from context have the most priority
|
||||||
|
factory_of_dict_factories = providers.Factory(
|
||||||
|
providers.Factory,
|
||||||
|
dict,
|
||||||
|
arg1=1,
|
||||||
|
)
|
||||||
|
dict_factory = factory_of_dict_factories(arg1=2)
|
||||||
|
print(dict_factory(arg1=3)) # prints: {'arg1': 3}
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
|
||||||
|
The "Factory of Factories" pattern was suggested by the ``Dependency Injector`` users.
|
||||||
|
|
||||||
|
.. disqus::
|
|
@ -1,20 +0,0 @@
|
||||||
Factory of Factories pattern
|
|
||||||
============================
|
|
||||||
|
|
||||||
This example demonstrate implementation of "Factory of Factories" pattern.
|
|
||||||
Main idea of this pattern is about creation of a :py:class:`Factory` that
|
|
||||||
creates another :py:class:`Factory` and mix additional arguments to it.
|
|
||||||
|
|
||||||
Listing of ``data.py``, demonstrates sample classes structure:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/miniapps/factory_patterns/data.py
|
|
||||||
:language: python
|
|
||||||
|
|
||||||
Listing of ``factory_of_factories.py``, demonstrates "Chained Factories"
|
|
||||||
pattern and provide some explanation:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/miniapps/factory_patterns/factory_of_factories.py
|
|
||||||
:language: python
|
|
||||||
|
|
||||||
|
|
||||||
.. disqus::
|
|
|
@ -14,4 +14,4 @@ This sections contains assorted ``Dependency Injector`` examples.
|
||||||
use-cases
|
use-cases
|
||||||
password-hashing
|
password-hashing
|
||||||
chained-factories
|
chained-factories
|
||||||
factory_of_factories
|
factory-of-factories
|
||||||
|
|
|
@ -10,11 +10,17 @@ This example demonstrates an injection of the ``Callable`` provider.
|
||||||
|
|
||||||
The source code is available on the `Github <https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/password-hashing>`_.
|
The source code is available on the `Github <https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/password-hashing>`_.
|
||||||
|
|
||||||
Listing of the ``example.py``:
|
Sample code
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Listing of the pattern example:
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/miniapps/password-hashing/example.py
|
.. literalinclude:: ../../examples/miniapps/password-hashing/example.py
|
||||||
:language: python
|
:language: python
|
||||||
|
|
||||||
|
Run the example
|
||||||
|
---------------
|
||||||
|
|
||||||
Instructions for running:
|
Instructions for running:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
|
@ -12,6 +12,7 @@ Develop
|
||||||
- Refactor "use cases" example.
|
- Refactor "use cases" example.
|
||||||
- Refactor "password hashing" example.
|
- Refactor "password hashing" example.
|
||||||
- Refactor "chained factories" pattern example.
|
- Refactor "chained factories" pattern example.
|
||||||
|
- Refactor "factory of factories" pattern example.
|
||||||
- Fix declarative container mypy stub to ``__init__`` to accept not only providers.
|
- Fix declarative container mypy stub to ``__init__`` to accept not only providers.
|
||||||
- Refactor main module of the "decoupled packages" example.
|
- Refactor main module of the "decoupled packages" example.
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
"""Sample classes and objects."""
|
|
||||||
|
|
||||||
|
|
||||||
class SqlAlchemyDatabaseService:
|
|
||||||
|
|
||||||
def __init__(self, session, base_class):
|
|
||||||
self.session = session
|
|
||||||
self.base_class = base_class
|
|
||||||
|
|
||||||
|
|
||||||
class TokensService:
|
|
||||||
|
|
||||||
def __init__(self, id_generator, database):
|
|
||||||
self.id_generator = id_generator
|
|
||||||
self.database = database
|
|
||||||
|
|
||||||
|
|
||||||
class Token:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
class UsersService:
|
|
||||||
|
|
||||||
def __init__(self, id_generator, database):
|
|
||||||
self.id_generator = id_generator
|
|
||||||
self.database = database
|
|
||||||
|
|
||||||
|
|
||||||
class User:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
# Sample objects
|
|
||||||
session = object()
|
|
||||||
id_generator = object()
|
|
|
@ -1,19 +1,43 @@
|
||||||
"""`Factory of Factories` pattern."""
|
"""`Factory of Factories` pattern."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
from data import (
|
|
||||||
id_generator,
|
|
||||||
session,
|
|
||||||
SqlAlchemyDatabaseService,
|
|
||||||
TokensService,
|
|
||||||
Token,
|
|
||||||
UsersService,
|
|
||||||
User,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# "Factory of Factories" pattern
|
class SqlAlchemyDatabaseService:
|
||||||
|
|
||||||
|
def __init__(self, session, base_class):
|
||||||
|
self.session = session
|
||||||
|
self.base_class = base_class
|
||||||
|
|
||||||
|
|
||||||
|
class TokensService:
|
||||||
|
|
||||||
|
def __init__(self, id_generator, database):
|
||||||
|
self.id_generator = id_generator
|
||||||
|
self.database = database
|
||||||
|
|
||||||
|
|
||||||
|
class Token:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class UsersService:
|
||||||
|
|
||||||
|
def __init__(self, id_generator, database):
|
||||||
|
self.id_generator = id_generator
|
||||||
|
self.database = database
|
||||||
|
|
||||||
|
|
||||||
|
class User:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
# Sample objects
|
||||||
|
session = object()
|
||||||
|
id_generator = object()
|
||||||
|
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
database_factory = providers.Factory(
|
database_factory = providers.Factory(
|
||||||
providers.Factory,
|
providers.Factory,
|
||||||
|
@ -21,49 +45,24 @@ database_factory = providers.Factory(
|
||||||
session=session,
|
session=session,
|
||||||
)
|
)
|
||||||
|
|
||||||
tokens = providers.Factory(
|
token_service = providers.Factory(
|
||||||
TokensService,
|
TokensService,
|
||||||
id_generator=id_generator,
|
id_generator=id_generator,
|
||||||
database=database_factory(base_class=Token),
|
database=database_factory(base_class=Token),
|
||||||
)
|
)
|
||||||
|
|
||||||
users = providers.Factory(
|
user_service = providers.Factory(
|
||||||
UsersService,
|
UsersService,
|
||||||
id_generator=id_generator,
|
id_generator=id_generator,
|
||||||
database=database_factory(base_class=User),
|
database=database_factory(base_class=User),
|
||||||
)
|
)
|
||||||
|
|
||||||
tokens_service = tokens()
|
|
||||||
assert tokens_service.database.base_class is Token
|
|
||||||
|
|
||||||
users_service = users()
|
if __name__ == '__main__':
|
||||||
assert users_service.database.base_class is User
|
container = Container()
|
||||||
|
|
||||||
# Explanation & some more examples
|
token_service = container.token_service()
|
||||||
|
assert token_service.database.base_class is Token
|
||||||
|
|
||||||
# 1. Keyword arguments of upper level factory are added to lower level factory
|
user_service = container.user_service()
|
||||||
factory_of_dict_factories = providers.Factory(
|
assert user_service.database.base_class is User
|
||||||
providers.Factory,
|
|
||||||
dict,
|
|
||||||
arg1=1,
|
|
||||||
)
|
|
||||||
dict_factory = factory_of_dict_factories(arg2=2)
|
|
||||||
print(dict_factory()) # prints: {'arg1': 1, 'arg2': 2}
|
|
||||||
|
|
||||||
# 2. Keyword arguments of upper level factory have priority
|
|
||||||
factory_of_dict_factories = providers.Factory(
|
|
||||||
providers.Factory,
|
|
||||||
dict,
|
|
||||||
arg1=1,
|
|
||||||
)
|
|
||||||
dict_factory = factory_of_dict_factories(arg1=2)
|
|
||||||
print(dict_factory()) # prints: {'arg1': 2}
|
|
||||||
|
|
||||||
# 3. Keyword arguments provided from context have most priority
|
|
||||||
factory_of_dict_factories = providers.Factory(
|
|
||||||
providers.Factory,
|
|
||||||
dict,
|
|
||||||
arg1=1,
|
|
||||||
)
|
|
||||||
dict_factory = factory_of_dict_factories(arg1=2)
|
|
||||||
print(dict_factory(arg1=3)) # prints: {'arg1': 3}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user