mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-29 13:04:02 +03:00
feed916f46
* Add support of async injections into wiring * Add support of async functions and async generators for resources * Update resource provider typing stub for stutdown * Add resource base class for async resources * Fix tests * Add tests for async injections in wiring @inject * Refactor provider tests * Add tests for async resources * Rework async resources callbacks to .add_done_callback() style (fixes pypy3 issue) * Add awaits into async resource class test * Refactor FastAPI tests * Implement async resources initialization in container * Move container async resource tests to a separate module for Python 3.6+ * Fix init async resources in container on Python 2 * Add first dirty async injections implementation * Fix isawaitable error * Turm asyncio import to conditional for safer Py2 usage * Refactor kwargs injections * Implement positional injections, add tests and make refactoring * Implement attribute injections and add tests * Add singleton implementation + tests for all singleton types * Implement injections in thread-local and thread-safe singleton providers * Update .provided + fix resource concurent initialization issue * Implement async mode for Dependency provider * Add async mode for the provider * Add overload for Factory typing * Add typing stubs for async resource * Refactor abstract* providers __call__() * Add async mode API + tests * Add typing stubs & tests for async mode API * Add tests for async mode auto configuration * Refactor Provider.__call__() to use async mode api * Refactor Dependency provider to use async mode api * Add tests for Dependency provider async mode * Add support of async mode for FactoryAggregate provider + tests * Refactor Singleton provider to use async mode api * Refactor ThreadSafeSingleton provider to use async mode api * Refactor ThreadLocalSingleton provider to use async mode api * Finish Singleton refactoring to use async mode api * Refactor Resource provider to use async mode api * Add Provider.async_() method + tests * Add typing stubs for async_() method + tests * Refactor Singleton typing stubs to return singleton from argument methods * Refactor provider typing stubs * Improve resource typing stub * Add tests for async context kwargs injections * Fix typo in resource provider tests * Cover shutdown of not initialized resource * Add test to cover resource initialization with an error * Fix Singleton and ThreadLocalSingleton to handle initialization errors * Add FastAPI + Redis example * Make cosmetic fixes to FastAPI + Redis example * Add missing development requirements * Update module docblock in fastapi + redis example * Add FastAPI + Redis example docs * Add references to FastAPI + Redis example * Refactor resource docs * Add asynchronous resources docs * Refactor wiring docs * Add async injections docs for wiring * Add async injections page and update docs index, readme, and key features pages * Add providers async injections example * Add docs on provider async mode enabling * Reword async provider docs * Add provider async mode docs * Add cross links to async docs * Mute flake8 errors in async provider examples * Update changelog * Make cosmetic fix to containers.pyx
109 lines
3.6 KiB
ReStructuredText
109 lines
3.6 KiB
ReStructuredText
.. _async-injections:
|
|
|
|
Asynchronous injections
|
|
=======================
|
|
|
|
.. meta::
|
|
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Providers,Async,Injections,Asynchronous,Await,
|
|
Asyncio
|
|
:description: Dependency Injector providers support asynchronous injections. This page
|
|
demonstrates how make asynchronous dependency injections in Python.
|
|
|
|
Providers support asynchronous injections.
|
|
|
|
.. literalinclude:: ../../examples/providers/async.py
|
|
:language: python
|
|
:emphasize-lines: 26-29
|
|
:lines: 3-
|
|
|
|
If provider has any awaitable injections it switches into async mode. In async mode provider always returns awaitable.
|
|
This causes a cascade effect:
|
|
|
|
.. code-block:: bash
|
|
|
|
provider1() <── Async mode enabled <──┐
|
|
│ │
|
|
├──> provider2() │
|
|
│ │
|
|
├──> provider3() <── Async mode enabled <──┤
|
|
│ │ │
|
|
│ └──> provider4() <── Async provider ───────┘
|
|
│
|
|
└──> provider5()
|
|
│
|
|
└──> provider6()
|
|
|
|
In async mode provider prepares injections asynchronously.
|
|
|
|
If provider has multiple awaitable dependencies, it will run them concurrently. Provider will wait until all
|
|
dependencies are ready and inject them afterwards.
|
|
|
|
.. code-block:: bash
|
|
|
|
provider1()
|
|
│
|
|
├──> provider2() <── Async mode enabled
|
|
│
|
|
├──> provider3() <── Async mode enabled
|
|
│
|
|
└──> provider4() <── Async mode enabled
|
|
|
|
Here is what provider will do for the previous example:
|
|
|
|
.. code-block:: python
|
|
|
|
injections = await asyncio.gather(
|
|
provider2(),
|
|
provider3(),
|
|
provider4(),
|
|
)
|
|
await provider1(*injections)
|
|
|
|
Overriding behaviour
|
|
--------------------
|
|
|
|
In async mode provider always returns awaitable. It applies to the overriding too. If provider in async mode is
|
|
overridden by a provider that doesn't return awaitable result, the result will be wrapped into awaitable.
|
|
|
|
.. literalinclude:: ../../examples/providers/async_overriding.py
|
|
:language: python
|
|
:emphasize-lines: 19-24
|
|
:lines: 3-
|
|
|
|
Async mode mechanics and API
|
|
----------------------------
|
|
|
|
By default provider's async mode is undefined.
|
|
|
|
When provider async mode is undefined, provider will automatically select the mode during the next call.
|
|
If the result is awaitable, provider will enable async mode, if not - disable it.
|
|
|
|
If provider async mode is enabled, provider always returns awaitable. If the result is not awaitable,
|
|
provider wraps it into awaitable explicitly. You can safely ``await`` provider in async mode.
|
|
|
|
If provider async mode is disabled, provider behaves the regular way. It doesn't do async injections
|
|
preparation or non-awaitables to awaitables conversion.
|
|
|
|
Once provider async mode is enabled or disabled, provider will stay in this state. No automatic switching
|
|
will be done.
|
|
|
|
.. image:: images/async_mode.png
|
|
|
|
You can also use following methods to change provider's async mode manually:
|
|
|
|
- ``Provider.enable_async_mode()``
|
|
- ``Provider.disable_async_mode()``
|
|
- ``Provider.reset_async_mode()``
|
|
|
|
To check the state of provider's async mode use:
|
|
|
|
- ``Provider.is_async_mode_enabled()``
|
|
- ``Provider.is_async_mode_disabled()``
|
|
- ``Provider.is_async_mode_undefined()``
|
|
|
|
See also:
|
|
|
|
- Wiring :ref:`async-injections-wiring`
|
|
- Resource provider :ref:`resource-async-initializers`
|
|
- :ref:`fastapi-redis-example`
|