mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-29 21:14:00 +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.
|
``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?
|
What is dependency injection?
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
.. _containers:
|
||||||
|
|
||||||
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.
|
``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).
|
Key features of the ``Dependency Injector``:
|
||||||
- Do no magic to your code.
|
|
||||||
|
|
||||||
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)*.
|
.. code-block:: python
|
||||||
- **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:
|
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**.
|
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
|
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
|
what_is_di
|
||||||
di_in_python
|
di_in_python
|
||||||
key_features
|
key_features
|
||||||
structure
|
|
||||||
|
|
|
@ -3,66 +3,33 @@ Key features
|
||||||
|
|
||||||
.. meta::
|
.. meta::
|
||||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||||
:description: This article describes key features of "Dependency Injector"
|
:description: This article describes key features of the Dependency Injector
|
||||||
framework. It also provides some cases and recommendations
|
framework.
|
||||||
about usage of "Dependency Injector" framework.
|
|
||||||
|
|
||||||
|
Key features of the ``Dependency Injector``:
|
||||||
|
|
||||||
``Dependency Injector`` is a dependency injection framework for Python.
|
- **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``,
|
||||||
It was designed to be a unified and developer-friendly tool that helps
|
``List``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help assembling your
|
||||||
implement a dependency injection design pattern in a formal, pretty, and
|
objects. See :ref:`providers`.
|
||||||
Pythonic way.
|
- **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).
|
- **Explicit is better than implicit (PEP20)**.
|
||||||
- Do no magic to your code.
|
- **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)*.
|
- **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.
|
- **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:
|
The power of the framework is in a simplicity. ``Dependency Injector`` is a simple tool for the powerful concept.
|
||||||
|
|
||||||
- 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.
|
|
||||||
|
|
||||||
.. disqus::
|
.. 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
|
From version 0.7.6 *Dependency Injector* framework strictly
|
||||||
follows `Semantic versioning`_
|
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
|
3.36.0
|
||||||
------
|
------
|
||||||
- Update providers overriding documentation and rework examples.
|
- Update providers overriding documentation and rework examples.
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
Feedback
|
Feedback
|
||||||
========
|
========
|
||||||
|
|
||||||
Feel free to post questions, bugs, feature requests, proposals etc. on
|
To post a question, bug report, a feature proposal or get some help open a
|
||||||
*Dependency Injector* GitHub Issues:
|
`Github Issue <https://github.com/ets-labs/python-dependency-injector/issues>`_ or leave a comment
|
||||||
|
below.
|
||||||
https://github.com/ets-labs/python-dependency-injector/issues
|
|
||||||
|
|
||||||
Your feedback is quite important!
|
|
||||||
|
|
||||||
|
|
||||||
.. disqus::
|
.. disqus::
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
.. _configuration-provider:
|
||||||
|
|
||||||
Configuration provider
|
Configuration provider
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
@ -14,8 +16,8 @@ Configuration provider
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/configuration/configuration.py
|
.. literalinclude:: ../../examples/providers/configuration/configuration.py
|
||||||
:language: python
|
:language: python
|
||||||
:emphasize-lines: 4,9-10
|
:emphasize-lines: 7,12-13
|
||||||
:lines: 4-14
|
:lines: 3-
|
||||||
|
|
||||||
It implements the principle "use first, define later".
|
It implements the principle "use first, define later".
|
||||||
|
|
||||||
|
@ -27,8 +29,8 @@ Loading from an INI file
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_ini.py
|
.. literalinclude:: ../../examples/providers/configuration/configuration_ini.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-5,6-
|
:lines: 3-
|
||||||
:emphasize-lines: 6
|
:emphasize-lines: 12
|
||||||
|
|
||||||
where ``examples/providers/configuration/config.ini`` is:
|
where ``examples/providers/configuration/config.ini`` is:
|
||||||
|
|
||||||
|
@ -47,8 +49,8 @@ Loading from a YAML file
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_yaml.py
|
.. literalinclude:: ../../examples/providers/configuration/configuration_yaml.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-5,6-
|
:lines: 3-
|
||||||
:emphasize-lines: 6
|
:emphasize-lines: 12
|
||||||
|
|
||||||
where ``examples/providers/configuration/config.yml`` is:
|
where ``examples/providers/configuration/config.yml`` is:
|
||||||
|
|
||||||
|
@ -81,8 +83,8 @@ Loading from a dictionary
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_dict.py
|
.. literalinclude:: ../../examples/providers/configuration/configuration_dict.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-5,6-
|
:lines: 3-
|
||||||
:emphasize-lines: 6-13
|
:emphasize-lines: 12-19
|
||||||
|
|
||||||
Loading from an environment variable
|
Loading from an environment variable
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
@ -92,8 +94,8 @@ Loading from an environment variable
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_env.py
|
.. literalinclude:: ../../examples/providers/configuration/configuration_env.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 5-7,13-21
|
:lines: 3-
|
||||||
:emphasize-lines: 6-8
|
:emphasize-lines: 18-20
|
||||||
|
|
||||||
Loading from the multiple sources
|
Loading from the multiple sources
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
@ -103,8 +105,8 @@ configuration is merged recursively over the existing configuration.
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_multiple.py
|
.. literalinclude:: ../../examples/providers/configuration/configuration_multiple.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-5,6-14
|
:lines: 3-
|
||||||
:emphasize-lines: 6-7
|
:emphasize-lines: 12-13
|
||||||
|
|
||||||
where ``examples/providers/configuration/config.local.yml`` is:
|
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
|
.. literalinclude:: ../../examples/providers/configuration/configuration_type.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 17
|
:emphasize-lines: 19
|
||||||
|
|
||||||
``Configuration`` provider has next helper methods:
|
``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
|
.. literalinclude:: ../../examples/providers/configuration/configuration_type_custom.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 16
|
:emphasize-lines: 18
|
||||||
|
|
||||||
With the ``.as_(callback, *args, **kwargs)`` you can specify a function that will be called
|
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
|
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.
|
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::
|
.. 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
|
.. literalinclude:: ../../examples/providers/factory_init_injections_underlying.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
: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
|
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.
|
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
|
.. literalinclude:: ../../examples/providers/factory_delegation.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 25
|
:emphasize-lines: 28
|
||||||
|
|
||||||
.. note:: Any provider has a ``.provider`` attribute.
|
.. note:: Any provider has a ``.provider`` attribute.
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ provider with two peculiarities:
|
||||||
.. literalinclude:: ../../examples/providers/abstract_factory.py
|
.. literalinclude:: ../../examples/providers/abstract_factory.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 32
|
:emphasize-lines: 34
|
||||||
|
|
||||||
Factory aggregate
|
Factory aggregate
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -155,7 +155,7 @@ rest of the arguments are passed to the delegated ``Factory``.
|
||||||
.. literalinclude:: ../../examples/providers/factory_aggregate.py
|
.. literalinclude:: ../../examples/providers/factory_aggregate.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
: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
|
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
|
``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
|
.. literalinclude:: ../../examples/providers/list.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 19-22
|
:emphasize-lines: 21-24
|
||||||
|
|
||||||
``List`` provider handles positional arguments the same way as a :ref:`factory-provider`.
|
``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
|
.. literalinclude:: ../../examples/providers/provided_instance.py
|
||||||
:language: python
|
:language: python
|
||||||
:emphasize-lines: 26-32
|
:emphasize-lines: 28-34
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
|
|
||||||
To use the feature you should use the ``.provided`` attribute of the injected provider. This
|
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
|
.. literalinclude:: ../../examples/providers/provided_instance_complex.py
|
||||||
:language: python
|
:language: python
|
||||||
:emphasize-lines: 24-30
|
:emphasize-lines: 26-32
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
|
|
||||||
The ``.provided`` attribute is available for the next providers:
|
The ``.provided`` attribute is available for the next providers:
|
||||||
|
|
|
@ -17,7 +17,7 @@ Selector provider
|
||||||
.. literalinclude:: ../../examples/providers/selector.py
|
.. literalinclude:: ../../examples/providers/selector.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
: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
|
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
|
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:`factory-specialize-provided-type`
|
||||||
- :ref:`abstract-factory`
|
- :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
|
Resetting memorized object
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
@ -41,7 +48,7 @@ provider.
|
||||||
.. literalinclude:: ../../examples/providers/singleton_resetting.py
|
.. literalinclude:: ../../examples/providers/singleton_resetting.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 14
|
:emphasize-lines: 18
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Resetting of the memorized object clears the reference to it. Further object's lifecycle is
|
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
|
.. literalinclude:: ../../examples/providers/singleton_thread_locals.py
|
||||||
:language: python
|
:language: python
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 11,12
|
:emphasize-lines: 13,15
|
||||||
|
|
||||||
Implementing scopes
|
Implementing scopes
|
||||||
-------------------
|
-------------------
|
||||||
|
|
|
@ -5,7 +5,7 @@ import dataclasses
|
||||||
import random
|
import random
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class AbstractCacheClient(metaclass=abc.ABCMeta):
|
class AbstractCacheClient(metaclass=abc.ABCMeta):
|
||||||
|
@ -31,18 +31,22 @@ class Service:
|
||||||
cache: AbstractCacheClient
|
cache: AbstractCacheClient
|
||||||
|
|
||||||
|
|
||||||
cache_client_factory = providers.AbstractFactory(AbstractCacheClient)
|
class Container(containers.DeclarativeContainer):
|
||||||
service_factory = providers.Factory(
|
|
||||||
|
cache_client_factory = providers.AbstractFactory(AbstractCacheClient)
|
||||||
|
|
||||||
|
service_factory = providers.Factory(
|
||||||
Service,
|
Service,
|
||||||
cache=cache_client_factory,
|
cache=cache_client_factory,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
cache_type = random.choice(['redis', 'memcached', None])
|
container = Container()
|
||||||
|
|
||||||
|
cache_type = random.choice(['redis', 'memcached'])
|
||||||
if cache_type == 'redis':
|
if cache_type == 'redis':
|
||||||
cache_client_factory.override(
|
container.cache_client_factory.override(
|
||||||
providers.Factory(
|
providers.Factory(
|
||||||
RedisCacheClient,
|
RedisCacheClient,
|
||||||
host='localhost',
|
host='localhost',
|
||||||
|
@ -51,7 +55,7 @@ if __name__ == '__main__':
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
elif cache_type == 'memcached':
|
elif cache_type == 'memcached':
|
||||||
cache_client_factory.override(
|
container.cache_client_factory.override(
|
||||||
providers.Factory(
|
providers.Factory(
|
||||||
MemcachedCacheClient,
|
MemcachedCacheClient,
|
||||||
hosts=['10.0.1.1'],
|
hosts=['10.0.1.1'],
|
||||||
|
@ -60,7 +64,7 @@ if __name__ == '__main__':
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
service = service_factory()
|
service = container.service_factory()
|
||||||
print(service.cache)
|
print(service.cache)
|
||||||
# The output depends on cache_type variable value.
|
# The output depends on cache_type variable value.
|
||||||
#
|
#
|
||||||
|
|
|
@ -2,17 +2,22 @@
|
||||||
|
|
||||||
import passlib.hash
|
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,
|
passlib.hash.sha256_crypt.hash,
|
||||||
salt_size=16,
|
salt_size=16,
|
||||||
rounds=10000,
|
rounds=10000,
|
||||||
)
|
)
|
||||||
password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify)
|
|
||||||
|
password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
hashed_password = password_hasher('super secret')
|
container = Container()
|
||||||
assert password_verifier('super secret', hashed_password)
|
|
||||||
|
hashed_password = container.password_hasher('super secret')
|
||||||
|
assert container.password_verifier('super secret', hashed_password)
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
"""`Configuration` provider example."""
|
"""`Configuration` provider example."""
|
||||||
|
|
||||||
import boto3
|
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,
|
boto3.client,
|
||||||
's3',
|
's3',
|
||||||
aws_access_key_id=config.aws.access_key_id,
|
aws_access_key_id=config.aws.access_key_id,
|
||||||
aws_secret_access_key=config.aws.secret_access_key,
|
aws_secret_access_key=config.aws.secret_access_key,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
config.from_dict(
|
container = Container()
|
||||||
|
container.config.from_dict(
|
||||||
{
|
{
|
||||||
'aws': {
|
'aws': {
|
||||||
'access_key_id': 'KEY',
|
'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."""
|
"""`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': {
|
'aws': {
|
||||||
'access_key_id': 'KEY',
|
'access_key_id': 'KEY',
|
||||||
'secret_access_key': 'SECRET',
|
'secret_access_key': 'SECRET',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert config() == {'aws': {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'}}
|
assert container.config() == {
|
||||||
assert config.aws() == {'access_key_id': 'KEY', 'secret_access_key': 'SECRET'}
|
'aws': {
|
||||||
assert config.aws.access_key_id() == 'KEY'
|
'access_key_id': 'KEY',
|
||||||
assert config.aws.secret_access_key() == 'SECRET'
|
'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
|
import os
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
# Emulate environment variables
|
class Container(containers.DeclarativeContainer):
|
||||||
os.environ['AWS_ACCESS_KEY_ID'] = 'KEY'
|
|
||||||
os.environ['AWS_SECRET_ACCESS_KEY'] = 'SECRET'
|
config = providers.Configuration()
|
||||||
|
|
||||||
|
|
||||||
config = providers.Configuration()
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
config.aws.access_key_id.from_env('AWS_ACCESS_KEY_ID')
|
# Emulate environment variables
|
||||||
config.aws.secret_access_key.from_env('AWS_SECRET_ACCESS_KEY')
|
os.environ['AWS_ACCESS_KEY_ID'] = 'KEY'
|
||||||
config.optional.from_env('UNDEFINED', 'default_value')
|
os.environ['AWS_SECRET_ACCESS_KEY'] = 'SECRET'
|
||||||
|
|
||||||
assert config.aws.access_key_id() == 'KEY'
|
container.config.aws.access_key_id.from_env('AWS_ACCESS_KEY_ID')
|
||||||
assert config.aws.secret_access_key() == 'SECRET'
|
container.config.aws.secret_access_key.from_env('AWS_SECRET_ACCESS_KEY')
|
||||||
assert config.optional() == 'default_value'
|
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."""
|
"""`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'}
|
if __name__ == '__main__':
|
||||||
assert config.aws.access_key_id() == 'KEY'
|
container = Container()
|
||||||
assert config.aws.secret_access_key() == 'SECRET'
|
|
||||||
|
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.
|
"""`Configuration` provider dynamic item selector."""
|
||||||
|
|
||||||
Details: https://github.com/ets-labs/python-dependency-injector/issues/274
|
|
||||||
"""
|
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
|
@ -14,7 +11,9 @@ class Foo:
|
||||||
option2: object
|
option2: object
|
||||||
|
|
||||||
|
|
||||||
config = providers.Configuration(default={
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
config = providers.Configuration(default={
|
||||||
'target': 'A',
|
'target': 'A',
|
||||||
'items': {
|
'items': {
|
||||||
'A': {
|
'A': {
|
||||||
|
@ -26,22 +25,23 @@ config = providers.Configuration(default={
|
||||||
'option2': 20,
|
'option2': 20,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
foo = providers.Factory(
|
foo_factory = providers.Factory(
|
||||||
Foo,
|
Foo,
|
||||||
option1=config.items[config.target].option1,
|
option1=config.items[config.target].option1,
|
||||||
option2=config.items[config.target].option2,
|
option2=config.items[config.target].option2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
config.target.from_env('TARGET')
|
container = Container()
|
||||||
f = foo()
|
|
||||||
print(f.option1, f.option2)
|
|
||||||
|
|
||||||
|
container.config.target.from_env('TARGET')
|
||||||
|
foo = container.foo_factory()
|
||||||
|
print(foo.option1, foo.option2)
|
||||||
|
|
||||||
# $ TARGET=A python configuration_itemselector.py
|
# $ TARGET=A python configuration_itemselector.py
|
||||||
# 60 80
|
# 60 80
|
||||||
# $ TARGET=B python configuration_itemselector.py
|
# $ TARGET=B python configuration_itemselector.py
|
||||||
# 10 20
|
# 10 20
|
||||||
|
|
|
@ -1,14 +1,28 @@
|
||||||
"""`Configuration` provider values loading example."""
|
"""`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()
|
||||||
config.from_yaml('examples/providers/configuration/config.local.yml')
|
|
||||||
|
|
||||||
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'}
|
if __name__ == '__main__':
|
||||||
assert config.aws.access_key_id() == 'LOCAL-KEY'
|
container = Container()
|
||||||
assert config.aws.secret_access_key() == 'LOCAL-SECRET'
|
|
||||||
|
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
|
import os
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class ApiClient:
|
class ApiClient:
|
||||||
|
@ -11,24 +11,28 @@ class ApiClient:
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
|
||||||
|
|
||||||
config = providers.Configuration()
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
api_client_factory = providers.Factory(
|
config = providers.Configuration()
|
||||||
|
|
||||||
|
api_client_factory = providers.Factory(
|
||||||
ApiClient,
|
ApiClient,
|
||||||
api_key=config.api.key,
|
api_key=config.api.key,
|
||||||
timeout=config.api.timeout.as_int(),
|
timeout=config.api.timeout.as_int(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
# Emulate environment variables
|
# Emulate environment variables
|
||||||
os.environ['API_KEY'] = 'secret'
|
os.environ['API_KEY'] = 'secret'
|
||||||
os.environ['API_TIMEOUT'] = '5'
|
os.environ['API_TIMEOUT'] = '5'
|
||||||
|
|
||||||
config.api.key.from_env('API_KEY')
|
container.config.api.key.from_env('API_KEY')
|
||||||
config.api.timeout.from_env('API_TIMEOUT')
|
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.api_key == 'secret'
|
||||||
assert api_client.timeout == 5
|
assert api_client.timeout == 5
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import os
|
import os
|
||||||
import decimal
|
import decimal
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class Calculator:
|
class Calculator:
|
||||||
|
@ -11,20 +11,24 @@ class Calculator:
|
||||||
self.pi = pi
|
self.pi = pi
|
||||||
|
|
||||||
|
|
||||||
config = providers.Configuration()
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
calculator_factory = providers.Factory(
|
config = providers.Configuration()
|
||||||
|
|
||||||
|
calculator_factory = providers.Factory(
|
||||||
Calculator,
|
Calculator,
|
||||||
pi=config.pi.as_(decimal.Decimal),
|
pi=config.pi.as_(decimal.Decimal),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
# Emulate environment variables
|
# Emulate environment variables
|
||||||
os.environ['PI'] = '3.1415926535897932384626433832'
|
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')
|
assert calculator.pi == decimal.Decimal('3.1415926535897932384626433832')
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
"""`Configuration` provider values loading example."""
|
"""`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'}
|
if __name__ == '__main__':
|
||||||
assert config.aws.access_key_id() == 'KEY'
|
container = Container()
|
||||||
assert config.aws.secret_access_key() == 'SECRET'
|
|
||||||
|
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
|
import asyncio
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
async def coroutine(arg1, arg2):
|
async def coroutine(arg1, arg2):
|
||||||
|
@ -10,10 +10,14 @@ async def coroutine(arg1, arg2):
|
||||||
return 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__':
|
if __name__ == '__main__':
|
||||||
arg1, arg2 = asyncio.run(coroutine_provider())
|
container = Container()
|
||||||
|
|
||||||
|
arg1, arg2 = asyncio.run(container.coroutine_provider())
|
||||||
assert (arg1, arg2) == (1, 2)
|
assert (arg1, arg2) == (1, 2)
|
||||||
assert asyncio.iscoroutinefunction(coroutine_provider)
|
assert asyncio.iscoroutinefunction(container.coroutine_provider)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Custom provider example."""
|
"""Custom provider example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class CustomFactory(providers.Provider):
|
class CustomFactory(providers.Provider):
|
||||||
|
@ -29,14 +29,18 @@ class CustomFactory(providers.Provider):
|
||||||
return self._factory(*args, **kwargs)
|
return self._factory(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
factory = CustomFactory(object)
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
factory = CustomFactory(object)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
object1 = factory()
|
container = Container()
|
||||||
|
|
||||||
|
object1 = container.factory()
|
||||||
assert isinstance(object1, object)
|
assert isinstance(object1, object)
|
||||||
|
|
||||||
object2 = factory()
|
object2 = container.factory()
|
||||||
assert isinstance(object1, object)
|
assert isinstance(object1, object)
|
||||||
|
|
||||||
assert object1 is not object2
|
assert object1 is not object2
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
"""`Factory` provider example."""
|
"""`Factory` provider example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class User:
|
class User:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
users_factory = providers.Factory(User)
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
user_factory = providers.Factory(User)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
user1 = users_factory()
|
container = Container()
|
||||||
user2 = users_factory()
|
|
||||||
|
user1 = container.user_factory()
|
||||||
|
user2 = container.user_factory()
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@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),
|
chess=providers.Factory(Chess),
|
||||||
checkers=providers.Factory(Checkers),
|
checkers=providers.Factory(Checkers),
|
||||||
ludo=providers.Factory(Ludo),
|
ludo=providers.Factory(Ludo),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -42,7 +44,9 @@ if __name__ == '__main__':
|
||||||
player1 = sys.argv[2].capitalize()
|
player1 = sys.argv[2].capitalize()
|
||||||
player2 = sys.argv[3].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()
|
selected_game.play()
|
||||||
|
|
||||||
# $ python factory_aggregate.py chess John Jane
|
# $ python factory_aggregate.py chess John Jane
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
from typing import Callable, List
|
from typing import Callable, List
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class User:
|
class User:
|
||||||
|
@ -21,15 +21,20 @@ class UserRepository:
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
user_factory = providers.Factory(User)
|
class Container(containers.DeclarativeContainer):
|
||||||
user_repository_factory = providers.Factory(
|
|
||||||
|
user_factory = providers.Factory(User)
|
||||||
|
|
||||||
|
user_repository_factory = providers.Factory(
|
||||||
UserRepository,
|
UserRepository,
|
||||||
user_factory=user_factory.provider,
|
user_factory=user_factory.provider,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
user_repository = user_repository_factory()
|
container = Container()
|
||||||
|
|
||||||
|
user_repository = container.user_repository_factory()
|
||||||
|
|
||||||
user1, user2 = user_repository.get_all()
|
user1, user2 = user_repository.get_all()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""`Factory` provider init injections example."""
|
"""`Factory` provider init injections example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class Photo:
|
class Photo:
|
||||||
|
@ -13,23 +13,27 @@ class User:
|
||||||
self.main_photo = main_photo
|
self.main_photo = main_photo
|
||||||
|
|
||||||
|
|
||||||
photo_factory = providers.Factory(Photo)
|
class Container(containers.DeclarativeContainer):
|
||||||
user_factory = providers.Factory(
|
|
||||||
|
photo_factory = providers.Factory(Photo)
|
||||||
|
|
||||||
|
user_factory = providers.Factory(
|
||||||
User,
|
User,
|
||||||
main_photo=photo_factory,
|
main_photo=photo_factory,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
user1 = user_factory(1)
|
container = Container()
|
||||||
|
|
||||||
|
user1 = container.user_factory(1)
|
||||||
# Same as: # user1 = User(1, main_photo=Photo())
|
# 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())
|
# Same as: # user2 = User(2, main_photo=Photo())
|
||||||
|
|
||||||
# Context keyword arguments have a priority:
|
|
||||||
another_photo = Photo()
|
another_photo = Photo()
|
||||||
user3 = user_factory(
|
user3 = container.user_factory(
|
||||||
uid=3,
|
uid=3,
|
||||||
main_photo=another_photo,
|
main_photo=another_photo,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""`Factory` provider - passing injections to the underlying providers example."""
|
"""`Factory` provider - passing injections to the underlying providers example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class Regularizer:
|
class Regularizer:
|
||||||
|
@ -23,7 +23,9 @@ class Algorithm:
|
||||||
self.task = task
|
self.task = task
|
||||||
|
|
||||||
|
|
||||||
algorithm_factory = providers.Factory(
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
algorithm_factory = providers.Factory(
|
||||||
Algorithm,
|
Algorithm,
|
||||||
task=providers.Factory(
|
task=providers.Factory(
|
||||||
ClassificationTask,
|
ClassificationTask,
|
||||||
|
@ -34,15 +36,18 @@ algorithm_factory = providers.Factory(
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
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
|
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
|
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."""
|
"""`Factory` specialization with limitation to provided type example."""
|
||||||
|
|
||||||
from dependency_injector import providers, errors
|
from dependency_injector import containers, providers, errors
|
||||||
|
|
||||||
|
|
||||||
class BaseService:
|
class BaseService:
|
||||||
|
@ -17,10 +17,14 @@ class ServiceProvider(providers.Factory):
|
||||||
|
|
||||||
|
|
||||||
# Creating service provider with a correct provided type:
|
# 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:
|
# Trying to create service provider an incorrect provided type:
|
||||||
try:
|
try:
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
some_service_provider = ServiceProvider(object)
|
some_service_provider = ServiceProvider(object)
|
||||||
except errors.Error as exception:
|
except errors.Error as exception:
|
||||||
print(exception)
|
print(exception)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import dataclasses
|
import dataclasses
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
|
@ -16,23 +16,27 @@ class Dispatcher:
|
||||||
modules: List[Module]
|
modules: List[Module]
|
||||||
|
|
||||||
|
|
||||||
dispatcher_factory = providers.Factory(
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
dispatcher_factory = providers.Factory(
|
||||||
Dispatcher,
|
Dispatcher,
|
||||||
modules=providers.List(
|
modules=providers.List(
|
||||||
providers.Factory(Module, name='m1'),
|
providers.Factory(Module, name='m1'),
|
||||||
providers.Factory(Module, name='m2'),
|
providers.Factory(Module, name='m2'),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
dispatcher = dispatcher_factory()
|
container = Container()
|
||||||
|
|
||||||
|
dispatcher = container.dispatcher_factory()
|
||||||
|
|
||||||
assert isinstance(dispatcher.modules, list)
|
assert isinstance(dispatcher.modules, list)
|
||||||
assert dispatcher.modules[0].name == 'm1'
|
assert dispatcher.modules[0].name == 'm1'
|
||||||
assert dispatcher.modules[1].name == 'm2'
|
assert dispatcher.modules[1].name == 'm2'
|
||||||
|
|
||||||
# Call "dispatcher = dispatcher_factory()" is an equivalent for:
|
# Call "dispatcher = container.dispatcher_factory()" is equivalent to:
|
||||||
# dispatcher = Dispatcher(
|
# dispatcher = Dispatcher(
|
||||||
# modules=[
|
# modules=[
|
||||||
# Module(name='m1'),
|
# Module(name='m1'),
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
"""`Object` provider example."""
|
"""`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__':
|
if __name__ == '__main__':
|
||||||
assert object_provider() == 1
|
container = Container()
|
||||||
|
|
||||||
|
assert container.object_provider() == 1
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
"""Simple providers overriding example."""
|
"""Simple providers overriding example."""
|
||||||
|
|
||||||
|
import dataclasses
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class ApiClient:
|
class ApiClient:
|
||||||
|
@ -13,30 +14,35 @@ class ApiClientStub(ApiClient):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class Service:
|
class Service:
|
||||||
def __init__(self, api_client: ApiClient):
|
api_client: ApiClient
|
||||||
self._api_client = api_client
|
|
||||||
|
|
||||||
|
|
||||||
api_client_factory = providers.Factory(ApiClient)
|
class Container(containers.DeclarativeContainer):
|
||||||
service_factory = providers.Factory(
|
|
||||||
|
api_client_factory = providers.Factory(ApiClient)
|
||||||
|
|
||||||
|
service_factory = providers.Factory(
|
||||||
Service,
|
Service,
|
||||||
api_client=api_client_factory,
|
api_client=api_client_factory,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
# 1. Use .override() to replace the API client with stub
|
# 1. Use .override() to replace the API client with stub
|
||||||
api_client_factory.override(providers.Factory(ApiClientStub))
|
container.api_client_factory.override(providers.Factory(ApiClientStub))
|
||||||
service1 = service_factory()
|
service1 = container.service_factory()
|
||||||
assert isinstance(service1.api_client, ApiClientStub)
|
assert isinstance(service1.api_client, ApiClientStub)
|
||||||
|
|
||||||
# 2. Use .override() as a context manager to mock the API client in testing
|
# 2. Use .override() as a context manager to mock the API client in testing
|
||||||
with api_client_factory.override(unittest.mock.Mock(ApiClient)):
|
with container.api_client_factory.override(unittest.mock.Mock(ApiClient)):
|
||||||
service3 = service_factory()
|
service2 = container.service_factory()
|
||||||
assert isinstance(service3.api_client, unittest.mock.Mock)
|
assert isinstance(service2.api_client, unittest.mock.Mock)
|
||||||
|
|
||||||
# 3. Use .reset_override() to get back to normal
|
# 3. Use .reset_override() to get back to normal
|
||||||
api_client_factory.reset_override()
|
container.api_client_factory.reset_override()
|
||||||
service3 = service_factory()
|
service3 = container.service_factory()
|
||||||
assert isinstance(service3.api_client, ApiClient)
|
assert isinstance(service3.api_client, ApiClient)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Example of the injecting of provided instance attributes and items."""
|
"""Example of the injecting of provided instance attributes and items."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
|
@ -23,17 +23,21 @@ class Client:
|
||||||
self.value4 = value4
|
self.value4 = value4
|
||||||
|
|
||||||
|
|
||||||
service = providers.Singleton(Service)
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
client_factory = providers.Factory(
|
service = providers.Singleton(Service)
|
||||||
|
|
||||||
|
client_factory = providers.Factory(
|
||||||
Client,
|
Client,
|
||||||
value1=service.provided[0],
|
value1=service.provided[0],
|
||||||
value2=service.provided.value,
|
value2=service.provided.value,
|
||||||
value3=service.provided.values[0],
|
value3=service.provided.values[0],
|
||||||
value4=service.provided.get_value.call(),
|
value4=service.provided.get_value.call(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
client = client_factory()
|
container = Container()
|
||||||
|
|
||||||
|
client = container.client_factory()
|
||||||
assert client.value1 == client.value2 == client.value3 == 'foo'
|
assert client.value1 == client.value2 == client.value3 == 'foo'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Complex example of the injecting of provided instance attributes and items."""
|
"""Complex example of the injecting of provided instance attributes and items."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
|
@ -12,31 +12,35 @@ class Service:
|
||||||
return self.value
|
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': {
|
'foo': {
|
||||||
'bar': 10,
|
'bar': 10,
|
||||||
'baz': lambda arg: {'arg': arg}
|
'baz': lambda arg: {'arg': arg}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
demo_list = providers.List(
|
demo_list = providers.List(
|
||||||
dependency.provided['foo']['bar'],
|
dependency.provided['foo']['bar'],
|
||||||
dependency.provided['foo']['baz'].call(22)['arg'],
|
dependency.provided['foo']['baz'].call(22)['arg'],
|
||||||
dependency.provided['foo']['baz'].call(service)['arg'],
|
dependency.provided['foo']['baz'].call(service)['arg'],
|
||||||
dependency.provided['foo']['baz'].call(service)['arg'].value,
|
dependency.provided['foo']['baz'].call(service)['arg'].value,
|
||||||
dependency.provided['foo']['baz'].call(service)['arg'].get_value.call(),
|
dependency.provided['foo']['baz'].call(service)['arg'].get_value.call(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
assert demo_list() == [
|
container = Container()
|
||||||
|
|
||||||
|
assert container.demo_list() == [
|
||||||
10,
|
10,
|
||||||
22,
|
22,
|
||||||
service(),
|
container.service(),
|
||||||
42,
|
42,
|
||||||
42,
|
42,
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""`Selector` provider example."""
|
"""`Selector` provider example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class SomeClass:
|
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,
|
config.one_or_another,
|
||||||
one=providers.Factory(SomeClass),
|
one=providers.Factory(SomeClass),
|
||||||
another=providers.Factory(SomeOtherClass),
|
another=providers.Factory(SomeOtherClass),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
config.override({'one_or_another': 'one'})
|
container = Container()
|
||||||
instance_1 = selector()
|
|
||||||
|
container.config.override({'one_or_another': 'one'})
|
||||||
|
instance_1 = container.selector()
|
||||||
assert isinstance(instance_1, SomeClass)
|
assert isinstance(instance_1, SomeClass)
|
||||||
|
|
||||||
config.override({'one_or_another': 'another'})
|
container.config.override({'one_or_another': 'another'})
|
||||||
instance_2 = selector()
|
instance_2 = container.selector()
|
||||||
assert isinstance(instance_2, SomeOtherClass)
|
assert isinstance(instance_2, SomeOtherClass)
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
"""`Singleton` provider example."""
|
"""`Singleton` provider example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class UserService:
|
class UserService:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
user_service_provider = providers.Singleton(UserService)
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
user_service_provider = providers.Singleton(UserService)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
user_service1 = user_service_provider()
|
container = Container()
|
||||||
user_service2 = user_service_provider()
|
|
||||||
|
user_service1 = container.user_service_provider()
|
||||||
|
user_service2 = container.user_service_provider()
|
||||||
assert user_service1 is user_service2
|
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."""
|
"""`Singleton` provider resetting example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
class UserService:
|
class UserService:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
user_service_provider = providers.Singleton(UserService)
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
user_service_provider = providers.Singleton(UserService)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
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()
|
container.user_service_provider.reset()
|
||||||
assert users_service2 is not user_service1
|
|
||||||
|
user_service2 = container.user_service_provider()
|
||||||
|
assert user_service2 is not user_service1
|
||||||
|
|
|
@ -1,30 +1,35 @@
|
||||||
"""`Singleton` - Flask request scope example."""
|
"""`Singleton` - Flask request scope example."""
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
from flask import Flask
|
from flask import Flask, current_app
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
service_provider = providers.Singleton(Service)
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
service_provider = providers.Singleton(Service)
|
||||||
|
|
||||||
|
|
||||||
def index_view():
|
def index_view():
|
||||||
service_1 = service_provider()
|
service_1 = current_app.container.service_provider()
|
||||||
service_2 = service_provider()
|
service_2 = current_app.container.service_provider()
|
||||||
assert service_1 is service_2
|
assert service_1 is service_2
|
||||||
print(service_1)
|
print(service_1)
|
||||||
return 'Hello World!'
|
return 'Hello World!'
|
||||||
|
|
||||||
|
|
||||||
def teardown_context(request):
|
def teardown_context(request):
|
||||||
service_provider.reset()
|
current_app.container.service_provider.reset()
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
app.container = container
|
||||||
app.add_url_rule('/', 'index', view_func=index_view)
|
app.add_url_rule('/', 'index', view_func=index_view)
|
||||||
app.after_request(teardown_context)
|
app.after_request(teardown_context)
|
||||||
|
|
||||||
|
|
|
@ -3,31 +3,39 @@
|
||||||
import threading
|
import threading
|
||||||
import queue
|
import queue
|
||||||
|
|
||||||
from dependency_injector import providers
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
def put_in_queue(example_object, queue_object):
|
def put_in_queue(example_object, queue_object):
|
||||||
queue_object.put(example_object)
|
queue_object.put(example_object)
|
||||||
|
|
||||||
|
|
||||||
thread_local_object = providers.ThreadLocalSingleton(object)
|
class Container(containers.DeclarativeContainer):
|
||||||
queue_provider = providers.ThreadSafeSingleton(queue.Queue)
|
|
||||||
put_in_queue = providers.Callable(
|
thread_local_object = providers.ThreadLocalSingleton(object)
|
||||||
|
|
||||||
|
queue_provider = providers.ThreadSafeSingleton(queue.Queue)
|
||||||
|
|
||||||
|
put_in_queue = providers.Callable(
|
||||||
put_in_queue,
|
put_in_queue,
|
||||||
example_object=thread_local_object,
|
example_object=thread_local_object,
|
||||||
queue_object=queue_provider,
|
queue_object=queue_provider,
|
||||||
)
|
)
|
||||||
thread_factory = providers.Factory(
|
|
||||||
|
thread_factory = providers.Factory(
|
||||||
threading.Thread,
|
threading.Thread,
|
||||||
target=put_in_queue.provider,
|
target=put_in_queue.provider,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
n = 10
|
||||||
threads = []
|
threads = []
|
||||||
for thread_number in range(10):
|
for thread_number in range(n):
|
||||||
threads.append(
|
threads.append(
|
||||||
thread_factory(name='Thread{0}'.format(thread_number)),
|
container.thread_factory(name='Thread{0}'.format(thread_number)),
|
||||||
)
|
)
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
thread.start()
|
thread.start()
|
||||||
|
@ -35,9 +43,9 @@ if __name__ == '__main__':
|
||||||
thread.join()
|
thread.join()
|
||||||
|
|
||||||
all_objects = set()
|
all_objects = set()
|
||||||
while not queue_provider().empty():
|
while not container.queue_provider().empty():
|
||||||
all_objects.add(queue_provider().get())
|
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
|
# Queue contains same number of objects as number of threads where
|
||||||
# thread-local singleton provider was used.
|
# thread-local singleton provider was used.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Dependency injector top-level package."""
|
"""Dependency injector top-level package."""
|
||||||
|
|
||||||
__version__ = '3.36.0'
|
__version__ = '3.37.0'
|
||||||
"""Version number that follows semantic versioning.
|
"""Version number that follows semantic versioning.
|
||||||
|
|
||||||
:type: str
|
:type: str
|
||||||
|
|
|
@ -283,8 +283,8 @@ class Selector(Provider):
|
||||||
|
|
||||||
|
|
||||||
class ProvidedInstanceFluentInterface:
|
class ProvidedInstanceFluentInterface:
|
||||||
def __getattr__(self, item: str) -> AttributeGetter: ...
|
def __getattr__(self, item: Any) -> AttributeGetter: ...
|
||||||
def __getitem__(self, item: str) -> ItemGetter: ...
|
def __getitem__(self, item: Any) -> ItemGetter: ...
|
||||||
def call(self, *args: Injection, **kwargs: Injection) -> MethodCaller: ...
|
def call(self, *args: Injection, **kwargs: Injection) -> MethodCaller: ...
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user