Fix #368 Async providers do not work with async dependencies

This commit is contained in:
Roman Mogylatov 2021-01-21 10:51:37 -05:00
parent 349c252b50
commit 4b0272ab30
5 changed files with 2651 additions and 1514 deletions

View File

@ -7,6 +7,12 @@ that were made in every particular version.
From version 0.7.6 *Dependency Injector* framework strictly From version 0.7.6 *Dependency Injector* framework strictly
follows `Semantic versioning`_ follows `Semantic versioning`_
4.10.4
------
- Fix a bug with asynchronous injections: async providers do not work with async dependencies.
See issue: `#368 <https://github.com/ets-labs/python-dependency-injector/issues/368>`_.
Thanks `@kolypto <https://github.com/kolypto>`_ for the bug report.
4.10.3 4.10.3
------ ------
- Fix a bug in the ``Configuration`` provider: strict mode didn't work when provider - Fix a bug in the ``Configuration`` provider: strict mode didn't work when provider

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@ try:
except ImportError: except ImportError:
asyncio = None asyncio = None
import functools
import inspect import inspect
cimport cython cimport cython
@ -531,9 +532,19 @@ cdef inline object __call(
cdef inline void __async_call_callback(object future): cdef inline void __async_call_callback(object future):
(future_result, call), args, kwargs = future.result() (future_result, call), args, kwargs = future.result()
result = call(*args, **kwargs) result = call(*args, **kwargs)
if __isawaitable(result):
result = asyncio.ensure_future(result)
result.add_done_callback(functools.partial(__async_result_callback, future_result))
return
future_result.set_result(result) future_result.set_result(result)
cdef inline object __async_result_callback(object future_result, object future):
future_result.set_result(future.result())
cdef inline object __callable_call(Callable self, tuple args, dict kwargs): cdef inline object __callable_call(Callable self, tuple args, dict kwargs):
return __call( return __call(
self.__provides, self.__provides,

View File

@ -816,3 +816,24 @@ class AsyncTypingStubTests(AsyncTestCase):
self.assertIs(service2.client.resource2, RESOURCE2) self.assertIs(service2.client.resource2, RESOURCE2)
self.assertIsNot(service1.client, service2.client) self.assertIsNot(service1.client, service2.client)
class AsyncProvidersWithAsyncDependenciesTests(AsyncTestCase):
def test_injections(self):
# See: https://github.com/ets-labs/python-dependency-injector/issues/368
async def async_db_provider():
return {'db': 'ok'}
async def async_service(db=None):
return {'service': 'ok', 'db': db}
class Container(containers.DeclarativeContainer):
db = providers.Factory(async_db_provider)
service = providers.Singleton(async_service, db=db)
container = Container()
service = self._run(container.service())
self.assertEquals(service, {'service': 'ok', 'db': {'db': 'ok'}})