mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 07:57:43 +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