Refactor kwargs injections

This commit is contained in:
Roman Mogylatov 2020-12-12 11:37:06 -05:00
parent aaacc07916
commit af51779477
4 changed files with 4132 additions and 3452 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -360,10 +360,9 @@ cdef inline tuple __provide_positional_args(
return tuple(positional_args) return tuple(positional_args)
# TODO: refactor
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
cdef inline dict __provide_keyword_args( cdef inline object __provide_keyword_args(
dict kwargs, dict kwargs,
tuple inj_kwargs, tuple inj_kwargs,
int inj_kwargs_len, int inj_kwargs_len,
@ -380,10 +379,9 @@ cdef inline dict __provide_keyword_args(
kw_injection = <NamedInjection>inj_kwargs[index] kw_injection = <NamedInjection>inj_kwargs[index]
name = __get_name(kw_injection) name = __get_name(kw_injection)
value = __get_value(kw_injection) value = __get_value(kw_injection)
kwargs[name] = value
if __isawaitable(value): if __isawaitable(value):
awaitables.append((name, value)) awaitables.append((name, value))
else:
kwargs[name] = value
else: else:
kwargs, prefixed = __separate_prefixed_kwargs(kwargs) kwargs, prefixed = __separate_prefixed_kwargs(kwargs)
@ -400,12 +398,29 @@ cdef inline dict __provide_keyword_args(
else: else:
value = __get_value(kw_injection) value = __get_value(kw_injection)
kwargs[name] = value
if __isawaitable(value): if __isawaitable(value):
awaitables.append((name, value)) awaitables.append((name, value))
else:
kwargs[name] = value
return {'kwargs': kwargs, 'awaitables': awaitables} if awaitables:
future_result = asyncio.Future()
args_future = asyncio.Future()
args_future.set_result((future_result, kwargs, awaitables))
kwargs_ready = asyncio.gather(args_future, *[value for _, value in awaitables])
kwargs_ready.add_done_callback(__async_prepare_kwargs_callback)
asyncio.ensure_future(kwargs_ready)
return future_result
return kwargs
cdef inline void __async_prepare_kwargs_callback(object future):
(future_result, kwargs, awaitables), *awaited = future.result()
for value, (name, _) in zip(awaited, awaitables):
kwargs[name] = value
future_result.set_result(kwargs)
@cython.boundscheck(False) @cython.boundscheck(False)
@ -428,59 +443,39 @@ cdef inline object __call(
tuple context_args, tuple context_args,
tuple injection_args, tuple injection_args,
int injection_args_len, int injection_args_len,
dict kwargs, dict context_kwargs,
tuple injection_kwargs, tuple injection_kwargs,
int injection_kwargs_len, int injection_kwargs_len,
): ):
cdef tuple positional_args args = __provide_positional_args(
cdef dict keyword_args
positional_args = __provide_positional_args(
context_args, context_args,
injection_args, injection_args,
injection_args_len, injection_args_len,
) )
kw_return = __provide_keyword_args( kwargs = __provide_keyword_args(
kwargs, context_kwargs,
injection_kwargs, injection_kwargs,
injection_kwargs_len, injection_kwargs_len,
) )
keyword_args, awaitable_keyword_args = kw_return['kwargs'], kw_return['awaitables']
# TODO: Refactor if __isawaitable(kwargs):
if awaitable_keyword_args: future_result = asyncio.Future()
call_future = asyncio.Future()
future = asyncio.Future() args_future = asyncio.Future()
future.set_result( args_future.set_result((future_result, call, args))
( args_kwargs_ready = asyncio.gather(args_future, kwargs)
call_future, args_kwargs_ready.add_done_callback(__async_call_callback)
call, asyncio.ensure_future(args_kwargs_ready)
positional_args,
keyword_args,
awaitable_keyword_args,
),
)
kwargs_ready = asyncio.gather(future, *[value for _, value in awaitable_keyword_args]) return future_result
kwargs_ready.add_done_callback(__async_call_callback)
asyncio.ensure_future(kwargs_ready)
return call_future return call(*args, **kwargs)
return call(*positional_args, **keyword_args)
# TODO: refactor cdef inline void __async_call_callback(object future):
cdef inline object __async_call_callback(object injections): (future_result, call, args), kwargs = future.result()
(call_future, call, positional_args, keyword_args, awaitable_keyword_args), *awaited_keyword_args = injections.result() result = call(*args, **kwargs)
future_result.set_result(result)
for value, (name, _) in zip(awaited_keyword_args, awaitable_keyword_args):
keyword_args[name] = value
result = call(*positional_args, **keyword_args)
call_future.set_result(result)
cdef inline object __callable_call(Callable self, tuple args, dict kwargs): cdef inline object __callable_call(Callable self, tuple args, dict kwargs):

View File

@ -2564,9 +2564,7 @@ cdef class Dict(Provider):
cpdef object _provide(self, tuple args, dict kwargs): cpdef object _provide(self, tuple args, dict kwargs):
"""Return result of provided callable's call.""" """Return result of provided callable's call."""
# TODO: hotfix, remove return __provide_keyword_args(kwargs, self.__kwargs, self.__kwargs_len)
kwargs = __provide_keyword_args(kwargs, self.__kwargs, self.__kwargs_len)
return kwargs['kwargs']
cdef class Resource(Provider): cdef class Resource(Provider):