mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-01-30 19:24:31 +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
|
||||
-------------------
|
||||
- Update ``Singleton`` provider documentation.
|
||||
- Rework ``Singleton`` provider examples.
|
||||
- Update documentation and rework examples for: ``Singleton``, ``Callable``, ``Coroutine``,
|
||||
``Object``, ``List``, ``Configuration``, ``Selector``, and ``Dependency`` providers.
|
||||
- Fix mypy stub of the ``DeclarativeContainer`` to specify the ``__init__`` interface.
|
||||
|
||||
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
|
||||
|
||||
: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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
: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
|
||||
.. literalinclude:: ../../examples/providers/callable.py
|
||||
:language: python
|
||||
:lines: 3-
|
||||
|
||||
Next one example shows usage of :py:class:`Callable` with keyword argument
|
||||
injections:
|
||||
|
||||
.. 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`).
|
||||
``Callable`` provider handles an injection of the dependencies the same way like a
|
||||
:ref:`factory-provider`.
|
||||
|
||||
.. 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
|
||||
|
||||
|
@ -10,13 +17,13 @@ Configuration providers
|
|||
:emphasize-lines: 4,9-10
|
||||
: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
|
||||
:py:meth:`Configuration.from_ini`:
|
||||
``Configuration`` provider can load configuration from an ``ini`` file using the
|
||||
:py:meth:`Configuration.from_ini` method:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/configuration/configuration_ini.py
|
||||
:language: python
|
||||
|
@ -28,15 +35,15 @@ where ``examples/providers/configuration/config.ini`` is:
|
|||
.. literalinclude:: ../../examples/providers/configuration/config.ini
|
||||
:language: ini
|
||||
|
||||
:py:meth:`Configuration.from_ini` supports environment variables interpolation. Use
|
||||
``${ENV_NAME}`` format in the configuration file to substitute value of environment
|
||||
:py:meth:`Configuration.from_ini` method supports environment variables interpolation. Use
|
||||
``${ENV_NAME}`` format in the configuration file to substitute value of the environment
|
||||
variable ``ENV_NAME``.
|
||||
|
||||
Loading from ``yaml`` file
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Loading from a YAML file
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:py:class:`Configuration` provider can load configuration from ``yaml`` file using
|
||||
:py:meth:`Configuration.from_yaml`:
|
||||
``Configuration`` provider can load configuration from a ``yaml`` file using the
|
||||
:py:meth:`Configuration.from_yaml` method:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/configuration/configuration_yaml.py
|
||||
:language: python
|
||||
|
@ -48,43 +55,51 @@ where ``examples/providers/configuration/config.yml`` is:
|
|||
.. literalinclude:: ../../examples/providers/configuration/config.yml
|
||||
:language: ini
|
||||
|
||||
:py:meth:`Configuration.from_yaml` supports environment variables interpolation. Use
|
||||
``${ENV_NAME}`` format in the configuration file to substitute value of environment
|
||||
:py:meth:`Configuration.from_yaml` method supports environment variables interpolation. Use
|
||||
``${ENV_NAME}`` format in the configuration file to substitute value of the environment
|
||||
variable ``ENV_NAME``.
|
||||
|
||||
.. note::
|
||||
|
||||
Loading configuration from yaml requires ``PyYAML`` package. You can install
|
||||
`Dependency Injector` with extras ``pip install dependency-injector[yaml]`` or install
|
||||
``PyYAML`` separately ``pip install pyyaml``.
|
||||
Loading of a yaml configuration requires ``PyYAML`` package.
|
||||
|
||||
Loading from ``dict``
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
You can install the ``Dependency Injector`` with an extra dependency::
|
||||
|
||||
:py:class:`Configuration` provider can load configuration from Python ``dict`` using
|
||||
:py:meth:`Configuration.from_dict`:
|
||||
pip install dependency-injector[yaml]
|
||||
|
||||
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
|
||||
:language: python
|
||||
:lines: 3-5,6-
|
||||
:emphasize-lines: 6-13
|
||||
|
||||
Loading from environment variable
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Loading from an environment variable
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:py:class:`Configuration` provider can load configuration from environment variable using
|
||||
:py:meth:`Configuration.from_env`:
|
||||
``Configuration`` provider can load configuration from an environment variable using the
|
||||
:py:meth:`Configuration.from_env` method:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/configuration/configuration_env.py
|
||||
:language: python
|
||||
:lines: 5-7,13-21
|
||||
: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 is merged recursively over existing configuration.
|
||||
``Configuration`` provider can load configuration from the multiple sources. Loaded
|
||||
configuration is merged recursively over the existing configuration.
|
||||
|
||||
.. literalinclude:: ../../examples/providers/configuration/configuration_multiple.py
|
||||
:language: python
|
||||
|
@ -96,12 +111,12 @@ where ``examples/providers/configuration/config.local.yml`` is:
|
|||
.. literalinclude:: ../../examples/providers/configuration/config.local.yml
|
||||
:language: ini
|
||||
|
||||
Specifying value type
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Specifying the value type
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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``.
|
||||
|
||||
.. literalinclude:: ../../examples/providers/configuration/configuration_type.py
|
||||
|
@ -109,20 +124,20 @@ convert it into an ``int`` or a ``float``.
|
|||
:lines: 3-
|
||||
:emphasize-lines: 17
|
||||
|
||||
:py:class:`Configuration` provider has next helper methods:
|
||||
``Configuration`` provider has next helper methods:
|
||||
|
||||
- ``.as_int()``
|
||||
- ``.as_float()``
|
||||
- ``.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
|
||||
:language: python
|
||||
:lines: 3-
|
||||
: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
|
||||
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
|
||||
|
||||
: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
|
||||
``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
|
||||
.. literalinclude:: ../../examples/providers/coroutine.py
|
||||
:language: python
|
||||
|
||||
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.
|
||||
:lines: 3-
|
||||
|
||||
.. 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 -
|
||||
:py:class:`Coroutine`.
|
||||
``Coroutine`` provider handles an injection of the dependencies the same way like a
|
||||
:ref:`factory-provider`.
|
||||
|
||||
.. _coroutine_providers_delegation:
|
||||
|
||||
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`).
|
||||
.. note::
|
||||
``Coroutine`` provider returns ``True`` for ``asyncio.iscoroutinefunction()`` check.
|
||||
|
||||
.. disqus::
|
||||
|
|
|
@ -1,43 +1,21 @@
|
|||
Dependency providers
|
||||
--------------------
|
||||
Dependency provider
|
||||
-------------------
|
||||
|
||||
.. currentmodule:: dependency_injector.providers
|
||||
|
||||
:py:class:`Dependency` provider can be useful for development of
|
||||
self-sufficient libraries / modules / applications that have required external
|
||||
dependencies.
|
||||
:py:class:`Dependency` provider is a placeholder for the dependency of the specified type.
|
||||
|
||||
For example, you have created self-sufficient library / module / application,
|
||||
that has dependency on *database connection*.
|
||||
The first argument of the ``Dependency`` provider specifies a type of the dependency. It is
|
||||
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
|
||||
reusable by wide amount of developers and to be easily integrated into many
|
||||
applications.
|
||||
|
||||
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
|
||||
The ``Dependency`` provider must be overridden before usage. It can be overridden by any type of
|
||||
the provider. The only rule is that overriding provider must return an instance of ``instance_of``
|
||||
dependency type.
|
||||
|
||||
.. literalinclude:: ../../examples/providers/dependency.py
|
||||
:language: python
|
||||
:lines: 3-
|
||||
:emphasize-lines: 26
|
||||
|
||||
.. 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
|
||||
|
||||
|
@ -7,28 +12,12 @@ List providers
|
|||
|
||||
.. literalinclude:: ../../examples/providers/list.py
|
||||
: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-
|
||||
:emphasize-lines: 19-22
|
||||
|
||||
``List`` provider handles positional arguments the same way as a :ref:`factory-provider`.
|
||||
|
||||
.. note::
|
||||
|
||||
Keyword argument injections are not supported.
|
||||
Keyword argument are not supported.
|
||||
|
||||
.. 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
|
||||
|
||||
:py:class:`Object` provider returns provided instance "as is".
|
||||
|
||||
Example:
|
||||
:py:class:`Object` provider returns an object "as is".
|
||||
|
||||
.. literalinclude:: ../../examples/providers/object.py
|
||||
:language: python
|
||||
|
||||
:lines: 3-
|
||||
|
||||
.. disqus::
|
||||
|
|
|
@ -3,29 +3,31 @@
|
|||
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
|
||||
|
||||
: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
|
||||
: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-
|
||||
: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::
|
||||
|
|
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.
|
||||
|
||||
Current example works only fot Python 3.4+.
|
||||
"""
|
||||
"""`Coroutine` providers example with async / await syntax."""
|
||||
|
||||
import asyncio
|
||||
|
||||
import dependency_injector.providers as providers
|
||||
from dependency_injector import providers
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def coroutine_function(arg1, arg2):
|
||||
"""Sample coroutine function."""
|
||||
yield from asyncio.sleep(0.1)
|
||||
async def coroutine(arg1, arg2):
|
||||
await asyncio.sleep(0.1)
|
||||
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__':
|
||||
loop = asyncio.get_event_loop()
|
||||
arg1, arg2 = loop.run_until_complete(coroutine_provider())
|
||||
|
||||
arg1, arg2 = asyncio.run(coroutine_provider())
|
||||
assert (arg1, arg2) == (1, 2)
|
||||
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 contextlib
|
||||
import abc
|
||||
import dataclasses
|
||||
|
||||
import dependency_injector.providers as providers
|
||||
from dependency_injector import containers, providers, errors
|
||||
|
||||
|
||||
class UsersService:
|
||||
"""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()
|
||||
class DbAdapter(metaclass=abc.ABCMeta):
|
||||
...
|
||||
|
||||
|
||||
# Database and UsersService providers:
|
||||
database = providers.Dependency(instance_of=sqlite3.dbapi2.Connection)
|
||||
users_service_factory = providers.Factory(UsersService,
|
||||
database=database)
|
||||
class SqliteDbAdapter(DbAdapter):
|
||||
...
|
||||
|
||||
# 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:
|
||||
users_service = users_service_factory()
|
||||
class PostgresDbAdapter(DbAdapter):
|
||||
...
|
||||
|
||||
# Initializing UsersService database:
|
||||
users_service.init_database()
|
||||
|
||||
# Creating test user and retrieving full information about him:
|
||||
test_user_id = users_service.create(name='test_user')
|
||||
test_user = users_service.get_by_id(test_user_id)
|
||||
@dataclasses.dataclass
|
||||
class UserService:
|
||||
database: DbAdapter
|
||||
|
||||
# Making some asserts:
|
||||
assert test_user['id'] == 1
|
||||
assert test_user['name'] == 'test_user'
|
||||
|
||||
class Container(containers.DeclarativeContainer):
|
||||
|
||||
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
|
||||
class Module:
|
||||
"""Example module."""
|
||||
|
||||
name: str
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Dispatcher:
|
||||
"""Example dispatcher."""
|
||||
|
||||
modules: List[Module]
|
||||
|
||||
|
||||
|
@ -28,6 +24,7 @@ dispatcher_factory = providers.Factory(
|
|||
),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dispatcher = dispatcher_factory()
|
||||
|
||||
|
@ -35,11 +32,10 @@ if __name__ == '__main__':
|
|||
assert dispatcher.modules[0].name == 'm1'
|
||||
assert dispatcher.modules[1].name == 'm2'
|
||||
|
||||
# Call of dispatcher_factory() is equivalent to:
|
||||
|
||||
dispatcher = Dispatcher(
|
||||
modules=[
|
||||
Module(name='m1'),
|
||||
Module(name='m2'),
|
||||
],
|
||||
)
|
||||
# Call "dispatcher = dispatcher_factory()" is an equivalent for:
|
||||
# dispatcher = Dispatcher(
|
||||
# modules=[
|
||||
# Module(name='m1'),
|
||||
# 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)
|
||||
|
||||
# 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),
|
||||
)
|
||||
|
||||
config.override({'one_or_another': 'one'})
|
||||
instance_1 = selector()
|
||||
assert isinstance(instance_1, SomeClass)
|
||||
if __name__ == '__main__':
|
||||
config.override({'one_or_another': 'one'})
|
||||
instance_1 = selector()
|
||||
assert isinstance(instance_1, SomeClass)
|
||||
|
||||
config.override({'one_or_another': 'another'})
|
||||
instance_2 = selector()
|
||||
assert isinstance(instance_2, SomeOtherClass)
|
||||
config.override({'one_or_another': 'another'})
|
||||
instance_2 = selector()
|
||||
assert isinstance(instance_2, SomeOtherClass)
|
||||
|
|
|
@ -24,6 +24,7 @@ class DynamicContainer(Container): ...
|
|||
class DeclarativeContainer(Container):
|
||||
cls_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]: ...
|
||||
|
|
Loading…
Reference in New Issue
Block a user