mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-01 00:17:55 +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, | ||||
|    ) | ||||
| 
 | ||||
|    factory = providers.Factory( | ||||
|    concrete_factory = providers.Factory( | ||||
|        base_factory, | ||||
|        extra_argument=2, | ||||
|    ) | ||||
|  | @ -23,7 +23,6 @@ additional arguments. | |||
|        instance = concrete_factory() | ||||
|        # Same as: # instance = SomeClass(base_argument=1, extra_argument=2) | ||||
| 
 | ||||
| 
 | ||||
| Sample code | ||||
| ----------- | ||||
| 
 | ||||
|  | @ -37,8 +36,6 @@ 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 | ||||
|  | @ -55,7 +52,7 @@ Explanation & some more examples: | |||
|    ) | ||||
|    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( | ||||
|        providers.Factory(dict, arg1=1), | ||||
|        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 | ||||
|     password-hashing | ||||
|     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>`_. | ||||
| 
 | ||||
| Listing of the ``example.py``: | ||||
| Sample code | ||||
| ----------- | ||||
| 
 | ||||
| Listing of the pattern example: | ||||
| 
 | ||||
| .. literalinclude:: ../../examples/miniapps/password-hashing/example.py | ||||
|    :language: python | ||||
| 
 | ||||
| Run the example | ||||
| --------------- | ||||
| 
 | ||||
| Instructions for running: | ||||
| 
 | ||||
| .. code-block:: bash | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ Develop | |||
| - Refactor "use cases" example. | ||||
| - Refactor "password hashing" example. | ||||
| - Refactor "chained factories" pattern example. | ||||
| - Refactor "factory of factories" pattern example. | ||||
| - Fix declarative container mypy stub to ``__init__`` to accept not only providers. | ||||
| - 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.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| 
 | ||||
| from data import ( | ||||
|     id_generator, | ||||
|     session, | ||||
|     SqlAlchemyDatabaseService, | ||||
|     TokensService, | ||||
|     Token, | ||||
|     UsersService, | ||||
|     User, | ||||
| ) | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| # "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( | ||||
|         providers.Factory, | ||||
|  | @ -21,49 +45,24 @@ database_factory = providers.Factory( | |||
|         session=session, | ||||
|     ) | ||||
| 
 | ||||
| tokens = providers.Factory( | ||||
|     token_service = providers.Factory( | ||||
|         TokensService, | ||||
|         id_generator=id_generator, | ||||
|         database=database_factory(base_class=Token), | ||||
|     ) | ||||
| 
 | ||||
| users = providers.Factory( | ||||
|     user_service = providers.Factory( | ||||
|         UsersService, | ||||
|         id_generator=id_generator, | ||||
|         database=database_factory(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 | ||||
| if __name__ == '__main__': | ||||
|     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 | ||||
| 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 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} | ||||
|     user_service = container.user_service() | ||||
|     assert user_service.database.base_class is User | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user