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. | ``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? | What is dependency injection? | ||||||
| ----------------------------- | ----------------------------- | ||||||
|  | @ -70,6 +70,9 @@ Before: | ||||||
| 
 | 
 | ||||||
| .. code-block:: python | .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  |    import os | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|    class ApiClient: |    class ApiClient: | ||||||
| 
 | 
 | ||||||
|        def __init__(self): |        def __init__(self): | ||||||
|  | @ -82,10 +85,18 @@ Before: | ||||||
|        def __init__(self): |        def __init__(self): | ||||||
|            self.api_client = ApiClient() |            self.api_client = ApiClient() | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |    if __name__ == '__main__': | ||||||
|  |        service = Service() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| After: | After: | ||||||
| 
 | 
 | ||||||
| .. code-block:: python | .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  |    import os | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|    class ApiClient: |    class ApiClient: | ||||||
| 
 | 
 | ||||||
|        def __init__(self, api_key: str, timeout: int): |        def __init__(self, api_key: str, timeout: int): | ||||||
|  | @ -98,48 +109,82 @@ After: | ||||||
|        def __init__(self, api_client: ApiClient): |        def __init__(self, api_client: ApiClient): | ||||||
|            self.api_client = api_client |            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? | What does Dependency Injector do? | ||||||
| --------------------------------- | --------------------------------- | ||||||
| 
 | 
 | ||||||
| ``Dependency Injector`` provides you with the container and the providers that help you build | ``Dependency Injector`` helps you assemble the objects. | ||||||
| your application objects when you apply dependency injection principle: | 
 | ||||||
|  | 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 | .. code-block:: python | ||||||
| 
 | 
 | ||||||
|     from dependency_injector import containers, providers |    from dependency_injector import containers, providers | ||||||
|     from unittest import mock |  | ||||||
| 
 |  | ||||||
|     from .example_di import ApiClient, Service |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     class Container(containers.DeclarativeContainer): |    class ApiClient: | ||||||
| 
 | 
 | ||||||
|         config = providers.Configuration() |        def __init__(self, api_key: str, timeout: int): | ||||||
| 
 |            self.api_key = api_key | ||||||
|         api_client = providers.Singleton( |            self.timeout = timeout | ||||||
|             ApiClient, |  | ||||||
|             api_key=config.api_key, |  | ||||||
|             timeout=config.timeout, |  | ||||||
|         ) |  | ||||||
| 
 |  | ||||||
|         service = providers.Factory( |  | ||||||
|             Service, |  | ||||||
|             api_client=api_client, |  | ||||||
|         ) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     if __name__ == '__main__': |    class Service: | ||||||
|         container = Container() |  | ||||||
|         container.config.from_yaml('config.yml') |  | ||||||
| 
 | 
 | ||||||
|         service = container.service() |        def __init__(self, api_client: ApiClient): | ||||||
|         assert isinstance(service.api_client, ApiClient) |            self.api_client = api_client | ||||||
| 
 | 
 | ||||||
|         with container.api_client.override(mock.Mock()): | 
 | ||||||
|             service = container.service() |    class Container(containers.DeclarativeContainer): | ||||||
|             assert isinstance(service.api_client, mock.Mock) | 
 | ||||||
|  |        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>`_ | `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 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): | class Container(containers.DeclarativeContainer): | ||||||
|  | @ -22,11 +32,8 @@ class Container(containers.DeclarativeContainer): | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     container = Container() |     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() |     service = container.service() | ||||||
|     assert isinstance(service.api_client, ApiClient) |     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: | class ApiClient: | ||||||
|  | @ -11,3 +12,7 @@ class Service: | ||||||
| 
 | 
 | ||||||
|     def __init__(self, api_client: ApiClient): |     def __init__(self, api_client: ApiClient): | ||||||
|         self.api_client = api_client |         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): |     def __init__(self): | ||||||
|         self.api_client = ApiClient() |         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