mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 09:57:37 +03:00 
			
		
		
		
	Providers docs update (#289)
* Update callable provider docs * Update coroutine provider docs * Edit object docs * Edit list provider docs * Edit configuration provider docs * Edit selector provider docs * Fix mypy stub of the ``DeclarativeContainer`` to specify the ``__init__`` interface * Edit Dependency provider docs
This commit is contained in:
		
							parent
							
								
									995b2165df
								
							
						
					
					
						commit
						c4b33749d2
					
				
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 32 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 42 KiB  | 
| 
						 | 
					@ -9,8 +9,9 @@ follows `Semantic versioning`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Development version
 | 
					Development version
 | 
				
			||||||
-------------------
 | 
					-------------------
 | 
				
			||||||
- Update ``Singleton`` provider documentation.
 | 
					- Update documentation and rework examples for: ``Singleton``, ``Callable``, ``Coroutine``,
 | 
				
			||||||
- Rework ``Singleton`` provider examples.
 | 
					  ``Object``, ``List``, ``Configuration``, ``Selector``, and ``Dependency`` providers.
 | 
				
			||||||
 | 
					- Fix mypy stub of the ``DeclarativeContainer`` to specify the ``__init__`` interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3.34.0
 | 
					3.34.0
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,69 +1,20 @@
 | 
				
			||||||
Callable providers
 | 
					Callable provider
 | 
				
			||||||
------------------
 | 
					-----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. meta::
 | 
				
			||||||
 | 
					   :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Function,Method,Example
 | 
				
			||||||
 | 
					   :description: Callable provider helps to make dependencies injection into functions. This page
 | 
				
			||||||
 | 
					                 demonstrates how to use a Callable provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Callable` provider calls wrapped callable on every call.
 | 
					:py:class:`Callable` provider calls a function, a method or another callable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Callable providers and injections
 | 
					.. literalinclude:: ../../examples/providers/callable.py
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`Callable` provider takes a various number of positional and keyword 
 | 
					 | 
				
			||||||
arguments that are used as wrapped callable injections. Every time, when 
 | 
					 | 
				
			||||||
:py:class:`Callable` provider is called, positional and keyword argument 
 | 
					 | 
				
			||||||
injections would be passed as callable arguments.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Injections are done according to the next rules:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
+ All providers (instances of :py:class:`Provider`) are called every time 
 | 
					 | 
				
			||||||
  when injection needs to be done.
 | 
					 | 
				
			||||||
+ Providers could be injected "as is" (delegated), if it is defined obviously.
 | 
					 | 
				
			||||||
  Check out :ref:`callable_providers_delegation`.
 | 
					 | 
				
			||||||
+ All other injectable values are provided *"as is"*.
 | 
					 | 
				
			||||||
+ Positional context arguments will be appended after :py:class:`Callable` 
 | 
					 | 
				
			||||||
  positional injections.
 | 
					 | 
				
			||||||
+ Keyword context arguments have priority on :py:class:`Callable` keyword 
 | 
					 | 
				
			||||||
  injections and will be merged over them.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Example that shows usage of :py:class:`Callable` with positional argument 
 | 
					 | 
				
			||||||
injections:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. literalinclude:: ../../examples/providers/callable_args.py
 | 
					 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
 | 
					   :lines: 3-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Next one example shows usage of :py:class:`Callable` with keyword argument 
 | 
					``Callable`` provider handles an injection of the dependencies the same way like a
 | 
				
			||||||
injections:
 | 
					:ref:`factory-provider`.
 | 
				
			||||||
 | 
					 | 
				
			||||||
.. image:: /images/providers/callable.png
 | 
					 | 
				
			||||||
    :width: 100%
 | 
					 | 
				
			||||||
    :align: center
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. literalinclude:: ../../examples/providers/callable_kwargs.py
 | 
					 | 
				
			||||||
   :language: python
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. _callable_providers_delegation:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Callable providers delegation
 | 
					 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`Callable` provider could be delegated to any other provider via 
 | 
					 | 
				
			||||||
any kind of injection. 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Delegation of :py:class:`Callable` providers is the same as 
 | 
					 | 
				
			||||||
:py:class:`Factory` providers delegation, please follow 
 | 
					 | 
				
			||||||
:ref:`factory_providers_delegation` section for examples (with exception 
 | 
					 | 
				
			||||||
of using :py:class:`DelegatedCallable` instead of
 | 
					 | 
				
			||||||
:py:class:`DelegatedFactory`).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Abstract callable providers
 | 
					 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`AbstractCallable` provider is a :py:class:`Callable` provider that
 | 
					 | 
				
			||||||
must be explicitly overridden before calling.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Behaviour of :py:class:`AbstractCallable` providers is the same as of
 | 
					 | 
				
			||||||
:py:class:`AbstractFactory`, please follow :ref:`abstract_factory_providers`
 | 
					 | 
				
			||||||
section for examples (with exception of using :py:class:`AbstractCallable`
 | 
					 | 
				
			||||||
provider instead of :py:class:`AbstractFactory`).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. disqus::
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,12 @@
 | 
				
			||||||
Configuration providers
 | 
					Configuration provider
 | 
				
			||||||
-----------------------
 | 
					----------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. meta::
 | 
				
			||||||
 | 
					   :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Configuration,Injection,
 | 
				
			||||||
 | 
					              Option,Ini,Json,Yaml,Dict,Environment Variable,Load,Read,Get
 | 
				
			||||||
 | 
					   :description: Configuration provides configuration options to the other providers. This page
 | 
				
			||||||
 | 
					                 demonstrates how to use Configuration provider to inject the dependencies, load
 | 
				
			||||||
 | 
					                 a configuration from an ini or yaml file, dictionary or an environment variable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,13 +17,13 @@ Configuration providers
 | 
				
			||||||
   :emphasize-lines: 4,9-10
 | 
					   :emphasize-lines: 4,9-10
 | 
				
			||||||
   :lines: 4-14
 | 
					   :lines: 4-14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It implements "use first, define later" principle.
 | 
					It implements the principle "use first, define later".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Loading from ``ini`` file
 | 
					Loading from an INI file
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Configuration` provider can load configuration from ``ini`` file using
 | 
					``Configuration`` provider can load configuration from an ``ini`` file using the
 | 
				
			||||||
:py:meth:`Configuration.from_ini`:
 | 
					:py:meth:`Configuration.from_ini` method:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_ini.py
 | 
					.. literalinclude:: ../../examples/providers/configuration/configuration_ini.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
| 
						 | 
					@ -28,15 +35,15 @@ where ``examples/providers/configuration/config.ini`` is:
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/config.ini
 | 
					.. literalinclude:: ../../examples/providers/configuration/config.ini
 | 
				
			||||||
   :language: ini
 | 
					   :language: ini
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:meth:`Configuration.from_ini` supports environment variables interpolation. Use
 | 
					:py:meth:`Configuration.from_ini` method supports environment variables interpolation. Use
 | 
				
			||||||
``${ENV_NAME}`` format in the configuration file to substitute value of environment
 | 
					``${ENV_NAME}`` format in the configuration file to substitute value of the environment
 | 
				
			||||||
variable ``ENV_NAME``.
 | 
					variable ``ENV_NAME``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Loading from ``yaml`` file
 | 
					Loading from a YAML file
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Configuration` provider can load configuration from ``yaml`` file using
 | 
					``Configuration`` provider can load configuration from a ``yaml`` file using the
 | 
				
			||||||
:py:meth:`Configuration.from_yaml`:
 | 
					:py:meth:`Configuration.from_yaml` method:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_yaml.py
 | 
					.. literalinclude:: ../../examples/providers/configuration/configuration_yaml.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
| 
						 | 
					@ -48,43 +55,51 @@ where ``examples/providers/configuration/config.yml`` is:
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/config.yml
 | 
					.. literalinclude:: ../../examples/providers/configuration/config.yml
 | 
				
			||||||
   :language: ini
 | 
					   :language: ini
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:meth:`Configuration.from_yaml` supports environment variables interpolation. Use
 | 
					:py:meth:`Configuration.from_yaml` method supports environment variables interpolation. Use
 | 
				
			||||||
``${ENV_NAME}`` format in the configuration file to substitute value of environment
 | 
					``${ENV_NAME}`` format in the configuration file to substitute value of the environment
 | 
				
			||||||
variable ``ENV_NAME``.
 | 
					variable ``ENV_NAME``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. note::
 | 
					.. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Loading configuration from yaml requires ``PyYAML`` package. You can install
 | 
					   Loading of a yaml configuration requires ``PyYAML`` package.
 | 
				
			||||||
    `Dependency Injector` with extras ``pip install dependency-injector[yaml]`` or install
 | 
					 | 
				
			||||||
    ``PyYAML`` separately  ``pip install pyyaml``.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Loading from ``dict``
 | 
					   You can install the ``Dependency Injector`` with an extra dependency::
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Configuration` provider can load configuration from Python ``dict`` using
 | 
					      pip install dependency-injector[yaml]
 | 
				
			||||||
:py:meth:`Configuration.from_dict`:
 | 
					
 | 
				
			||||||
 | 
					   or install ``PyYAML`` directly::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pip install pyyaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   *Don't forget to mirror the changes in the requirements file.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Loading from a dictionary
 | 
				
			||||||
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``Configuration`` provider can load configuration from a Python ``dict`` using the
 | 
				
			||||||
 | 
					:py:meth:`Configuration.from_dict` method:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_dict.py
 | 
					.. literalinclude:: ../../examples/providers/configuration/configuration_dict.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
   :lines: 3-5,6-
 | 
					   :lines: 3-5,6-
 | 
				
			||||||
   :emphasize-lines: 6-13
 | 
					   :emphasize-lines: 6-13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Loading from environment variable
 | 
					Loading from an environment variable
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Configuration` provider can load configuration from environment variable using
 | 
					``Configuration`` provider can load configuration from an environment variable using the
 | 
				
			||||||
:py:meth:`Configuration.from_env`:
 | 
					:py:meth:`Configuration.from_env` method:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_env.py
 | 
					.. literalinclude:: ../../examples/providers/configuration/configuration_env.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
   :lines: 5-7,13-21
 | 
					   :lines: 5-7,13-21
 | 
				
			||||||
   :emphasize-lines: 6-8
 | 
					   :emphasize-lines: 6-8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Loading from multiple sources
 | 
					Loading from the multiple sources
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Configuration` provider can load configuration from multiple sources. Loaded
 | 
					``Configuration`` provider can load configuration from the multiple sources. Loaded
 | 
				
			||||||
configuration is merged recursively over existing configuration.
 | 
					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
 | 
				
			||||||
| 
						 | 
					@ -96,12 +111,12 @@ where ``examples/providers/configuration/config.local.yml`` is:
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/config.local.yml
 | 
					.. literalinclude:: ../../examples/providers/configuration/config.local.yml
 | 
				
			||||||
   :language: ini
 | 
					   :language: ini
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Specifying value type
 | 
					Specifying the value type
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can specify the type of the injected configuration value explicitly.
 | 
					You can specify the type of the injected configuration value explicitly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This helps when you read the value from the ini file or the environment variable and need to
 | 
					This helps when you read the value from an ini file or an environment variable and need to
 | 
				
			||||||
convert it into an ``int`` or a ``float``.
 | 
					convert it into an ``int`` or a ``float``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/configuration/configuration_type.py
 | 
					.. literalinclude:: ../../examples/providers/configuration/configuration_type.py
 | 
				
			||||||
| 
						 | 
					@ -109,20 +124,20 @@ convert it into an ``int`` or a ``float``.
 | 
				
			||||||
   :lines: 3-
 | 
					   :lines: 3-
 | 
				
			||||||
   :emphasize-lines: 17
 | 
					   :emphasize-lines: 17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Configuration` provider has next helper methods:
 | 
					``Configuration`` provider has next helper methods:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- ``.as_int()``
 | 
					- ``.as_int()``
 | 
				
			||||||
- ``.as_float()``
 | 
					- ``.as_float()``
 | 
				
			||||||
- ``.as_(callback, *args, **kwargs)``
 | 
					- ``.as_(callback, *args, **kwargs)``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The last method ``.as_(callback, *args, **kwargs)`` helps to implement a other conversions.
 | 
					The last method ``.as_(callback, *args, **kwargs)`` helps to implement other conversions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. 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: 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
With the ``.as_(callback, *args, **kwargs)`` you can specify the 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,72 +1,27 @@
 | 
				
			||||||
Coroutine providers
 | 
					Coroutine provider
 | 
				
			||||||
-------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. meta::
 | 
				
			||||||
 | 
					   :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Coroutine,Asynchronous,
 | 
				
			||||||
 | 
					              Asyncio,Example
 | 
				
			||||||
 | 
					   :description: Coroutine provider creates a coroutine. This page demonstrates how to use a
 | 
				
			||||||
 | 
					                 Coroutine provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Coroutine` provider create wrapped coroutine on every call.
 | 
					:py:class:`Coroutine` provider creates a coroutine.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Coroutine` provider is designed for making better integration with
 | 
					.. literalinclude:: ../../examples/providers/coroutine.py
 | 
				
			||||||
``asyncio`` coroutines. In particular, :py:class:`Coroutine` provider returns
 | 
					 | 
				
			||||||
``True`` for ``asyncio.iscoroutinefunction()`` checks.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. note::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    :py:class:`Coroutine` provider works only for Python 3.4+.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Example of usage :py:class:`Coroutine` provider with ``async / await``-based
 | 
					 | 
				
			||||||
coroutine:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. literalinclude:: ../../examples/providers/coroutine_async_await.py
 | 
					 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
 | 
					   :lines: 3-
 | 
				
			||||||
Coroutine providers and injections
 | 
					 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`Coroutine` provider takes a various number of positional and keyword
 | 
					 | 
				
			||||||
arguments that are used as wrapped coroutine injections. Every time, when
 | 
					 | 
				
			||||||
:py:class:`Coroutine` provider is called, positional and keyword argument
 | 
					 | 
				
			||||||
injections would be passed as coroutine arguments.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Injections are done according to the next rules:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
+ All providers (instances of :py:class:`Provider`) are called every time 
 | 
					 | 
				
			||||||
  when injection needs to be done.
 | 
					 | 
				
			||||||
+ Providers could be injected "as is" (delegated), if it is defined obviously.
 | 
					 | 
				
			||||||
  Check out :ref:`coroutine_providers_delegation`.
 | 
					 | 
				
			||||||
+ All other injectable values are provided *"as is"*.
 | 
					 | 
				
			||||||
+ Positional context arguments will be appended after :py:class:`Coroutine`
 | 
					 | 
				
			||||||
  positional injections.
 | 
					 | 
				
			||||||
+ Keyword context arguments have priority on :py:class:`Coroutine` keyword
 | 
					 | 
				
			||||||
  injections and will be merged over them.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. note::
 | 
					.. note::
 | 
				
			||||||
 | 
					   The example works on Python 3.7+. For earlier versions use ``loop.run_until_complete()``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Examples of making injections could be found in API docs -
 | 
					``Coroutine`` provider handles an injection of the dependencies the same way like a
 | 
				
			||||||
    :py:class:`Coroutine`.
 | 
					:ref:`factory-provider`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. _coroutine_providers_delegation:
 | 
					.. note::
 | 
				
			||||||
 | 
					   ``Coroutine`` provider returns ``True`` for ``asyncio.iscoroutinefunction()`` check.
 | 
				
			||||||
Coroutine providers delegation
 | 
					 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`Coroutine` provider could be delegated to any other provider via
 | 
					 | 
				
			||||||
any kind of injection. 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Delegation of :py:class:`Coroutine` providers is the same as
 | 
					 | 
				
			||||||
:py:class:`Factory` providers delegation, please follow 
 | 
					 | 
				
			||||||
:ref:`factory_providers_delegation` section for examples (with exception 
 | 
					 | 
				
			||||||
of using :py:class:`DelegatedCoroutine` instead of
 | 
					 | 
				
			||||||
:py:class:`DelegatedFactory`).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Abstract coroutine providers
 | 
					 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`AbstractCoroutine` provider is a :py:class:`Coroutine` provider that
 | 
					 | 
				
			||||||
must be explicitly overridden before calling.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Behaviour of :py:class:`AbstractCoroutine` providers is the same as of
 | 
					 | 
				
			||||||
:py:class:`AbstractFactory`, please follow :ref:`abstract_factory_providers`
 | 
					 | 
				
			||||||
section for examples (with exception of using :py:class:`AbstractCoroutine`
 | 
					 | 
				
			||||||
provider instead of :py:class:`AbstractFactory`).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. disqus::
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,43 +1,21 @@
 | 
				
			||||||
Dependency providers
 | 
					Dependency provider
 | 
				
			||||||
--------------------
 | 
					-------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Dependency` provider can be useful for development of
 | 
					:py:class:`Dependency` provider is a placeholder for the dependency of the specified type.
 | 
				
			||||||
self-sufficient libraries / modules / applications that have required external
 | 
					 | 
				
			||||||
dependencies.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
For example, you have created self-sufficient library / module / application,
 | 
					The first argument of the ``Dependency`` provider specifies a type of the dependency. It is
 | 
				
			||||||
that has dependency on *database connection*.
 | 
					called ``instance_of``. ``Dependency`` provider controls the type of the returned object to be an
 | 
				
			||||||
 | 
					instance of the ``instance_of`` type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Second step you want to do is to make this software component to be easy
 | 
					The ``Dependency`` provider must be overridden before usage. It can be overridden by any type of
 | 
				
			||||||
reusable by wide amount of developers and to be easily integrated into many
 | 
					the provider. The only rule is that overriding provider must return an instance of ``instance_of``
 | 
				
			||||||
applications.
 | 
					dependency type.
 | 
				
			||||||
 | 
					 | 
				
			||||||
It may be good idea, to move all external dependencies (like
 | 
					 | 
				
			||||||
*database connection*) to the top level and make them to be injected on your
 | 
					 | 
				
			||||||
software component's initialization. It will make third party developers feel
 | 
					 | 
				
			||||||
themselves free about integration of your component in their applications,
 | 
					 | 
				
			||||||
because they would be able to find right place / right way for doing this
 | 
					 | 
				
			||||||
in their application's architectures.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
At the same time, you can be sure, that your external dependency will be
 | 
					 | 
				
			||||||
satisfied with appropriate instance.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Example:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. note::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Class ``UsersService`` is a part of some library. ``UsersService`` has
 | 
					 | 
				
			||||||
    dependency on database connection, which can be satisfied with any
 | 
					 | 
				
			||||||
    DBAPI 2.0 database connection. Being a self-sufficient library,
 | 
					 | 
				
			||||||
    ``UsersService`` doesn't hardcode any kind of database management logic.
 | 
					 | 
				
			||||||
    Instead of this, ``UsersService`` has external dependency, that has to
 | 
					 | 
				
			||||||
    be satisfied by client's code, out of library's scope.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. image:: /images/providers/dependency.png
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/dependency.py
 | 
					.. literalinclude:: ../../examples/providers/dependency.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
 | 
					   :lines: 3-
 | 
				
			||||||
 | 
					   :emphasize-lines: 26
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. disqus::
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,10 @@
 | 
				
			||||||
List providers
 | 
					List provider
 | 
				
			||||||
--------------
 | 
					-------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. meta::
 | 
				
			||||||
 | 
					   :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,List,Injection
 | 
				
			||||||
 | 
					   :description: List provider helps to inject a list of the dependencies. This page demonstrates
 | 
				
			||||||
 | 
					                 how to use a List provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,28 +12,12 @@ List providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/list.py
 | 
					.. literalinclude:: ../../examples/providers/list.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
   :emphasize-lines: 6-9
 | 
					 | 
				
			||||||
   :lines: 6-8, 23-29
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`List` provider is needed for injecting a list of dependencies. It handles
 | 
					 | 
				
			||||||
positional argument injections the same way as :py:class:`Factory` provider:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
+ All providers (instances of :py:class:`Provider`) are called every time
 | 
					 | 
				
			||||||
  when injection needs to be done.
 | 
					 | 
				
			||||||
+ Providers could be injected "as is" (delegated), if it is defined explicitly. Check out
 | 
					 | 
				
			||||||
  :ref:`factory_providers_delegation`.
 | 
					 | 
				
			||||||
+ All other values are injected *"as is"*.
 | 
					 | 
				
			||||||
+ Positional context arguments will be appended after :py:class:`List` positional injections.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Full example:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. literalinclude:: ../../examples/providers/list.py
 | 
					 | 
				
			||||||
   :language: python
 | 
					 | 
				
			||||||
   :emphasize-lines: 23-26
 | 
					 | 
				
			||||||
   :lines: 3-
 | 
					   :lines: 3-
 | 
				
			||||||
 | 
					   :emphasize-lines: 19-22
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``List`` provider handles positional arguments the same way as a :ref:`factory-provider`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. note::
 | 
					.. note::
 | 
				
			||||||
 | 
					    Keyword argument are not supported.
 | 
				
			||||||
    Keyword argument injections are not supported.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. disqus::
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,17 @@
 | 
				
			||||||
Object providers
 | 
					Object provider
 | 
				
			||||||
----------------
 | 
					---------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. meta::
 | 
				
			||||||
 | 
					   :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Object
 | 
				
			||||||
 | 
					   :description: Object provider provides an object "as is". This page demonstrates how to use an
 | 
				
			||||||
 | 
					                 Object provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Object` provider returns provided instance "as is".
 | 
					:py:class:`Object` provider returns an object "as is".
 | 
				
			||||||
 | 
					 | 
				
			||||||
Example:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/object.py
 | 
					.. literalinclude:: ../../examples/providers/object.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
 | 
					   :lines: 3-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. disqus::
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,29 +3,31 @@
 | 
				
			||||||
Selector providers
 | 
					Selector providers
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. meta::
 | 
				
			||||||
 | 
					   :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Configuration,Injection,
 | 
				
			||||||
 | 
					              Selector,Polymorphism,Environment Variable,Flexibility
 | 
				
			||||||
 | 
					   :description: Selector selects provider based on a configuration value or another callable.
 | 
				
			||||||
 | 
					                 This page demonstrates how to implement the polymorphism and increase the
 | 
				
			||||||
 | 
					                 flexibility of your application using the Selector provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Selector` provider selects provider based on the configuration value or other callable.
 | 
					:py:class:`Selector` provider selects provider based on a configuration value or another callable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/selector.py
 | 
					.. literalinclude:: ../../examples/providers/selector.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
   :emphasize-lines: 6-10
 | 
					 | 
				
			||||||
   :lines: 3-5,14-20
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:py:class:`Selector` provider has a callable called ``selector`` and a dictionary of providers.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The ``selector`` callable is provided as a first positional argument. It can be
 | 
					 | 
				
			||||||
:py:class:`Configuration` provider or any other callable. It has to return a string value.
 | 
					 | 
				
			||||||
This value is used as a key for selecting the provider from the dictionary of providers.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The providers are provided as keyword arguments. Argument name is used as a key for
 | 
					 | 
				
			||||||
selecting the provider.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Full example:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. literalinclude:: ../../examples/providers/selector.py
 | 
					 | 
				
			||||||
   :language: python
 | 
					 | 
				
			||||||
   :emphasize-lines: 14-18
 | 
					 | 
				
			||||||
   :lines: 3-
 | 
					   :lines: 3-
 | 
				
			||||||
 | 
					   :emphasize-lines: 14-18
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					string value. This value is used as a key for selecting the provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The providers are provided as keyword arguments. Argument name is used as a key for selecting the
 | 
				
			||||||
 | 
					provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When a ``Selector`` provider is called, it gets a ``selector`` value and delegates the work to
 | 
				
			||||||
 | 
					the provider with a matching name. The ``selector`` callable works as a switch: when the returned
 | 
				
			||||||
 | 
					value is changed the ``Selector`` provider will delegate the work to another provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. disqus::
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								examples/providers/callable.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								examples/providers/callable.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					"""`Callable` provider example."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import passlib.hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from dependency_injector import providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					password_hasher = providers.Callable(
 | 
				
			||||||
 | 
					    passlib.hash.sha256_crypt.hash,
 | 
				
			||||||
 | 
					    salt_size=16,
 | 
				
			||||||
 | 
					    rounds=10000,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
| 
						 | 
					@ -1,16 +0,0 @@
 | 
				
			||||||
"""`Callable` providers with positional arguments example."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dependency_injector.providers as providers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Creating even and odd filter providers:
 | 
					 | 
				
			||||||
even_filter = providers.Callable(filter, lambda x: x % 2 == 0)
 | 
					 | 
				
			||||||
odd_filter = providers.Callable(filter, lambda x: x % 2 != 0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Creating even and odd ranges using range() and filter providers:
 | 
					 | 
				
			||||||
even_range = even_filter(range(1, 10))
 | 
					 | 
				
			||||||
odd_range = odd_filter(range(1, 10))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Making some asserts:
 | 
					 | 
				
			||||||
assert even_range == [2, 4, 6, 8]
 | 
					 | 
				
			||||||
assert odd_range == [1, 3, 5, 7, 9]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,16 +0,0 @@
 | 
				
			||||||
"""`Callable` providers with keyword arguments example."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import passlib.hash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dependency_injector.providers as providers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Password hasher and verifier providers:
 | 
					 | 
				
			||||||
password_hasher = providers.Callable(passlib.hash.sha256_crypt.encrypt,
 | 
					 | 
				
			||||||
                                     salt_size=16,
 | 
					 | 
				
			||||||
                                     rounds=10000)
 | 
					 | 
				
			||||||
password_verifier = providers.Callable(passlib.hash.sha256_crypt.verify)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Making some asserts:
 | 
					 | 
				
			||||||
hashed_password = password_hasher('super secret')
 | 
					 | 
				
			||||||
assert password_verifier('super secret', hashed_password)
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,26 +1,19 @@
 | 
				
			||||||
"""`Coroutine` providers example with @asyncio.coroutine decorator.
 | 
					"""`Coroutine` providers example with async / await syntax."""
 | 
				
			||||||
 | 
					 | 
				
			||||||
Current example works only fot Python 3.4+.
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import asyncio
 | 
					import asyncio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dependency_injector.providers as providers
 | 
					from dependency_injector import providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@asyncio.coroutine
 | 
					async def coroutine(arg1, arg2):
 | 
				
			||||||
def coroutine_function(arg1, arg2):
 | 
					    await asyncio.sleep(0.1)
 | 
				
			||||||
    """Sample coroutine function."""
 | 
					 | 
				
			||||||
    yield from asyncio.sleep(0.1)
 | 
					 | 
				
			||||||
    return arg1, arg2
 | 
					    return arg1, arg2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
coroutine_provider = providers.Coroutine(coroutine_function, arg1=1, arg2=2)
 | 
					coroutine_provider = providers.Coroutine(coroutine, arg1=1, arg2=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    loop = asyncio.get_event_loop()
 | 
					    arg1, arg2 = asyncio.run(coroutine_provider())
 | 
				
			||||||
    arg1, arg2 = loop.run_until_complete(coroutine_provider())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert (arg1, arg2) == (1, 2)
 | 
					    assert (arg1, arg2) == (1, 2)
 | 
				
			||||||
    assert asyncio.iscoroutinefunction(coroutine_provider)
 | 
					    assert asyncio.iscoroutinefunction(coroutine_provider)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +0,0 @@
 | 
				
			||||||
"""`Coroutine` providers example with async / await syntax.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Current example works only fot Python 3.5+.
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import asyncio
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dependency_injector.providers as providers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def coroutine_function(arg1, arg2):
 | 
					 | 
				
			||||||
    """Sample coroutine function."""
 | 
					 | 
				
			||||||
    await asyncio.sleep(0.1)
 | 
					 | 
				
			||||||
    return arg1, arg2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
coroutine_provider = providers.Coroutine(coroutine_function, arg1=1, arg2=2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == '__main__':
 | 
					 | 
				
			||||||
    loop = asyncio.get_event_loop()
 | 
					 | 
				
			||||||
    arg1, arg2 = loop.run_until_complete(coroutine_provider())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert (arg1, arg2) == (1, 2)
 | 
					 | 
				
			||||||
    assert asyncio.iscoroutinefunction(coroutine_provider)
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,73 +1,50 @@
 | 
				
			||||||
"""`Dependency` providers example."""
 | 
					"""`Dependency` provider example."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sqlite3
 | 
					import abc
 | 
				
			||||||
import contextlib
 | 
					import dataclasses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dependency_injector.providers as providers
 | 
					from dependency_injector import containers, providers, errors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UsersService:
 | 
					class DbAdapter(metaclass=abc.ABCMeta):
 | 
				
			||||||
    """Example class UsersService.
 | 
					    ...
 | 
				
			||||||
 | 
					 | 
				
			||||||
    UsersService has dependency on DBAPI 2.0 database connection.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, database):
 | 
					 | 
				
			||||||
        """Initialize instance.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :param database: Database connection.
 | 
					 | 
				
			||||||
        :type database: sqlite3.dbapi2.Connection
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        self.database = database
 | 
					 | 
				
			||||||
        self.database.row_factory = sqlite3.dbapi2.Row
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def init_database(self):
 | 
					 | 
				
			||||||
        """Initialize database, if it has not been initialized yet."""
 | 
					 | 
				
			||||||
        with contextlib.closing(self.database.cursor()) as cursor:
 | 
					 | 
				
			||||||
            cursor.execute("""
 | 
					 | 
				
			||||||
              CREATE TABLE IF NOT EXISTS users(
 | 
					 | 
				
			||||||
                id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
					 | 
				
			||||||
                name VARCHAR(32)
 | 
					 | 
				
			||||||
              )
 | 
					 | 
				
			||||||
            """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def create(self, name):
 | 
					 | 
				
			||||||
        """Create user with provided name and return his id."""
 | 
					 | 
				
			||||||
        with contextlib.closing(self.database.cursor()) as cursor:
 | 
					 | 
				
			||||||
            cursor.execute('INSERT INTO users(name) VALUES (?)', (name,))
 | 
					 | 
				
			||||||
            return cursor.lastrowid
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_by_id(self, id):
 | 
					 | 
				
			||||||
        """Return user info by user id."""
 | 
					 | 
				
			||||||
        with contextlib.closing(self.database.cursor()) as cursor:
 | 
					 | 
				
			||||||
            cursor.execute('SELECT id, name FROM users WHERE id=?', (id,))
 | 
					 | 
				
			||||||
            return cursor.fetchone()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Database and UsersService providers:
 | 
					class SqliteDbAdapter(DbAdapter):
 | 
				
			||||||
database = providers.Dependency(instance_of=sqlite3.dbapi2.Connection)
 | 
					    ...
 | 
				
			||||||
users_service_factory = providers.Factory(UsersService,
 | 
					 | 
				
			||||||
                                          database=database)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Out of library's scope.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Setting database provider:
 | 
					 | 
				
			||||||
database.provided_by(providers.Singleton(sqlite3.dbapi2.Connection,
 | 
					 | 
				
			||||||
                                         database=':memory:',
 | 
					 | 
				
			||||||
                                         timeout=30,
 | 
					 | 
				
			||||||
                                         detect_types=True,
 | 
					 | 
				
			||||||
                                         isolation_level='EXCLUSIVE'))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Creating UsersService instance:
 | 
					class PostgresDbAdapter(DbAdapter):
 | 
				
			||||||
users_service = users_service_factory()
 | 
					    ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Initializing UsersService database:
 | 
					 | 
				
			||||||
users_service.init_database()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Creating test user and retrieving full information about him:
 | 
					@dataclasses.dataclass
 | 
				
			||||||
test_user_id = users_service.create(name='test_user')
 | 
					class UserService:
 | 
				
			||||||
test_user = users_service.get_by_id(test_user_id)
 | 
					    database: DbAdapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Making some asserts:
 | 
					
 | 
				
			||||||
assert test_user['id'] == 1
 | 
					class Container(containers.DeclarativeContainer):
 | 
				
			||||||
assert test_user['name'] == 'test_user'
 | 
					
 | 
				
			||||||
 | 
					    database = providers.Dependency(instance_of=DbAdapter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    user_service = providers.Factory(
 | 
				
			||||||
 | 
					        UserService,
 | 
				
			||||||
 | 
					        database=database,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    container1 = Container(database=providers.Singleton(SqliteDbAdapter))
 | 
				
			||||||
 | 
					    container2 = Container(database=providers.Singleton(PostgresDbAdapter))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert isinstance(container1.user_service().database, SqliteDbAdapter)
 | 
				
			||||||
 | 
					    assert isinstance(container2.user_service().database, PostgresDbAdapter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    container3 = Container(database=providers.Singleton(object))
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        container3.user_service()
 | 
				
			||||||
 | 
					    except errors.Error as exception:
 | 
				
			||||||
 | 
					        print(exception)
 | 
				
			||||||
 | 
					        # The output is:
 | 
				
			||||||
 | 
					        # <object object at 0x107ce5c40> is not an
 | 
				
			||||||
 | 
					        # instance of <class '__main__.DbAdapter'>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,15 +8,11 @@ from dependency_injector import providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@dataclasses.dataclass
 | 
					@dataclasses.dataclass
 | 
				
			||||||
class Module:
 | 
					class Module:
 | 
				
			||||||
    """Example module."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@dataclasses.dataclass
 | 
					@dataclasses.dataclass
 | 
				
			||||||
class Dispatcher:
 | 
					class Dispatcher:
 | 
				
			||||||
    """Example dispatcher."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    modules: List[Module]
 | 
					    modules: List[Module]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +24,7 @@ dispatcher_factory = providers.Factory(
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    dispatcher = dispatcher_factory()
 | 
					    dispatcher = dispatcher_factory()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,11 +32,10 @@ if __name__ == '__main__':
 | 
				
			||||||
    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 of dispatcher_factory() is equivalent to:
 | 
					    # Call "dispatcher = dispatcher_factory()" is an equivalent for:
 | 
				
			||||||
 | 
					    # dispatcher = Dispatcher(
 | 
				
			||||||
    dispatcher = Dispatcher(
 | 
					    #     modules=[
 | 
				
			||||||
        modules=[
 | 
					    #         Module(name='m1'),
 | 
				
			||||||
            Module(name='m1'),
 | 
					    #         Module(name='m2'),
 | 
				
			||||||
            Module(name='m2'),
 | 
					    #     ],
 | 
				
			||||||
        ],
 | 
					    # )
 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
"""Object providers example."""
 | 
					"""`Object` provider example."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dependency_injector.providers as providers
 | 
					from dependency_injector import providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Creating object provider:
 | 
					 | 
				
			||||||
object_provider = providers.Object(1)
 | 
					object_provider = providers.Object(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Making some asserts:
 | 
					
 | 
				
			||||||
assert object_provider() == 1
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    assert object_provider() == 1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,10 +19,11 @@ selector = providers.Selector(
 | 
				
			||||||
    another=providers.Factory(SomeOtherClass),
 | 
					    another=providers.Factory(SomeOtherClass),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config.override({'one_or_another': 'one'})
 | 
					if __name__ == '__main__':
 | 
				
			||||||
instance_1 = selector()
 | 
					    config.override({'one_or_another': 'one'})
 | 
				
			||||||
assert isinstance(instance_1, SomeClass)
 | 
					    instance_1 = selector()
 | 
				
			||||||
 | 
					    assert isinstance(instance_1, SomeClass)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config.override({'one_or_another': 'another'})
 | 
					    config.override({'one_or_another': 'another'})
 | 
				
			||||||
instance_2 = selector()
 | 
					    instance_2 = selector()
 | 
				
			||||||
assert isinstance(instance_2, SomeOtherClass)
 | 
					    assert isinstance(instance_2, SomeOtherClass)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ class DynamicContainer(Container): ...
 | 
				
			||||||
class DeclarativeContainer(Container):
 | 
					class DeclarativeContainer(Container):
 | 
				
			||||||
    cls_providers: ClassVar[Dict[str, Provider]]
 | 
					    cls_providers: ClassVar[Dict[str, Provider]]
 | 
				
			||||||
    inherited_providers: ClassVar[Dict[str, Provider]]
 | 
					    inherited_providers: ClassVar[Dict[str, Provider]]
 | 
				
			||||||
 | 
					    def __init__(self, **overriding_providers: Provider) -> None: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def override(container: Container) -> _Callable[[Container], Container]: ...
 | 
					def override(container: Container) -> _Callable[[Container], Container]: ...
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user