mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 07:57:43 +03:00 
			
		
		
		
	Merge branch 'release/3.37.0' into master
This commit is contained in:
		
						commit
						2cf5efa031
					
				|  | @ -52,7 +52,7 @@ What is ``Dependency Injector``? | |||
| 
 | ||||
| ``Dependency Injector`` is a dependency injection framework for Python. | ||||
| 
 | ||||
| It helps you in implementing the dependency injection principle. | ||||
| It helps implementing the dependency injection principle. | ||||
| 
 | ||||
| What is dependency injection? | ||||
| ----------------------------- | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| .. _containers: | ||||
| 
 | ||||
| Containers | ||||
| ========== | ||||
| 
 | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 8.1 KiB | 
|  | @ -64,22 +64,49 @@ Dependency Injector --- Dependency injection framework for Python | |||
| 
 | ||||
| ``Dependency Injector`` is a dependency injection framework for Python. | ||||
| 
 | ||||
| It stands on two principles: | ||||
| It helps implementing the dependency injection principle. | ||||
| 
 | ||||
| - Explicit is better than implicit (PEP20). | ||||
| - Do no magic to your code. | ||||
| Key features of the ``Dependency Injector``: | ||||
| 
 | ||||
| How does it different from the other frameworks? | ||||
| - **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``, | ||||
|   ``List``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help assembling your | ||||
|   objects. See :ref:`providers`. | ||||
| - **Overriding**. Can override any provider by another provider on the fly. This helps in testing | ||||
|   and configuring dev / stage environment to replace API clients with stubs etc. See | ||||
|   :ref:`provider-overriding`. | ||||
| - **Configuration**. Read configuration from ``yaml`` & ``ini`` files, environment variables | ||||
|   and dictionaries. See :ref:`configuration-provider`. | ||||
| - **Containers**. Provides declarative and dynamic containers. See :ref:`containers`. | ||||
| - **Performance**. Fast. Written in ``Cython``. | ||||
| - **Maturity**. Mature and production-ready. Well-tested, documented and supported. | ||||
| 
 | ||||
| - **No autowiring.** The framework does NOT do any autowiring / autoresolving of the dependencies. You need to specify everything explicitly. Because *"Explicit is better than implicit" (PEP20)*. | ||||
| - **Does not pollute your code.** Your application does NOT know and does NOT depend on the framework. No ``@inject`` decorators, annotations, patching or any other magic tricks. | ||||
| .. code-block:: python | ||||
| 
 | ||||
| ``Dependency Injector`` makes a simple contract with you: | ||||
|    from dependency_injector import containers, providers | ||||
| 
 | ||||
| - You tell the framework how to assemble your objects | ||||
| - The framework does it for you | ||||
| 
 | ||||
| The power of the ``Dependency Injector`` is in its simplicity and straightforwardness. It is a simple tool for the powerful concept. | ||||
|    class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|        config = providers.Configuration() | ||||
| 
 | ||||
|        api_client = providers.Singleton( | ||||
|            ApiClient, | ||||
|            api_key=config.api_key, | ||||
|            timeout=config.timeout.as_int(), | ||||
|        ) | ||||
| 
 | ||||
|        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() | ||||
| 
 | ||||
| With the ``Dependency Injector`` you keep **application structure in one place**. | ||||
| This place is called **the container**. You use the container to manage all the components of the | ||||
|  |  | |||
|  | @ -17,4 +17,3 @@ dependency injection pattern, inversion of control principle and | |||
|     what_is_di | ||||
|     di_in_python | ||||
|     key_features | ||||
|     structure | ||||
|  |  | |||
|  | @ -3,66 +3,33 @@ Key features | |||
| 
 | ||||
| .. meta:: | ||||
|    :keywords: Python,DI,Dependency injection,IoC,Inversion of Control | ||||
|    :description: This article describes key features of "Dependency Injector"  | ||||
|                  framework. It also provides some cases and recommendations  | ||||
|                  about usage of "Dependency Injector" framework. | ||||
|    :description: This article describes key features of the Dependency Injector | ||||
|                  framework. | ||||
| 
 | ||||
| Key features of the ``Dependency Injector``: | ||||
| 
 | ||||
| ``Dependency Injector`` is a dependency injection framework for Python. | ||||
| It was designed to be a unified and developer-friendly tool that helps | ||||
| implement a dependency injection design pattern in a formal, pretty, and | ||||
| Pythonic way. | ||||
| - **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``, | ||||
|   ``List``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help assembling your | ||||
|   objects. See :ref:`providers`. | ||||
| - **Overriding**. Can override any provider by another provider on the fly. This helps in testing | ||||
|   and configuring dev / stage environment to replace API clients with stubs etc. See | ||||
|   :ref:`provider-overriding`. | ||||
| - **Configuration**. Read configuration from ``yaml`` & ``ini`` files, environment variables | ||||
|   and dictionaries. See :ref:`configuration-provider`. | ||||
| - **Containers**. Provides declarative and dynamic containers. See :ref:`containers`. | ||||
| - **Performance**. Fast. Written in ``Cython``. | ||||
| - **Maturity**. Mature and production-ready. Well-tested, documented and supported. | ||||
| 
 | ||||
| It stands on two principles: | ||||
| The framework stands on two principles: | ||||
| 
 | ||||
| - Explicit is better than implicit (PEP20). | ||||
| - Do no magic to your code. | ||||
| - **Explicit is better than implicit (PEP20)**. | ||||
| - **Do not do any magic to your code**. | ||||
| 
 | ||||
| How does it different from the other frameworks? | ||||
| How is that different from the other frameworks? | ||||
| 
 | ||||
| - **No autowiring.** The framework does NOT do any autowiring / autoresolving of the dependencies. You need to specify everything explicitly. Because *"Explicit is better than implicit" (PEP20)*. | ||||
| - **Does not pollute your code.** Your application does NOT know and does NOT depend on the framework. No ``@inject`` decorators, annotations, patching or any other magic tricks. | ||||
| 
 | ||||
| ``Dependency Injector`` makes a simple contract with you: | ||||
| 
 | ||||
| - You tell the framework how to build you code | ||||
| - The framework does it for you | ||||
| 
 | ||||
| The power of the ``Dependency Injector`` is in its simplicity and straightforwardness. It is a simple tool for the powerful concept. | ||||
| 
 | ||||
| The key features of the ``Dependency Injector`` framework are: | ||||
| 
 | ||||
| + Easy, smart, and Pythonic style. | ||||
| + Does NOT pollute client code. | ||||
| + Obvious and clear structure. | ||||
| + Extensibility and flexibility. | ||||
| + High performance. | ||||
| + Memory efficiency. | ||||
| + Thread safety. | ||||
| + Documented. | ||||
| + Semantically versioned. | ||||
| + Distributed as pre-compiled wheels. | ||||
| 
 | ||||
| ``Dependency Injector`` containers and providers are implemented as C extension | ||||
| types using ``Cython``. | ||||
| 
 | ||||
| ``Dependency Injector`` framework can be used in the different application types: | ||||
| 
 | ||||
| + Web applications based on the ``Flask``, ``Django`` or any other web framework. | ||||
| + Asynchronous applications ``asyncio``, ``aiohttp``, ``Tornado``, or ``Twisted``. | ||||
| + Standalone frameworks and libraries. | ||||
| + GUI applications. | ||||
| 
 | ||||
| ``Dependency Injector`` framework can be integrated on the different project | ||||
| stages: | ||||
| 
 | ||||
| + It can be used in the beginning of the development of a new application. | ||||
| + It can be integrated into application that is on its active development stage. | ||||
| + It can be used for refactoring of legacy application. | ||||
| 
 | ||||
| Components of ``Dependency Injector`` framework could be used: | ||||
| 
 | ||||
| + In composition with each other. | ||||
| + Independently from each other. | ||||
| The power of the framework is in a simplicity. ``Dependency Injector`` is a simple tool for the powerful concept. | ||||
| 
 | ||||
| .. disqus:: | ||||
|  |  | |||
|  | @ -1,50 +0,0 @@ | |||
| Structure of Dependency Injector | ||||
| -------------------------------- | ||||
| 
 | ||||
| .. meta:: | ||||
|    :keywords: Python,DI,Dependency injection,IoC,Inversion of Control | ||||
|    :description: This article describes "Dependency Injector" framework  | ||||
|                  components and their interaction between each other.  | ||||
|                  Providers and containers are the former components of  | ||||
|                  the framework. | ||||
| 
 | ||||
| Current section describes *Dependency Injector* main entities and their  | ||||
| interaction between each other. | ||||
| 
 | ||||
| .. image:: /images/internals.png | ||||
|     :width: 100% | ||||
|     :align: center | ||||
| 
 | ||||
| There are 2 main entities: providers & containers. | ||||
| 
 | ||||
| Providers | ||||
| ~~~~~~~~~ | ||||
| 
 | ||||
| Providers are strategies of accessing objects. For example,  | ||||
| :py:class:`dependency_injector.providers.Factory` creates new instance  | ||||
| of provided class every time it is called.  | ||||
| :py:class:`dependency_injector.providers.Singleton` creates provided  | ||||
| instance once and returns it on every next call. Base class is -  | ||||
| :py:class:`dependency_injector.providers.Provider`. | ||||
| 
 | ||||
| Providers could be: | ||||
| 
 | ||||
| + Injected into each other. | ||||
| + Overridden by each other. | ||||
| + Extended. | ||||
| 
 | ||||
| Containers  | ||||
| ~~~~~~~~~~ | ||||
| 
 | ||||
| Containers are collections of providers. They are used for grouping  | ||||
| of providers by some principles. Base class is -  | ||||
| :py:class:`dependency_injector.containers.DeclarativeContainer`. | ||||
| 
 | ||||
| Containers could be: | ||||
| 
 | ||||
| + Overridden by each other. | ||||
| + Copied from each other. | ||||
| + Extended. | ||||
| 
 | ||||
| 
 | ||||
| .. disqus:: | ||||
|  | @ -7,6 +7,14 @@ that were made in every particular version. | |||
| From version 0.7.6 *Dependency Injector* framework strictly  | ||||
| follows `Semantic versioning`_ | ||||
| 
 | ||||
| 3.37.0 | ||||
| ------ | ||||
| - Update index documentation page. | ||||
| - Make multiple improvements and fixes for the providers documentation. | ||||
| - Update "Key Features" documentation page. | ||||
| - Remove "Structure of Dependency Injector" documentation page. | ||||
| - Edit "Feedback" documentation page. | ||||
| 
 | ||||
| 3.36.0 | ||||
| ------ | ||||
| - Update providers overriding documentation and rework examples. | ||||
|  |  | |||
|  | @ -1,12 +1,8 @@ | |||
| Feedback | ||||
| ======== | ||||
| 
 | ||||
| Feel free to post questions, bugs, feature requests, proposals etc. on | ||||
| *Dependency Injector*  GitHub Issues: | ||||
| 
 | ||||
|     https://github.com/ets-labs/python-dependency-injector/issues | ||||
| 
 | ||||
| Your feedback is quite important! | ||||
| 
 | ||||
| To post a question, bug report, a feature proposal or get some help open a | ||||
| `Github Issue <https://github.com/ets-labs/python-dependency-injector/issues>`_ or leave a comment | ||||
| below. | ||||
| 
 | ||||
| .. disqus:: | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| .. _configuration-provider: | ||||
| 
 | ||||
| Configuration provider | ||||
| ====================== | ||||
| 
 | ||||
|  | @ -14,8 +16,8 @@ Configuration provider | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration.py | ||||
|    :language: python | ||||
|    :emphasize-lines: 4,9-10 | ||||
|    :lines: 4-14 | ||||
|    :emphasize-lines: 7,12-13 | ||||
|    :lines: 3- | ||||
| 
 | ||||
| It implements the principle "use first, define later". | ||||
| 
 | ||||
|  | @ -27,8 +29,8 @@ Loading from an INI file | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration_ini.py | ||||
|    :language: python | ||||
|    :lines: 3-5,6- | ||||
|    :emphasize-lines: 6 | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 12 | ||||
| 
 | ||||
| where ``examples/providers/configuration/config.ini`` is: | ||||
| 
 | ||||
|  | @ -47,8 +49,8 @@ Loading from a YAML file | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration_yaml.py | ||||
|    :language: python | ||||
|    :lines: 3-5,6- | ||||
|    :emphasize-lines: 6 | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 12 | ||||
| 
 | ||||
| where ``examples/providers/configuration/config.yml`` is: | ||||
| 
 | ||||
|  | @ -81,8 +83,8 @@ Loading from a dictionary | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration_dict.py | ||||
|    :language: python | ||||
|    :lines: 3-5,6- | ||||
|    :emphasize-lines: 6-13 | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 12-19 | ||||
| 
 | ||||
| Loading from an environment variable | ||||
| ------------------------------------ | ||||
|  | @ -92,8 +94,8 @@ Loading from an environment variable | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration_env.py | ||||
|    :language: python | ||||
|    :lines: 5-7,13-21 | ||||
|    :emphasize-lines: 6-8 | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 18-20 | ||||
| 
 | ||||
| Loading from the multiple sources | ||||
| --------------------------------- | ||||
|  | @ -103,8 +105,8 @@ configuration is merged recursively over the existing configuration. | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration_multiple.py | ||||
|    :language: python | ||||
|    :lines: 3-5,6-14 | ||||
|    :emphasize-lines: 6-7 | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 12-13 | ||||
| 
 | ||||
| where ``examples/providers/configuration/config.local.yml`` is: | ||||
| 
 | ||||
|  | @ -122,7 +124,7 @@ convert it into an ``int`` or a ``float``. | |||
| .. literalinclude:: ../../examples/providers/configuration/configuration_type.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 17 | ||||
|    :emphasize-lines: 19 | ||||
| 
 | ||||
| ``Configuration`` provider has next helper methods: | ||||
| 
 | ||||
|  | @ -135,10 +137,27 @@ The last method ``.as_(callback, *args, **kwargs)`` helps to implement other con | |||
| .. literalinclude:: ../../examples/providers/configuration/configuration_type_custom.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 16 | ||||
|    :emphasize-lines: 18 | ||||
| 
 | ||||
| With the ``.as_(callback, *args, **kwargs)`` you can specify a function that will be called | ||||
| before the injection. The value from the config will be passed as a first argument. The returned | ||||
| value will be injected. Parameters ``*args`` and ``**kwargs`` are handled as any other injections. | ||||
| 
 | ||||
| Injecting invariants | ||||
| -------------------- | ||||
| 
 | ||||
| You can inject invariant configuration options based on the value of the other configuration | ||||
| option. | ||||
| 
 | ||||
| To use that you should provide the switch-value as an item of the configuration option that | ||||
| contains sections ``config.options[config.switch]``: | ||||
| 
 | ||||
| - When the value of the ``config.switch`` is ``A``, the ``config.options.A`` is injected | ||||
| - When the value of the ``config.switch`` is ``B``, the ``config.options.B`` is injected | ||||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration_itemselector.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 15,30-31,38 | ||||
| 
 | ||||
| .. disqus:: | ||||
|  |  | |||
|  | @ -73,7 +73,7 @@ all the classes and use special double-underscore ``__`` syntax for passing the | |||
| .. literalinclude:: ../../examples/providers/factory_init_injections_underlying.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 24-35,39,42,45 | ||||
|    :emphasize-lines: 44,49 | ||||
| 
 | ||||
| When you use ``__`` separator in the name of the keyword argument the ``Factory`` looks for | ||||
| the dependency with the same name as the left part of the ``__`` expression. | ||||
|  | @ -98,7 +98,7 @@ attribute of the provider that you're going to inject. | |||
| .. literalinclude:: ../../examples/providers/factory_delegation.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 25 | ||||
|    :emphasize-lines: 28 | ||||
| 
 | ||||
| .. note:: Any provider has a ``.provider`` attribute. | ||||
| 
 | ||||
|  | @ -135,7 +135,7 @@ provider with two peculiarities: | |||
| .. literalinclude:: ../../examples/providers/abstract_factory.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 32 | ||||
|    :emphasize-lines: 34 | ||||
| 
 | ||||
| Factory aggregate | ||||
| ----------------- | ||||
|  | @ -155,7 +155,7 @@ rest of the arguments are passed to the delegated ``Factory``. | |||
| .. literalinclude:: ../../examples/providers/factory_aggregate.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 31-35,43 | ||||
|    :emphasize-lines: 33-37,47 | ||||
| 
 | ||||
| You can get a dictionary of the aggregated factories using the ``.factories`` attribute of the | ||||
| ``FactoryAggregate``. To get a game factories dictionary from the previous example you can use | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ List provider | |||
| .. literalinclude:: ../../examples/providers/list.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 19-22 | ||||
|    :emphasize-lines: 21-24 | ||||
| 
 | ||||
| ``List`` provider handles positional arguments the same way as a :ref:`factory-provider`. | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ You can inject provided object attribute, item or result of its method call. | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/provided_instance.py | ||||
|    :language: python | ||||
|    :emphasize-lines: 26-32 | ||||
|    :emphasize-lines: 28-34 | ||||
|    :lines: 3- | ||||
| 
 | ||||
| To use the feature you should use the ``.provided`` attribute of the injected provider. This | ||||
|  | @ -32,7 +32,7 @@ You can do nested constructions: | |||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/provided_instance_complex.py | ||||
|    :language: python | ||||
|    :emphasize-lines: 24-30 | ||||
|    :emphasize-lines: 26-32 | ||||
|    :lines: 3- | ||||
| 
 | ||||
| The ``.provided`` attribute is available for the next providers: | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ Selector provider | |||
| .. literalinclude:: ../../examples/providers/selector.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 14-18 | ||||
|    :emphasize-lines: 16-20 | ||||
| 
 | ||||
| The first argument of the ``Selector`` provider is called ``selector``. It can be an option of | ||||
| a ``Configuration`` provider or any other callable. The ``selector`` callable has to return a | ||||
|  |  | |||
|  | @ -32,6 +32,13 @@ factories: | |||
| - :ref:`factory-specialize-provided-type` | ||||
| - :ref:`abstract-factory` | ||||
| 
 | ||||
| ``Singleton`` provider scope is tied to the container. Two different containers will provider | ||||
| two different singleton objects: | ||||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/singleton_multiple_containers.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
| 
 | ||||
| Resetting memorized object | ||||
| -------------------------- | ||||
| 
 | ||||
|  | @ -41,7 +48,7 @@ provider. | |||
| .. literalinclude:: ../../examples/providers/singleton_resetting.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 14 | ||||
|    :emphasize-lines: 18 | ||||
| 
 | ||||
| .. note:: | ||||
|    Resetting of the memorized object clears the reference to it. Further object's lifecycle is | ||||
|  | @ -64,7 +71,7 @@ There are two thread-safe singleton implementations out of the box: | |||
| .. literalinclude:: ../../examples/providers/singleton_thread_locals.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 11,12 | ||||
|    :emphasize-lines: 13,15 | ||||
| 
 | ||||
| Implementing scopes | ||||
| ------------------- | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import dataclasses | |||
| import random | ||||
| from typing import List | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class AbstractCacheClient(metaclass=abc.ABCMeta): | ||||
|  | @ -31,18 +31,22 @@ class Service: | |||
|     cache: AbstractCacheClient | ||||
| 
 | ||||
| 
 | ||||
| cache_client_factory = providers.AbstractFactory(AbstractCacheClient) | ||||
| service_factory = providers.Factory( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     cache_client_factory = providers.AbstractFactory(AbstractCacheClient) | ||||
| 
 | ||||
|     service_factory = providers.Factory( | ||||
|         Service, | ||||
|         cache=cache_client_factory, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     cache_type = random.choice(['redis', 'memcached', None]) | ||||
|     container = Container() | ||||
| 
 | ||||
|     cache_type = random.choice(['redis', 'memcached']) | ||||
|     if cache_type == 'redis': | ||||
|         cache_client_factory.override( | ||||
|         container.cache_client_factory.override( | ||||
|             providers.Factory( | ||||
|                 RedisCacheClient, | ||||
|                 host='localhost', | ||||
|  | @ -51,7 +55,7 @@ if __name__ == '__main__': | |||
|             ), | ||||
|         ) | ||||
|     elif cache_type == 'memcached': | ||||
|         cache_client_factory.override( | ||||
|         container.cache_client_factory.override( | ||||
|             providers.Factory( | ||||
|                 MemcachedCacheClient, | ||||
|                 hosts=['10.0.1.1'], | ||||
|  | @ -60,7 +64,7 @@ if __name__ == '__main__': | |||
|             ), | ||||
|         ) | ||||
| 
 | ||||
|     service = service_factory() | ||||
|     service = container.service_factory() | ||||
|     print(service.cache) | ||||
|     # The output depends on cache_type variable value. | ||||
|     # | ||||
|  |  | |||
|  | @ -2,17 +2,22 @@ | |||
| 
 | ||||
| import passlib.hash | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| password_hasher = providers.Callable( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     password_hasher = providers.Callable( | ||||
|         passlib.hash.sha256_crypt.hash, | ||||
|         salt_size=16, | ||||
|         rounds=10000, | ||||
| ) | ||||
| password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify) | ||||
|     ) | ||||
| 
 | ||||
|     password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     hashed_password = password_hasher('super secret') | ||||
|     assert password_verifier('super secret', hashed_password) | ||||
|     container = Container() | ||||
| 
 | ||||
|     hashed_password = container.password_hasher('super secret') | ||||
|     assert container.password_verifier('super secret', hashed_password) | ||||
|  |  | |||
|  | @ -1,21 +1,24 @@ | |||
| """`Configuration` provider example.""" | ||||
| 
 | ||||
| import boto3 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| s3_client_factory = providers.Factory( | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
|     s3_client_factory = providers.Factory( | ||||
|         boto3.client, | ||||
|         's3', | ||||
|         aws_access_key_id=config.aws.access_key_id, | ||||
|         aws_secret_access_key=config.aws.secret_access_key, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     config.from_dict( | ||||
|     container = Container() | ||||
|     container.config.from_dict( | ||||
|         { | ||||
|             'aws': { | ||||
|                  'access_key_id': 'KEY', | ||||
|  | @ -23,4 +26,4 @@ if __name__ == '__main__': | |||
|              }, | ||||
|         }, | ||||
|     ) | ||||
|     s3_client = s3_client_factory() | ||||
|     s3_client = container.s3_client_factory() | ||||
|  |  | |||
|  | @ -1,20 +1,34 @@ | |||
| """`Configuration` provider values loading example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| config.from_dict( | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     container.config.from_dict( | ||||
|         { | ||||
|             'aws': { | ||||
|                  'access_key_id': 'KEY', | ||||
|                  'secret_access_key': 'SECRET', | ||||
|              }, | ||||
|         }, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| assert config() == {'aws': {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'}} | ||||
| assert config.aws() == {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'} | ||||
| assert config.aws.access_key_id() == 'KEY' | ||||
| assert config.aws.secret_access_key() == 'SECRET' | ||||
|     assert container.config() == { | ||||
|         'aws': { | ||||
|             'access_key_id': 'KEY', | ||||
|             'secret_access_key': 'SECRET', | ||||
|         }, | ||||
|     } | ||||
|     assert container.config.aws() == { | ||||
|         'access_key_id': 'KEY', | ||||
|         'secret_access_key': 'SECRET', | ||||
|     } | ||||
|     assert container.config.aws.access_key_id() == 'KEY' | ||||
|     assert container.config.aws.secret_access_key() == 'SECRET' | ||||
|  |  | |||
|  | @ -2,20 +2,25 @@ | |||
| 
 | ||||
| import os | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| # Emulate environment variables | ||||
| os.environ['AWS_ACCESS_KEY_ID'] = 'KEY' | ||||
| os.environ['AWS_SECRET_ACCESS_KEY'] = 'SECRET' | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
| config.aws.access_key_id.from_env('AWS_ACCESS_KEY_ID') | ||||
| config.aws.secret_access_key.from_env('AWS_SECRET_ACCESS_KEY') | ||||
| config.optional.from_env('UNDEFINED', 'default_value') | ||||
|     # Emulate environment variables | ||||
|     os.environ['AWS_ACCESS_KEY_ID'] = 'KEY' | ||||
|     os.environ['AWS_SECRET_ACCESS_KEY'] = 'SECRET' | ||||
| 
 | ||||
| assert config.aws.access_key_id() == 'KEY' | ||||
| assert config.aws.secret_access_key() == 'SECRET' | ||||
| assert config.optional() == 'default_value' | ||||
|     container.config.aws.access_key_id.from_env('AWS_ACCESS_KEY_ID') | ||||
|     container.config.aws.secret_access_key.from_env('AWS_SECRET_ACCESS_KEY') | ||||
|     container.config.optional.from_env('UNDEFINED', 'default_value') | ||||
| 
 | ||||
|     assert container.config.aws.access_key_id() == 'KEY' | ||||
|     assert container.config.aws.secret_access_key() == 'SECRET' | ||||
|     assert container.config.optional() == 'default_value' | ||||
|  |  | |||
|  | @ -1,13 +1,27 @@ | |||
| """`Configuration` provider values loading example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| config.from_ini('examples/providers/configuration/config.ini') | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
| assert config() == {'aws': {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'}} | ||||
| assert config.aws() == {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'} | ||||
| assert config.aws.access_key_id() == 'KEY' | ||||
| assert config.aws.secret_access_key() == 'SECRET' | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     container.config.from_ini('examples/providers/configuration/config.ini') | ||||
| 
 | ||||
|     assert container.config() == { | ||||
|         'aws': { | ||||
|             'access_key_id': 'KEY', | ||||
|             'secret_access_key': 'SECRET', | ||||
|         }, | ||||
|     } | ||||
|     assert container.config.aws() == { | ||||
|         'access_key_id': 'KEY', | ||||
|         'secret_access_key': 'SECRET', | ||||
|     } | ||||
|     assert container.config.aws.access_key_id() == 'KEY' | ||||
|     assert container.config.aws.secret_access_key() == 'SECRET' | ||||
|  |  | |||
|  | @ -1,11 +1,8 @@ | |||
| """`Configuration` provider dynamic item selector. | ||||
| 
 | ||||
| Details: https://github.com/ets-labs/python-dependency-injector/issues/274 | ||||
| """ | ||||
| """`Configuration` provider dynamic item selector.""" | ||||
| 
 | ||||
| import dataclasses | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| @dataclasses.dataclass | ||||
|  | @ -14,7 +11,9 @@ class Foo: | |||
|     option2: object | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration(default={ | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     config = providers.Configuration(default={ | ||||
|         'target': 'A', | ||||
|         'items': { | ||||
|             'A': { | ||||
|  | @ -26,22 +25,23 @@ config = providers.Configuration(default={ | |||
|                 'option2': 20, | ||||
|             }, | ||||
|         }, | ||||
| }) | ||||
|     }) | ||||
| 
 | ||||
| foo = providers.Factory( | ||||
|     foo_factory = providers.Factory( | ||||
|         Foo, | ||||
|         option1=config.items[config.target].option1, | ||||
|         option2=config.items[config.target].option2, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     config.target.from_env('TARGET') | ||||
|     f = foo() | ||||
|     print(f.option1, f.option2) | ||||
|     container = Container() | ||||
| 
 | ||||
|     container.config.target.from_env('TARGET') | ||||
|     foo = container.foo_factory() | ||||
|     print(foo.option1, foo.option2) | ||||
| 
 | ||||
| # $ TARGET=A python configuration_itemselector.py | ||||
| # 60 80 | ||||
| # $ TARGET=B python configuration_itemselector.py | ||||
| # 10 20 | ||||
|     # $ TARGET=A python configuration_itemselector.py | ||||
|     # 60 80 | ||||
|     # $ TARGET=B python configuration_itemselector.py | ||||
|     # 10 20 | ||||
|  |  | |||
|  | @ -1,14 +1,28 @@ | |||
| """`Configuration` provider values loading example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| config.from_yaml('examples/providers/configuration/config.yml') | ||||
| config.from_yaml('examples/providers/configuration/config.local.yml') | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
| assert config() == {'aws': {'access_key_id': 'LOCAL-KEY', 'secret_access_key': 'LOCAL-SECRET'}} | ||||
| assert config.aws() == {'access_key_id': 'LOCAL-KEY', 'secret_access_key': 'LOCAL-SECRET'} | ||||
| assert config.aws.access_key_id() == 'LOCAL-KEY' | ||||
| assert config.aws.secret_access_key() == 'LOCAL-SECRET' | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     container.config.from_yaml('examples/providers/configuration/config.yml') | ||||
|     container.config.from_yaml('examples/providers/configuration/config.local.yml') | ||||
| 
 | ||||
|     assert container.config() == { | ||||
|         'aws': { | ||||
|             'access_key_id': 'LOCAL-KEY', | ||||
|             'secret_access_key': 'LOCAL-SECRET', | ||||
|         }, | ||||
|     } | ||||
|     assert container.config.aws() == { | ||||
|         'access_key_id': 'LOCAL-KEY', | ||||
|         'secret_access_key': 'LOCAL-SECRET', | ||||
|     } | ||||
|     assert container.config.aws.access_key_id() == 'LOCAL-KEY' | ||||
|     assert container.config.aws.secret_access_key() == 'LOCAL-SECRET' | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| 
 | ||||
| import os | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class ApiClient: | ||||
|  | @ -11,24 +11,28 @@ class ApiClient: | |||
|         self.timeout = timeout | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| api_client_factory = providers.Factory( | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
|     api_client_factory = providers.Factory( | ||||
|         ApiClient, | ||||
|         api_key=config.api.key, | ||||
|         timeout=config.api.timeout.as_int(), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     # Emulate environment variables | ||||
|     os.environ['API_KEY'] = 'secret' | ||||
|     os.environ['API_TIMEOUT'] = '5' | ||||
| 
 | ||||
|     config.api.key.from_env('API_KEY') | ||||
|     config.api.timeout.from_env('API_TIMEOUT') | ||||
|     container.config.api.key.from_env('API_KEY') | ||||
|     container.config.api.timeout.from_env('API_TIMEOUT') | ||||
| 
 | ||||
|     api_client = api_client_factory() | ||||
|     api_client = container.api_client_factory() | ||||
| 
 | ||||
|     assert api_client.api_key == 'secret' | ||||
|     assert api_client.timeout == 5 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| import os | ||||
| import decimal | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class Calculator: | ||||
|  | @ -11,20 +11,24 @@ class Calculator: | |||
|         self.pi = pi | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| calculator_factory = providers.Factory( | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
|     calculator_factory = providers.Factory( | ||||
|         Calculator, | ||||
|         pi=config.pi.as_(decimal.Decimal), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     # Emulate environment variables | ||||
|     os.environ['PI'] = '3.1415926535897932384626433832' | ||||
| 
 | ||||
|     config.pi.from_env('PI') | ||||
|     container.config.pi.from_env('PI') | ||||
| 
 | ||||
|     calculator = calculator_factory() | ||||
|     calculator = container.calculator_factory() | ||||
| 
 | ||||
|     assert calculator.pi == decimal.Decimal('3.1415926535897932384626433832') | ||||
|  |  | |||
|  | @ -1,13 +1,27 @@ | |||
| """`Configuration` provider values loading example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| config.from_yaml('examples/providers/configuration/config.yml') | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
| assert config() == {'aws': {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'}} | ||||
| assert config.aws() == {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'} | ||||
| assert config.aws.access_key_id() == 'KEY' | ||||
| assert config.aws.secret_access_key() == 'SECRET' | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     container.config.from_yaml('examples/providers/configuration/config.yml') | ||||
| 
 | ||||
|     assert container.config() == { | ||||
|         'aws': { | ||||
|             'access_key_id': 'KEY', | ||||
|             'secret_access_key': 'SECRET', | ||||
|         }, | ||||
|     } | ||||
|     assert container.config.aws() == { | ||||
|         'access_key_id': 'KEY', | ||||
|         'secret_access_key': 'SECRET', | ||||
|     } | ||||
|     assert container.config.aws.access_key_id() == 'KEY' | ||||
|     assert container.config.aws.secret_access_key() == 'SECRET' | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| 
 | ||||
| import asyncio | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| async def coroutine(arg1, arg2): | ||||
|  | @ -10,10 +10,14 @@ async def coroutine(arg1, arg2): | |||
|     return arg1, arg2 | ||||
| 
 | ||||
| 
 | ||||
| coroutine_provider = providers.Coroutine(coroutine, arg1=1, arg2=2) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     coroutine_provider = providers.Coroutine(coroutine, arg1=1, arg2=2) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     arg1, arg2 = asyncio.run(coroutine_provider()) | ||||
|     container = Container() | ||||
| 
 | ||||
|     arg1, arg2 = asyncio.run(container.coroutine_provider()) | ||||
|     assert (arg1, arg2) == (1, 2) | ||||
|     assert asyncio.iscoroutinefunction(coroutine_provider) | ||||
|     assert asyncio.iscoroutinefunction(container.coroutine_provider) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """Custom provider example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class CustomFactory(providers.Provider): | ||||
|  | @ -29,14 +29,18 @@ class CustomFactory(providers.Provider): | |||
|         return self._factory(*args, **kwargs) | ||||
| 
 | ||||
| 
 | ||||
| factory = CustomFactory(object) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     factory = CustomFactory(object) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     object1 = factory() | ||||
|     container = Container() | ||||
| 
 | ||||
|     object1 = container.factory() | ||||
|     assert isinstance(object1, object) | ||||
| 
 | ||||
|     object2 = factory() | ||||
|     object2 = container.factory() | ||||
|     assert isinstance(object1, object) | ||||
| 
 | ||||
|     assert object1 is not object2 | ||||
|  |  | |||
|  | @ -1,15 +1,19 @@ | |||
| """`Factory` provider example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class User: | ||||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| users_factory = providers.Factory(User) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     user_factory = providers.Factory(User) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     user1 = users_factory() | ||||
|     user2 = users_factory() | ||||
|     container = Container() | ||||
| 
 | ||||
|     user1 = container.user_factory() | ||||
|     user2 = container.user_factory() | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| import dataclasses | ||||
| import sys | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| @dataclasses.dataclass | ||||
|  | @ -30,11 +30,13 @@ class Ludo(Game): | |||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| game_factory = providers.FactoryAggregate( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     game_factory = providers.FactoryAggregate( | ||||
|         chess=providers.Factory(Chess), | ||||
|         checkers=providers.Factory(Checkers), | ||||
|         ludo=providers.Factory(Ludo), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|  | @ -42,7 +44,9 @@ if __name__ == '__main__': | |||
|     player1 = sys.argv[2].capitalize() | ||||
|     player2 = sys.argv[3].capitalize() | ||||
| 
 | ||||
|     selected_game = game_factory(game_type, player1, player2) | ||||
|     container = Container() | ||||
| 
 | ||||
|     selected_game = container.game_factory(game_type, player1, player2) | ||||
|     selected_game.play() | ||||
| 
 | ||||
|     # $ python factory_aggregate.py chess John Jane | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| 
 | ||||
| from typing import Callable, List | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class User: | ||||
|  | @ -21,15 +21,20 @@ class UserRepository: | |||
|         ] | ||||
| 
 | ||||
| 
 | ||||
| user_factory = providers.Factory(User) | ||||
| user_repository_factory = providers.Factory( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     user_factory = providers.Factory(User) | ||||
| 
 | ||||
|     user_repository_factory = providers.Factory( | ||||
|         UserRepository, | ||||
|         user_factory=user_factory.provider, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     user_repository = user_repository_factory() | ||||
|     container = Container() | ||||
| 
 | ||||
|     user_repository = container.user_repository_factory() | ||||
| 
 | ||||
|     user1, user2 = user_repository.get_all() | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """`Factory` provider init injections example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class Photo: | ||||
|  | @ -13,23 +13,27 @@ class User: | |||
|         self.main_photo = main_photo | ||||
| 
 | ||||
| 
 | ||||
| photo_factory = providers.Factory(Photo) | ||||
| user_factory = providers.Factory( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     photo_factory = providers.Factory(Photo) | ||||
| 
 | ||||
|     user_factory = providers.Factory( | ||||
|         User, | ||||
|         main_photo=photo_factory, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     user1 = user_factory(1) | ||||
|     container = Container() | ||||
| 
 | ||||
|     user1 = container.user_factory(1) | ||||
|     # Same as: # user1 = User(1, main_photo=Photo()) | ||||
| 
 | ||||
|     user2 = user_factory(2) | ||||
|     user2 = container.user_factory(2) | ||||
|     # Same as: # user2 = User(2, main_photo=Photo()) | ||||
| 
 | ||||
|     # Context keyword arguments have a priority: | ||||
|     another_photo = Photo() | ||||
|     user3 = user_factory( | ||||
|     user3 = container.user_factory( | ||||
|         uid=3, | ||||
|         main_photo=another_photo, | ||||
|     ) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """`Factory` provider - passing injections to the underlying providers example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class Regularizer: | ||||
|  | @ -23,7 +23,9 @@ class Algorithm: | |||
|         self.task = task | ||||
| 
 | ||||
| 
 | ||||
| algorithm_factory = providers.Factory( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     algorithm_factory = providers.Factory( | ||||
|         Algorithm, | ||||
|         task=providers.Factory( | ||||
|             ClassificationTask, | ||||
|  | @ -34,15 +36,18 @@ algorithm_factory = providers.Factory( | |||
|                 ), | ||||
|             ), | ||||
|         ), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     algorithm_1 = algorithm_factory(task__loss__regularizer__alpha=0.5) | ||||
|     container = Container() | ||||
| 
 | ||||
|     algorithm_1 = container.algorithm_factory( | ||||
|         task__loss__regularizer__alpha=0.5, | ||||
|     ) | ||||
|     assert algorithm_1.task.loss.regularizer.alpha == 0.5 | ||||
| 
 | ||||
|     algorithm_2 = algorithm_factory(task__loss__regularizer__alpha=0.7) | ||||
|     algorithm_2 = container.algorithm_factory( | ||||
|         task__loss__regularizer__alpha=0.7, | ||||
|     ) | ||||
|     assert algorithm_2.task.loss.regularizer.alpha == 0.7 | ||||
| 
 | ||||
|     algorithm_3 = algorithm_factory(task__loss__regularizer=Regularizer(alpha=0.8)) | ||||
|     assert algorithm_3.task.loss.regularizer.alpha == 0.8 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """`Factory` specialization with limitation to provided type example.""" | ||||
| 
 | ||||
| from dependency_injector import providers, errors | ||||
| from dependency_injector import containers, providers, errors | ||||
| 
 | ||||
| 
 | ||||
| class BaseService: | ||||
|  | @ -17,10 +17,14 @@ class ServiceProvider(providers.Factory): | |||
| 
 | ||||
| 
 | ||||
| # Creating service provider with a correct provided type: | ||||
| some_service_provider = ServiceProvider(SomeService) | ||||
| class Services(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     some_service_provider = ServiceProvider(SomeService) | ||||
| 
 | ||||
| 
 | ||||
| # Trying to create service provider an incorrect provided type: | ||||
| try: | ||||
|     class Container(containers.DeclarativeContainer): | ||||
|         some_service_provider = ServiceProvider(object) | ||||
| except errors.Error as exception: | ||||
|     print(exception) | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| import dataclasses | ||||
| from typing import List | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| @dataclasses.dataclass | ||||
|  | @ -16,23 +16,27 @@ class Dispatcher: | |||
|     modules: List[Module] | ||||
| 
 | ||||
| 
 | ||||
| dispatcher_factory = providers.Factory( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     dispatcher_factory = providers.Factory( | ||||
|         Dispatcher, | ||||
|         modules=providers.List( | ||||
|             providers.Factory(Module, name='m1'), | ||||
|             providers.Factory(Module, name='m2'), | ||||
|         ), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     dispatcher = dispatcher_factory() | ||||
|     container = Container() | ||||
| 
 | ||||
|     dispatcher = container.dispatcher_factory() | ||||
| 
 | ||||
|     assert isinstance(dispatcher.modules, list) | ||||
|     assert dispatcher.modules[0].name == 'm1' | ||||
|     assert dispatcher.modules[1].name == 'm2' | ||||
| 
 | ||||
|     # Call "dispatcher = dispatcher_factory()" is an equivalent for: | ||||
|     # Call "dispatcher = container.dispatcher_factory()" is equivalent to: | ||||
|     # dispatcher = Dispatcher( | ||||
|     #     modules=[ | ||||
|     #         Module(name='m1'), | ||||
|  |  | |||
|  | @ -1,10 +1,14 @@ | |||
| """`Object` provider example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| object_provider = providers.Object(1) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     object_provider = providers.Object(1) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     assert object_provider() == 1 | ||||
|     container = Container() | ||||
| 
 | ||||
|     assert container.object_provider() == 1 | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| """Simple providers overriding example.""" | ||||
| 
 | ||||
| import dataclasses | ||||
| import unittest.mock | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class ApiClient: | ||||
|  | @ -13,30 +14,35 @@ class ApiClientStub(ApiClient): | |||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| @dataclasses.dataclass | ||||
| class Service: | ||||
|     def __init__(self, api_client: ApiClient): | ||||
|         self._api_client = api_client | ||||
|     api_client: ApiClient | ||||
| 
 | ||||
| 
 | ||||
| api_client_factory = providers.Factory(ApiClient) | ||||
| service_factory = providers.Factory( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     api_client_factory = providers.Factory(ApiClient) | ||||
| 
 | ||||
|     service_factory = providers.Factory( | ||||
|         Service, | ||||
|         api_client=api_client_factory, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     # 1. Use .override() to replace the API client with stub | ||||
|     api_client_factory.override(providers.Factory(ApiClientStub)) | ||||
|     service1 = service_factory() | ||||
|     container.api_client_factory.override(providers.Factory(ApiClientStub)) | ||||
|     service1 = container.service_factory() | ||||
|     assert isinstance(service1.api_client, ApiClientStub) | ||||
| 
 | ||||
|     # 2. Use .override() as a context manager to mock the API client in testing | ||||
|     with api_client_factory.override(unittest.mock.Mock(ApiClient)): | ||||
|         service3 = service_factory() | ||||
|         assert isinstance(service3.api_client, unittest.mock.Mock) | ||||
|     with container.api_client_factory.override(unittest.mock.Mock(ApiClient)): | ||||
|         service2 = container.service_factory() | ||||
|         assert isinstance(service2.api_client, unittest.mock.Mock) | ||||
| 
 | ||||
|     # 3. Use .reset_override() to get back to normal | ||||
|     api_client_factory.reset_override() | ||||
|     service3 = service_factory() | ||||
|     container.api_client_factory.reset_override() | ||||
|     service3 = container.service_factory() | ||||
|     assert isinstance(service3.api_client, ApiClient) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """Example of the injecting of provided instance attributes and items.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class Service: | ||||
|  | @ -23,17 +23,21 @@ class Client: | |||
|         self.value4 = value4 | ||||
| 
 | ||||
| 
 | ||||
| service = providers.Singleton(Service) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| client_factory = providers.Factory( | ||||
|     service = providers.Singleton(Service) | ||||
| 
 | ||||
|     client_factory = providers.Factory( | ||||
|         Client, | ||||
|         value1=service.provided[0], | ||||
|         value2=service.provided.value, | ||||
|         value3=service.provided.values[0], | ||||
|         value4=service.provided.get_value.call(), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     client = client_factory() | ||||
|     container = Container() | ||||
| 
 | ||||
|     client = container.client_factory() | ||||
|     assert client.value1 == client.value2 == client.value3 == 'foo' | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """Complex example of the injecting of provided instance attributes and items.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class Service: | ||||
|  | @ -12,31 +12,35 @@ class Service: | |||
|         return self.value | ||||
| 
 | ||||
| 
 | ||||
| service = providers.Singleton(Service, value=42) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| dependency = providers.Object( | ||||
|     service = providers.Singleton(Service, value=42) | ||||
| 
 | ||||
|     dependency = providers.Object( | ||||
|         { | ||||
|             'foo': { | ||||
|                 'bar': 10, | ||||
|                 'baz': lambda arg: {'arg': arg} | ||||
|             }, | ||||
|         }, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| demo_list = providers.List( | ||||
|     demo_list = providers.List( | ||||
|         dependency.provided['foo']['bar'], | ||||
|         dependency.provided['foo']['baz'].call(22)['arg'], | ||||
|         dependency.provided['foo']['baz'].call(service)['arg'], | ||||
|         dependency.provided['foo']['baz'].call(service)['arg'].value, | ||||
|         dependency.provided['foo']['baz'].call(service)['arg'].get_value.call(), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     assert demo_list() == [ | ||||
|     container = Container() | ||||
| 
 | ||||
|     assert container.demo_list() == [ | ||||
|         10, | ||||
|         22, | ||||
|         service(), | ||||
|         container.service(), | ||||
|         42, | ||||
|         42, | ||||
|     ] | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """`Selector` provider example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class SomeClass: | ||||
|  | @ -11,19 +11,24 @@ class SomeOtherClass: | |||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| config = providers.Configuration() | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
| selector = providers.Selector( | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
|     selector = providers.Selector( | ||||
|         config.one_or_another, | ||||
|         one=providers.Factory(SomeClass), | ||||
|         another=providers.Factory(SomeOtherClass), | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     config.override({'one_or_another': 'one'}) | ||||
|     instance_1 = selector() | ||||
|     container = Container() | ||||
| 
 | ||||
|     container.config.override({'one_or_another': 'one'}) | ||||
|     instance_1 = container.selector() | ||||
|     assert isinstance(instance_1, SomeClass) | ||||
| 
 | ||||
|     config.override({'one_or_another': 'another'}) | ||||
|     instance_2 = selector() | ||||
|     container.config.override({'one_or_another': 'another'}) | ||||
|     instance_2 = container.selector() | ||||
|     assert isinstance(instance_2, SomeOtherClass) | ||||
|  |  | |||
|  | @ -1,16 +1,20 @@ | |||
| """`Singleton` provider example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class UserService: | ||||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| user_service_provider = providers.Singleton(UserService) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     user_service_provider = providers.Singleton(UserService) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     user_service1 = user_service_provider() | ||||
|     user_service2 = user_service_provider() | ||||
|     container = Container() | ||||
| 
 | ||||
|     user_service1 = container.user_service_provider() | ||||
|     user_service2 = container.user_service_provider() | ||||
|     assert user_service1 is user_service2 | ||||
|  |  | |||
							
								
								
									
										24
									
								
								examples/providers/singleton_multiple_containers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								examples/providers/singleton_multiple_containers.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| """`Singleton` provider resetting example.""" | ||||
| 
 | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class UserService: | ||||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     user_service_provider = providers.Singleton(UserService) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container1 = Container() | ||||
|     user_service1 = container1.user_service_provider() | ||||
|     assert user_service1 is container1.user_service_provider() | ||||
| 
 | ||||
|     container2 = Container() | ||||
|     user_service2 = container2.user_service_provider() | ||||
|     assert user_service2 is container2.user_service_provider() | ||||
| 
 | ||||
|     assert user_service1 is not user_service2 | ||||
|  | @ -1,19 +1,23 @@ | |||
| """`Singleton` provider resetting example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class UserService: | ||||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| user_service_provider = providers.Singleton(UserService) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     user_service_provider = providers.Singleton(UserService) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     user_service1 = user_service_provider() | ||||
|     container = Container() | ||||
| 
 | ||||
|     user_service_provider.reset() | ||||
|     user_service1 = container.user_service_provider() | ||||
| 
 | ||||
|     users_service2 = user_service_provider() | ||||
|     assert users_service2 is not user_service1 | ||||
|     container.user_service_provider.reset() | ||||
| 
 | ||||
|     user_service2 = container.user_service_provider() | ||||
|     assert user_service2 is not user_service1 | ||||
|  |  | |||
|  | @ -1,30 +1,35 @@ | |||
| """`Singleton` - Flask request scope example.""" | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from flask import Flask | ||||
| from dependency_injector import containers, providers | ||||
| from flask import Flask, current_app | ||||
| 
 | ||||
| 
 | ||||
| class Service: | ||||
|     ... | ||||
| 
 | ||||
| 
 | ||||
| service_provider = providers.Singleton(Service) | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     service_provider = providers.Singleton(Service) | ||||
| 
 | ||||
| 
 | ||||
| def index_view(): | ||||
|     service_1 = service_provider() | ||||
|     service_2 = service_provider() | ||||
|     service_1 = current_app.container.service_provider() | ||||
|     service_2 = current_app.container.service_provider() | ||||
|     assert service_1 is service_2 | ||||
|     print(service_1) | ||||
|     return 'Hello  World!' | ||||
| 
 | ||||
| 
 | ||||
| def teardown_context(request): | ||||
|     service_provider.reset() | ||||
|     current_app.container.service_provider.reset() | ||||
|     return request | ||||
| 
 | ||||
| 
 | ||||
| container = Container() | ||||
| 
 | ||||
| app = Flask(__name__) | ||||
| app.container = container | ||||
| app.add_url_rule('/', 'index', view_func=index_view) | ||||
| app.after_request(teardown_context) | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,31 +3,39 @@ | |||
| import threading | ||||
| import queue | ||||
| 
 | ||||
| from dependency_injector import providers | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| def put_in_queue(example_object, queue_object): | ||||
|     queue_object.put(example_object) | ||||
| 
 | ||||
| 
 | ||||
| thread_local_object = providers.ThreadLocalSingleton(object) | ||||
| queue_provider = providers.ThreadSafeSingleton(queue.Queue) | ||||
| put_in_queue = providers.Callable( | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     thread_local_object = providers.ThreadLocalSingleton(object) | ||||
| 
 | ||||
|     queue_provider = providers.ThreadSafeSingleton(queue.Queue) | ||||
| 
 | ||||
|     put_in_queue = providers.Callable( | ||||
|         put_in_queue, | ||||
|         example_object=thread_local_object, | ||||
|         queue_object=queue_provider, | ||||
| ) | ||||
| thread_factory = providers.Factory( | ||||
|     ) | ||||
| 
 | ||||
|     thread_factory = providers.Factory( | ||||
|         threading.Thread, | ||||
|         target=put_in_queue.provider, | ||||
| ) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     n = 10 | ||||
|     threads = [] | ||||
|     for thread_number in range(10): | ||||
|     for thread_number in range(n): | ||||
|         threads.append( | ||||
|             thread_factory(name='Thread{0}'.format(thread_number)), | ||||
|             container.thread_factory(name='Thread{0}'.format(thread_number)), | ||||
|         ) | ||||
|     for thread in threads: | ||||
|         thread.start() | ||||
|  | @ -35,9 +43,9 @@ if __name__ == '__main__': | |||
|         thread.join() | ||||
| 
 | ||||
|     all_objects = set() | ||||
|     while not queue_provider().empty(): | ||||
|         all_objects.add(queue_provider().get()) | ||||
|     while not container.queue_provider().empty(): | ||||
|         all_objects.add(container.queue_provider().get()) | ||||
| 
 | ||||
|     assert len(all_objects) == len(threads) | ||||
|     assert len(all_objects) == len(threads) == n | ||||
|     # Queue contains same number of objects as number of threads where | ||||
|     # thread-local singleton provider was used. | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """Dependency injector top-level package.""" | ||||
| 
 | ||||
| __version__ = '3.36.0' | ||||
| __version__ = '3.37.0' | ||||
| """Version number that follows semantic versioning. | ||||
| 
 | ||||
| :type: str | ||||
|  |  | |||
|  | @ -283,8 +283,8 @@ class Selector(Provider): | |||
| 
 | ||||
| 
 | ||||
| class ProvidedInstanceFluentInterface: | ||||
|     def __getattr__(self, item: str) -> AttributeGetter: ... | ||||
|     def __getitem__(self, item: str) -> ItemGetter: ... | ||||
|     def __getattr__(self, item: Any) -> AttributeGetter: ... | ||||
|     def __getitem__(self, item: Any) -> ItemGetter: ... | ||||
|     def call(self, *args: Injection, **kwargs: Injection) -> MethodCaller: ... | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user