Refactor asynchronous injections

This commit is contained in:
Roman Mogylatov 2021-01-21 11:20:21 -05:00
parent 4b0272ab30
commit c16f974517
4 changed files with 3901 additions and 2717 deletions

View File

@ -12,6 +12,7 @@ follows `Semantic versioning`_
- Fix a bug with asynchronous injections: async providers do not work with async dependencies. - 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>`_. See issue: `#368 <https://github.com/ets-labs/python-dependency-injector/issues/368>`_.
Thanks `@kolypto <https://github.com/kolypto>`_ for the bug report. Thanks `@kolypto <https://github.com/kolypto>`_ for the bug report.
- Refactor asynchronous injections.
4.10.3 4.10.3
------ ------

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -420,18 +420,27 @@ cdef inline object __provide_keyword_args(
cdef inline object __awaitable_args_kwargs_future(object args, list awaitables): cdef inline object __awaitable_args_kwargs_future(object args, list awaitables):
future_result = asyncio.Future() future_result = asyncio.Future()
args_future = asyncio.Future() args_ready = asyncio.gather(*[value for _, value in awaitables])
args_future.set_result((future_result, args, awaitables)) args_ready.add_done_callback(
functools.partial(
args_ready = asyncio.gather(args_future, *[value for _, value in awaitables]) __async_prepare_args_kwargs_callback,
args_ready.add_done_callback(__async_prepare_args_kwargs_callback) future_result,
args,
awaitables,
),
)
asyncio.ensure_future(args_ready) asyncio.ensure_future(args_ready)
return future_result return future_result
cdef inline void __async_prepare_args_kwargs_callback(object future): cdef inline void __async_prepare_args_kwargs_callback(
(future_result, args, awaitables), *awaited = future.result() object future_result,
object args,
object awaitables,
object future,
):
awaited = future.result()
for value, (key, _) in zip(awaited, awaitables): for value, (key, _) in zip(awaited, awaitables):
args[key] = value args[key] = value
future_result.set_result(args) future_result.set_result(args)
@ -461,17 +470,20 @@ cdef inline object __provide_attributes(tuple attributes, int attributes_len):
cdef inline object __async_inject_attributes(future_instance, future_attributes): cdef inline object __async_inject_attributes(future_instance, future_attributes):
future_result = asyncio.Future() future_result = asyncio.Future()
future = asyncio.Future() attributes_ready = asyncio.gather(future_instance, future_attributes)
future.set_result(future_result) attributes_ready.add_done_callback(
functools.partial(
attributes_ready = asyncio.gather(future, future_instance, future_attributes) __async_inject_attributes_callback,
attributes_ready.add_done_callback(__async_inject_attributes_callback) future_result,
),
)
asyncio.ensure_future(attributes_ready) asyncio.ensure_future(attributes_ready)
return future_result return future_result
cdef inline void __async_inject_attributes_callback(future):
future_result, instance, attributes = future.result() cdef inline void __async_inject_attributes_callback(object future_result, object future):
instance, attributes = future.result()
__inject_attributes(instance, attributes) __inject_attributes(instance, attributes)
future_result.set_result(instance) future_result.set_result(instance)
@ -517,11 +529,14 @@ cdef inline object __call(
future_result = asyncio.Future() future_result = asyncio.Future()
future = asyncio.Future() args_kwargs_ready = asyncio.gather(args, kwargs)
future.set_result((future_result, call)) args_kwargs_ready.add_done_callback(
functools.partial(
args_kwargs_ready = asyncio.gather(future, args, kwargs) __async_call_callback,
args_kwargs_ready.add_done_callback(__async_call_callback) future_result,
call,
),
)
asyncio.ensure_future(args_kwargs_ready) asyncio.ensure_future(args_kwargs_ready)
return future_result return future_result
@ -529,8 +544,8 @@ cdef inline object __call(
return call(*args, **kwargs) return call(*args, **kwargs)
cdef inline void __async_call_callback(object future): cdef inline void __async_call_callback(object future_result, object call, object future):
(future_result, call), args, kwargs = future.result() args, kwargs = future.result()
result = call(*args, **kwargs) result = call(*args, **kwargs)
if __isawaitable(result): if __isawaitable(result):