mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-30 23:47:40 +03:00 
			
		
		
		
	Update DI Demo 2
This commit is contained in:
		
							parent
							
								
									e479e2cb94
								
							
						
					
					
						commit
						e0fa746d7f
					
				
							
								
								
									
										103
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								README.rst
									
									
									
									
									
								
							|  | @ -52,7 +52,7 @@ What is ``Dependency Injector``? | |||
| 
 | ||||
| ``Dependency Injector`` is a dependency injection framework for Python. | ||||
| 
 | ||||
| It helps you implement the dependency injection principle. | ||||
| It helps you in implementing the dependency injection principle. | ||||
| 
 | ||||
| What is dependency injection? | ||||
| ----------------------------- | ||||
|  | @ -70,6 +70,9 @@ Before: | |||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|    import os | ||||
| 
 | ||||
| 
 | ||||
|    class ApiClient: | ||||
| 
 | ||||
|        def __init__(self): | ||||
|  | @ -82,10 +85,18 @@ Before: | |||
|        def __init__(self): | ||||
|            self.api_client = ApiClient() | ||||
| 
 | ||||
| 
 | ||||
|    if __name__ == '__main__': | ||||
|        service = Service() | ||||
| 
 | ||||
| 
 | ||||
| After: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|    import os | ||||
| 
 | ||||
| 
 | ||||
|    class ApiClient: | ||||
| 
 | ||||
|        def __init__(self, api_key: str, timeout: int): | ||||
|  | @ -98,48 +109,82 @@ After: | |||
|        def __init__(self, api_client: ApiClient): | ||||
|            self.api_client = api_client | ||||
| 
 | ||||
| Who creates the objects now? Look at the next section. | ||||
| 
 | ||||
|    if __name__ == '__main__': | ||||
|        service = Service(ApiClient(os.getenv('API_KEY'), os.getenv('TIMEOUT'))) | ||||
| 
 | ||||
| 
 | ||||
| Flexibility comes with a price: now you need to assemble your objects like this | ||||
| ``Service(ApiClient(os.getenv('API_KEY'), os.getenv('TIMEOUT')))``. The assembly code might get | ||||
| duplicated and it'll become harder to change the application structure. | ||||
| 
 | ||||
| What does Dependency Injector do? | ||||
| --------------------------------- | ||||
| 
 | ||||
| ``Dependency Injector`` provides you with the container and the providers that help you build | ||||
| your application objects when you apply dependency injection principle: | ||||
| ``Dependency Injector`` helps you assemble the objects. | ||||
| 
 | ||||
| It provides you the container and the providers that help you describe objects assembly. When you | ||||
| need an object you get it from the container. The rest of the assembly work is done by the | ||||
| framework: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     from dependency_injector import containers, providers | ||||
|     from unittest import mock | ||||
| 
 | ||||
|     from .example_di import ApiClient, Service | ||||
|    from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
|     class Container(containers.DeclarativeContainer): | ||||
|    class ApiClient: | ||||
| 
 | ||||
|         config = providers.Configuration() | ||||
| 
 | ||||
|         api_client = providers.Singleton( | ||||
|             ApiClient, | ||||
|             api_key=config.api_key, | ||||
|             timeout=config.timeout, | ||||
|         ) | ||||
| 
 | ||||
|         service = providers.Factory( | ||||
|             Service, | ||||
|             api_client=api_client, | ||||
|         ) | ||||
|        def __init__(self, api_key: str, timeout: int): | ||||
|            self.api_key = api_key | ||||
|            self.timeout = timeout | ||||
| 
 | ||||
| 
 | ||||
|     if __name__ == '__main__': | ||||
|         container = Container() | ||||
|         container.config.from_yaml('config.yml') | ||||
|    class Service: | ||||
| 
 | ||||
|         service = container.service() | ||||
|         assert isinstance(service.api_client, ApiClient) | ||||
|        def __init__(self, api_client: ApiClient): | ||||
|            self.api_client = api_client | ||||
| 
 | ||||
|         with container.api_client.override(mock.Mock()): | ||||
|             service = container.service() | ||||
|             assert isinstance(service.api_client, mock.Mock) | ||||
| 
 | ||||
|    class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|        config = providers.Configuration() | ||||
| 
 | ||||
|        api_client = providers.Singleton( | ||||
|            ApiClient, | ||||
|            api_key=config.api_key, | ||||
|            timeout=config.timeout, | ||||
|        ) | ||||
| 
 | ||||
|        service = providers.Factory( | ||||
|            Service, | ||||
|            api_client=api_client, | ||||
|        ) | ||||
| 
 | ||||
| 
 | ||||
|    if __name__ == '__main__': | ||||
|        container = Container() | ||||
|        container.config.api_key.from_env('API_KEY') | ||||
|        container.config.timeout.from_env('TIMEOUT') | ||||
| 
 | ||||
|        service = container.service() | ||||
|        assert isinstance(service.api_client, ApiClient) | ||||
| 
 | ||||
| Retrieving of the ``Service`` instance now is done like this ``container.service()``. | ||||
| 
 | ||||
| Also ``Dependency Injector`` provides a bonus in overriding any of the providers with the | ||||
| ``.override()`` method: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|    from unittest import mock | ||||
| 
 | ||||
| 
 | ||||
|    with container.api_client.override(mock.Mock()): | ||||
|        service = container.service() | ||||
|        assert isinstance(service.api_client, mock.Mock) | ||||
| 
 | ||||
| It helps in a testing. Also you can use it for configuring project for the different environments: | ||||
| replace an API client with a stub on the dev or stage. | ||||
| 
 | ||||
| `More examples <https://github.com/ets-labs/python-dependency-injector/tree/master/examples>`_ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,2 +0,0 @@ | |||
| api_key: test-key | ||||
| timeout: 5 | ||||
|  | @ -1,7 +1,17 @@ | |||
| from dependency_injector import containers, providers | ||||
| from unittest import mock | ||||
| 
 | ||||
| from .example_di import ApiClient, Service | ||||
| 
 | ||||
| class ApiClient: | ||||
| 
 | ||||
|     def __init__(self, api_key: str, timeout: int): | ||||
|         self.api_key = api_key | ||||
|         self.timeout = timeout | ||||
| 
 | ||||
| 
 | ||||
| class Service: | ||||
| 
 | ||||
|     def __init__(self, api_client: ApiClient): | ||||
|         self.api_client = api_client | ||||
| 
 | ||||
| 
 | ||||
| class Container(containers.DeclarativeContainer): | ||||
|  | @ -22,11 +32,8 @@ class Container(containers.DeclarativeContainer): | |||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
|     container.config.from_yaml('config.yml') | ||||
|     container.config.api_key.from_env('API_KEY') | ||||
|     container.config.timeout.from_env('TIMEOUT') | ||||
| 
 | ||||
|     service = container.service() | ||||
|     assert isinstance(service.api_client, ApiClient) | ||||
| 
 | ||||
|     with container.api_client.override(mock.Mock()): | ||||
|         service = container.service() | ||||
|         assert isinstance(service.api_client, mock.Mock) | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| import os | ||||
| 
 | ||||
| 
 | ||||
| class ApiClient: | ||||
|  | @ -11,3 +12,7 @@ class Service: | |||
| 
 | ||||
|     def __init__(self, api_client: ApiClient): | ||||
|         self.api_client = api_client | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     service = Service(ApiClient(os.getenv('API_KEY'), os.getenv('TIMEOUT'))) | ||||
|  |  | |||
|  | @ -12,3 +12,7 @@ class Service: | |||
| 
 | ||||
|     def __init__(self): | ||||
|         self.api_client = ApiClient() | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     service = Service() | ||||
|  |  | |||
							
								
								
									
										11
									
								
								examples/di_demo2/test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/di_demo2/test.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| from unittest import mock | ||||
| 
 | ||||
| from demo import Container | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     with container.api_client.override(mock.Mock()): | ||||
|         service = container.service() | ||||
|         assert isinstance(service.api_client, mock.Mock) | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user