mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-01-30 19:24:31 +03:00
Refactor chained factories pattern example
This commit is contained in:
parent
d93c4a419b
commit
8284d1f169
71
docs/examples-other/chained-factories.rst
Normal file
71
docs/examples-other/chained-factories.rst
Normal file
|
@ -0,0 +1,71 @@
|
|||
Chained Factories pattern
|
||||
=========================
|
||||
|
||||
This example demonstrates "Chained Factories" pattern.
|
||||
|
||||
The idea of the pattern is in wrapping ``Factory`` into another ``Factory`` that adds
|
||||
additional arguments.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
base_factory = providers.Factory(
|
||||
SomeClass,
|
||||
base_argument=1,
|
||||
)
|
||||
|
||||
factory = providers.Factory(
|
||||
base_factory,
|
||||
extra_argument=2,
|
||||
)
|
||||
|
||||
|
||||
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/chained_factories.py
|
||||
:language: python
|
||||
|
||||
Arguments priority
|
||||
------------------
|
||||
|
||||
Passing of the arguments works the same way like for any other :ref:`factory-provider`.
|
||||
|
||||
Explanation & some more examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# 1. Keyword arguments of upper level factory are added to lower level factory
|
||||
chained_dict_factory = providers.Factory(
|
||||
providers.Factory(dict, arg1=1),
|
||||
arg2=2,
|
||||
)
|
||||
print(chained_dict_factory()) # prints: {'arg1': 1, 'arg2': 2}
|
||||
|
||||
# 2. Keyword arguments of upper level factory have priority
|
||||
chained_dict_factory = providers.Factory(
|
||||
providers.Factory(dict, arg1=1),
|
||||
arg1=2,
|
||||
)
|
||||
print(chained_dict_factory()) # prints: {'arg1': 2}
|
||||
|
||||
# 3. Keyword arguments provided from context have most priority
|
||||
chained_dict_factory = providers.Factory(
|
||||
providers.Factory(dict, arg1=1),
|
||||
arg1=2,
|
||||
)
|
||||
print(chained_dict_factory(arg1=3)) # prints: {'arg1': 3}
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
The "Chained Factories" pattern was suggested by the ``Dependency Injector`` users.
|
||||
|
||||
.. disqus::
|
|
@ -1,21 +0,0 @@
|
|||
Chained Factories pattern
|
||||
=========================
|
||||
|
||||
This example demonstrate implementation of "Chained Factories" pattern.
|
||||
Main idea of this pattern is about wrapping :py:class:`Factory` into
|
||||
another :py:class:`Factory` that mix additional arguments or keyword
|
||||
arguments to a wrapped one.
|
||||
|
||||
Listing of ``data.py``, demonstrates sample classes structure:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/factory_patterns/data.py
|
||||
:language: python
|
||||
|
||||
Listing of ``chained_factories.py``, demonstrates "Chained Factories"
|
||||
pattern and provide some explanation:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/factory_patterns/chained_factories.py
|
||||
:language: python
|
||||
|
||||
|
||||
.. disqus::
|
|
@ -13,5 +13,5 @@ This sections contains assorted ``Dependency Injector`` examples.
|
|||
|
||||
use-cases
|
||||
password-hashing
|
||||
chained_factories
|
||||
chained-factories
|
||||
factory_of_factories
|
||||
|
|
|
@ -11,6 +11,7 @@ Develop
|
|||
-------
|
||||
- Refactor "use cases" example.
|
||||
- Refactor "password hashing" example.
|
||||
- Refactor "chained factories" pattern example.
|
||||
- Fix declarative container mypy stub to ``__init__`` to accept not only providers.
|
||||
- Refactor main module of the "decoupled packages" example.
|
||||
|
||||
|
|
73
examples/miniapps/factory-patterns/chained_factories.py
Normal file
73
examples/miniapps/factory-patterns/chained_factories.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
"""`Chained Factories` pattern."""
|
||||
|
||||
from dependency_injector import containers, providers
|
||||
|
||||
|
||||
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 = providers.Factory(
|
||||
SqlAlchemyDatabaseService,
|
||||
session=session,
|
||||
)
|
||||
|
||||
token_service = providers.Factory(
|
||||
TokensService,
|
||||
id_generator=id_generator,
|
||||
database=providers.Factory(
|
||||
database,
|
||||
base_class=Token,
|
||||
),
|
||||
)
|
||||
|
||||
user_service = providers.Factory(
|
||||
UsersService,
|
||||
id_generator=id_generator,
|
||||
database=providers.Factory(
|
||||
database,
|
||||
base_class=User,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
container = Container()
|
||||
|
||||
token_service = container.token_service()
|
||||
assert token_service.database.base_class is Token
|
||||
|
||||
user_service = container.user_service()
|
||||
assert user_service.database.base_class is User
|
|
@ -1,39 +1,33 @@
|
|||
"""Sample data classes."""
|
||||
"""Sample classes and objects."""
|
||||
|
||||
|
||||
class SqlAlchemyDatabaseService:
|
||||
"""Database service of an entity."""
|
||||
|
||||
def __init__(self, session, base_class):
|
||||
"""Initialize object."""
|
||||
self.session = session
|
||||
self.base_class = base_class
|
||||
|
||||
|
||||
class TokensService:
|
||||
"""Tokens service."""
|
||||
|
||||
def __init__(self, id_generator, database):
|
||||
"""Initialize object."""
|
||||
self.id_generator = id_generator
|
||||
self.database = database
|
||||
|
||||
|
||||
class Token:
|
||||
"""Token entity."""
|
||||
...
|
||||
|
||||
|
||||
class UsersService:
|
||||
"""Users service."""
|
||||
|
||||
def __init__(self, id_generator, database):
|
||||
"""Initialize object."""
|
||||
self.id_generator = id_generator
|
||||
self.database = database
|
||||
|
||||
|
||||
class User:
|
||||
"""User entity."""
|
||||
...
|
||||
|
||||
|
||||
# Sample objects
|
|
@ -1,59 +0,0 @@
|
|||
"""`Chained Factories` pattern."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
from data import (
|
||||
id_generator,
|
||||
session,
|
||||
SqlAlchemyDatabaseService,
|
||||
TokensService,
|
||||
Token,
|
||||
UsersService,
|
||||
User,
|
||||
)
|
||||
|
||||
|
||||
# "Chained Factories" pattern
|
||||
|
||||
database = providers.Factory(SqlAlchemyDatabaseService, session=session)
|
||||
|
||||
tokens = providers.Factory(
|
||||
TokensService,
|
||||
id_generator=id_generator,
|
||||
database=providers.Factory(database, base_class=Token),
|
||||
)
|
||||
|
||||
users = providers.Factory(
|
||||
UsersService,
|
||||
id_generator=id_generator,
|
||||
database=providers.Factory(database, base_class=User),
|
||||
)
|
||||
|
||||
tokens_service = tokens()
|
||||
assert tokens_service.database.base_class is Token
|
||||
|
||||
users_service = users()
|
||||
assert users_service.database.base_class is User
|
||||
|
||||
# Explanation & some more examples
|
||||
|
||||
# 1. Keyword arguments of upper level factory are added to lower level factory
|
||||
chained_dict_factory = providers.Factory(
|
||||
providers.Factory(dict, arg1=1),
|
||||
arg2=2,
|
||||
)
|
||||
print(chained_dict_factory()) # prints: {'arg1': 1, 'arg2': 2}
|
||||
|
||||
# 2. Keyword arguments of upper level factory have priority
|
||||
chained_dict_factory = providers.Factory(
|
||||
providers.Factory(dict, arg1=1),
|
||||
arg1=2,
|
||||
)
|
||||
print(chained_dict_factory()) # prints: {'arg1': 2}
|
||||
|
||||
# 3. Keyword arguments provided from context have most priority
|
||||
chained_dict_factory = providers.Factory(
|
||||
providers.Factory(dict, arg1=1),
|
||||
arg1=2,
|
||||
)
|
||||
print(chained_dict_factory(arg1=3)) # prints: {'arg1': 3}
|
Loading…
Reference in New Issue
Block a user