(#454) (#597) Fix @inject + @wraps, refactor patched callables registry and injections storage principles (#610)

* Refactor patched callables registry and injections storage principles

* Rename properties of PatchedRegistry

* Add typing improvements in wiring module

* Add __slots__ for PatchedAttribute

* Minor code style fixes

* Add test

* Rename test

* Update typing in test

* Make minor style fixes to test

* Update changelog

* Add documentation on the @inject decorator
This commit is contained in:
Roman Mogylatov 2022-07-26 21:37:15 -04:00 committed by GitHub
parent 0668295543
commit 6f859e4aa2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 545 additions and 280 deletions

View File

@ -11,7 +11,13 @@ follows `Semantic versioning`_
Development Development
----------- -----------
- Add ``Configuration.from_json()`` method to load configuration from a json file. - Add ``Configuration.from_json()`` method to load configuration from a json file.
- Fix bug with wiring not working properly with functions double wrapped by ``@functools.wraps`` decorator.
See issue: `#454 <https://github.com/ets-labs/python-dependency-injector/issues/454>`_.
Many thanks to: `@platipo <https://github.com/platipo>`_, `@MatthieuMoreau0 <https://github.com/MatthieuMoreau0>`_,
`@fabiocerqueira <https://github.com/fabiocerqueira>`_, `@Jitesh-Khuttan <https://github.com/Jitesh-Khuttan>`_.
- Refactor wiring module to store all patched callable data in the ``PatchedRegistry``.
- Improve wording on the "Dependency injection and inversion of control in Python" docs page. - Improve wording on the "Dependency injection and inversion of control in Python" docs page.
- Add documentation on the ``@inject`` decorator.
- Update typing in the main example and cohesion/coupling correlation definition in - Update typing in the main example and cohesion/coupling correlation definition in
"Dependency injection and inversion of control in Python". "Dependency injection and inversion of control in Python".
Thanks to `@illia-v (Illia Volochii) <https://github.com/illia-v>`_ for the Thanks to `@illia-v (Illia Volochii) <https://github.com/illia-v>`_ for the

View File

@ -22,6 +22,82 @@ To use wiring you need:
:local: :local:
:backlinks: none :backlinks: none
Decorator @inject
-----------------
Decorator ``@inject`` injects the dependencies. Use it to decorate all functions and methods
with the injections.
.. code-block:: python
from dependency_injector.wiring import inject, Provide
@inject
def foo(bar: Bar = Provide[Container.bar]):
...
Decorator ``@inject`` must be specified as a very first decorator of a function to ensure that
the wiring works appropriately. This will also contribute to the performance of the wiring process.
.. code-block:: python
from dependency_injector.wiring import inject, Provide
@decorator_etc
@decorator_2
@decorator_1
@inject
def foo(bar: Bar = Provide[Container.bar]):
...
Specifying the ``@inject`` as a first decorator is also crucial for FastAPI, other frameworks
using decorators similarly, for closures, and for any types of custom decorators with the injections.
FastAPI example:
.. code-block:: python
app = FastAPI()
@app.api_route("/")
@inject
async def index(service: Service = Depends(Provide[Container.service])):
value = await service.process()
return {"result": value}
Decorators example:
.. code-block:: python
def decorator1(func):
@functools.wraps(func)
@inject
def wrapper(value1: int = Provide[Container.config.value1]):
result = func()
return result + value1
return wrapper
def decorator2(func):
@functools.wraps(func)
@inject
def wrapper(value2: int = Provide[Container.config.value2]):
result = func()
return result + value2
return wrapper
@decorator1
@decorator2
def sample():
...
.. seealso::
`Issue #404 <https://github.com/ets-labs/python-dependency-injector/issues/404#issuecomment-785216978>`_
explains ``@inject`` decorator in a few more details.
Markers Markers
------- -------

View File

@ -1657,14 +1657,14 @@ struct __pyx_obj_19dependency_injector_9providers_SingletonFullResetContext {
/* "dependency_injector/_cwiring.pyx":15 /* "dependency_injector/_cwiring.pyx":15
* *
* *
* def _get_sync_patched(fn): # <<<<<<<<<<<<<< * def _get_sync_patched(fn, patched: PatchedCallable): # <<<<<<<<<<<<<<
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): * def _patched(*args, **kwargs):
*/ */
struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched { struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched {
PyObject_HEAD PyObject_HEAD
PyObject *__pyx_v__patched;
PyObject *__pyx_v_fn; PyObject *__pyx_v_fn;
PyObject *__pyx_v_patched;
}; };
@ -2424,6 +2424,18 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject
/* GetBuiltinName.proto */ /* GetBuiltinName.proto */
static PyObject *__Pyx_GetBuiltinName(PyObject *name); static PyObject *__Pyx_GetBuiltinName(PyObject *name);
/* RaiseArgTupleInvalid.proto */
static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found);
/* RaiseDoubleKeywords.proto */
static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name);
/* ParseKeywords.proto */
static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\
PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\
const char* function_name);
/* KeywordStringCheck.proto */ /* KeywordStringCheck.proto */
static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed);
@ -2635,18 +2647,6 @@ static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml,
PyObject *module, PyObject *globals, PyObject *module, PyObject *globals,
PyObject* code); PyObject* code);
/* RaiseArgTupleInvalid.proto */
static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found);
/* RaiseDoubleKeywords.proto */
static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name);
/* ParseKeywords.proto */
static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\
PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\
const char* function_name);
/* ArgTypeTest.proto */ /* ArgTypeTest.proto */
#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ #define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\
((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\ ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\
@ -3203,12 +3203,12 @@ static const char __pyx_k_result[] = "result";
static const char __pyx_k_wiring[] = "wiring"; static const char __pyx_k_wiring[] = "wiring";
static const char __pyx_k_arg_key[] = "arg_key"; static const char __pyx_k_arg_key[] = "arg_key";
static const char __pyx_k_asyncio[] = "asyncio"; static const char __pyx_k_asyncio[] = "asyncio";
static const char __pyx_k_closing[] = "__closing__"; static const char __pyx_k_closing[] = "closing";
static const char __pyx_k_genexpr[] = "genexpr"; static const char __pyx_k_genexpr[] = "genexpr";
static const char __pyx_k_gi_code[] = "gi_code"; static const char __pyx_k_gi_code[] = "gi_code";
static const char __pyx_k_inspect[] = "inspect"; static const char __pyx_k_inspect[] = "inspect";
static const char __pyx_k_partial[] = "partial"; static const char __pyx_k_partial[] = "partial";
static const char __pyx_k_patched[] = "_patched"; static const char __pyx_k_patched[] = "patched";
static const char __pyx_k_provide[] = "provide"; static const char __pyx_k_provide[] = "provide";
static const char __pyx_k_Resource[] = "Resource"; static const char __pyx_k_Resource[] = "Resource";
static const char __pyx_k_closings[] = "closings"; static const char __pyx_k_closings[] = "closings";
@ -3218,16 +3218,16 @@ static const char __pyx_k_shutdown[] = "shutdown";
static const char __pyx_k_Awaitable[] = "Awaitable"; static const char __pyx_k_Awaitable[] = "Awaitable";
static const char __pyx_k_functools[] = "functools"; static const char __pyx_k_functools[] = "functools";
static const char __pyx_k_injection[] = "injection"; static const char __pyx_k_injection[] = "injection";
static const char __pyx_k_patched_2[] = "_patched";
static const char __pyx_k_providers[] = "providers"; static const char __pyx_k_providers[] = "providers";
static const char __pyx_k_to_inject[] = "to_inject"; static const char __pyx_k_to_inject[] = "to_inject";
static const char __pyx_k_injections[] = "__injections__"; static const char __pyx_k_injections[] = "injections";
static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__"; static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__";
static const char __pyx_k_set_result[] = "set_result"; static const char __pyx_k_set_result[] = "set_result";
static const char __pyx_k_ImportError[] = "ImportError"; static const char __pyx_k_ImportError[] = "ImportError";
static const char __pyx_k_cfunc_to_py[] = "cfunc.to_py"; static const char __pyx_k_cfunc_to_py[] = "cfunc.to_py";
static const char __pyx_k_collections[] = "collections"; static const char __pyx_k_collections[] = "collections";
static const char __pyx_k_async_inject[] = "_async_inject"; static const char __pyx_k_async_inject[] = "_async_inject";
static const char __pyx_k_injections_2[] = "injections";
static const char __pyx_k_stringsource[] = "stringsource"; static const char __pyx_k_stringsource[] = "stringsource";
static const char __pyx_k_CoroutineType[] = "CoroutineType"; static const char __pyx_k_CoroutineType[] = "CoroutineType";
static const char __pyx_k_GeneratorType[] = "GeneratorType"; static const char __pyx_k_GeneratorType[] = "GeneratorType";
@ -3236,6 +3236,7 @@ static const char __pyx_k_ensure_future[] = "ensure_future";
static const char __pyx_k_future_result[] = "future_result"; static const char __pyx_k_future_result[] = "future_result";
static const char __pyx_k_set_exception[] = "set_exception"; static const char __pyx_k_set_exception[] = "set_exception";
static const char __pyx_k_to_close_await[] = "to_close_await"; static const char __pyx_k_to_close_await[] = "to_close_await";
static const char __pyx_k_PatchedCallable[] = "PatchedCallable";
static const char __pyx_k_async_to_inject[] = "async_to_inject"; static const char __pyx_k_async_to_inject[] = "async_to_inject";
static const char __pyx_k_collections_abc[] = "collections.abc"; static const char __pyx_k_collections_abc[] = "collections.abc";
static const char __pyx_k_to_inject_await[] = "to_inject_await"; static const char __pyx_k_to_inject_await[] = "to_inject_await";
@ -3262,6 +3263,7 @@ static PyObject *__pyx_n_s_Future;
static PyObject *__pyx_n_s_GeneratorType; static PyObject *__pyx_n_s_GeneratorType;
static PyObject *__pyx_n_s_ImportError; static PyObject *__pyx_n_s_ImportError;
static PyObject *__pyx_n_s_Marker; static PyObject *__pyx_n_s_Marker;
static PyObject *__pyx_n_s_PatchedCallable;
static PyObject *__pyx_n_s_Pyx_CFunc_object____object; static PyObject *__pyx_n_s_Pyx_CFunc_object____object;
static PyObject *__pyx_n_s_Pyx_CFunc_void____object____ob; static PyObject *__pyx_n_s_Pyx_CFunc_void____object____ob;
static PyObject *__pyx_n_s_Pyx_CFunc_void____object____ob_2; static PyObject *__pyx_n_s_Pyx_CFunc_void____object____ob_2;
@ -3308,7 +3310,6 @@ static PyObject *__pyx_n_s_import;
static PyObject *__pyx_n_s_index; static PyObject *__pyx_n_s_index;
static PyObject *__pyx_n_s_injection; static PyObject *__pyx_n_s_injection;
static PyObject *__pyx_n_s_injections; static PyObject *__pyx_n_s_injections;
static PyObject *__pyx_n_s_injections_2;
static PyObject *__pyx_n_s_inspect; static PyObject *__pyx_n_s_inspect;
static PyObject *__pyx_n_s_items; static PyObject *__pyx_n_s_items;
static PyObject *__pyx_n_s_kwargs; static PyObject *__pyx_n_s_kwargs;
@ -3316,6 +3317,7 @@ static PyObject *__pyx_n_s_main;
static PyObject *__pyx_n_s_name; static PyObject *__pyx_n_s_name;
static PyObject *__pyx_n_s_partial; static PyObject *__pyx_n_s_partial;
static PyObject *__pyx_n_s_patched; static PyObject *__pyx_n_s_patched;
static PyObject *__pyx_n_s_patched_2;
static PyObject *__pyx_n_s_provide; static PyObject *__pyx_n_s_provide;
static PyObject *__pyx_n_s_provider; static PyObject *__pyx_n_s_provider;
static PyObject *__pyx_n_s_providers; static PyObject *__pyx_n_s_providers;
@ -3339,7 +3341,7 @@ static PyObject *__pyx_n_s_wrap;
static PyObject *__pyx_n_s_wraps; static PyObject *__pyx_n_s_wraps;
static PyObject *__pyx_n_s_zip; static PyObject *__pyx_n_s_zip;
static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__patched(PyObject *__pyx_self, PyObject *__pyx_v_args, PyObject *__pyx_v_kwargs); /* proto */ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__patched(PyObject *__pyx_self, PyObject *__pyx_v_args, PyObject *__pyx_v_kwargs); /* proto */
static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn); /* proto */ static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn, PyObject *__pyx_v_patched); /* proto */
static PyObject *__pyx_pf_19dependency_injector_8_cwiring_13_async_inject_genexpr(PyObject *__pyx_self); /* proto */ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_13_async_inject_genexpr(PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_19dependency_injector_8_cwiring_2_async_inject(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn, PyObject *__pyx_v_args, PyObject *__pyx_v_kwargs, PyObject *__pyx_v_injections, PyObject *__pyx_v_closings); /* proto */ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_2_async_inject(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn, PyObject *__pyx_v_args, PyObject *__pyx_v_kwargs, PyObject *__pyx_v_injections, PyObject *__pyx_v_closings); /* proto */
static PyObject *__pyx_pf_11cfunc_dot_to_py_64__Pyx_CFunc_void____object____object____object____object___to_py_wrap(PyObject *__pyx_self, PyObject *__pyx_v_future_result, PyObject *__pyx_v_args, PyObject *__pyx_v_future_args_kwargs, PyObject *__pyx_v_future); /* proto */ static PyObject *__pyx_pf_11cfunc_dot_to_py_64__Pyx_CFunc_void____object____object____object____object___to_py_wrap(PyObject *__pyx_self, PyObject *__pyx_v_future_result, PyObject *__pyx_v_args, PyObject *__pyx_v_future_args_kwargs, PyObject *__pyx_v_future); /* proto */
@ -3374,19 +3376,70 @@ static PyObject *__pyx_codeobj__15;
/* "dependency_injector/_cwiring.pyx":15 /* "dependency_injector/_cwiring.pyx":15
* *
* *
* def _get_sync_patched(fn): # <<<<<<<<<<<<<< * def _get_sync_patched(fn, patched: PatchedCallable): # <<<<<<<<<<<<<<
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): * def _patched(*args, **kwargs):
*/ */
/* Python wrapper */ /* Python wrapper */
static PyObject *__pyx_pw_19dependency_injector_8_cwiring_1_get_sync_patched(PyObject *__pyx_self, PyObject *__pyx_v_fn); /*proto*/ static PyObject *__pyx_pw_19dependency_injector_8_cwiring_1_get_sync_patched(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_19dependency_injector_8_cwiring_1_get_sync_patched = {"_get_sync_patched", (PyCFunction)__pyx_pw_19dependency_injector_8_cwiring_1_get_sync_patched, METH_O, 0}; static PyMethodDef __pyx_mdef_19dependency_injector_8_cwiring_1_get_sync_patched = {"_get_sync_patched", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_19dependency_injector_8_cwiring_1_get_sync_patched, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_19dependency_injector_8_cwiring_1_get_sync_patched(PyObject *__pyx_self, PyObject *__pyx_v_fn) { static PyObject *__pyx_pw_19dependency_injector_8_cwiring_1_get_sync_patched(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
PyObject *__pyx_v_fn = 0;
PyObject *__pyx_v_patched = 0;
int __pyx_lineno = 0;
const char *__pyx_filename = NULL;
int __pyx_clineno = 0;
PyObject *__pyx_r = 0; PyObject *__pyx_r = 0;
__Pyx_RefNannyDeclarations __Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("_get_sync_patched (wrapper)", 0); __Pyx_RefNannySetupContext("_get_sync_patched (wrapper)", 0);
__pyx_r = __pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(__pyx_self, ((PyObject *)__pyx_v_fn)); {
static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_fn,&__pyx_n_s_patched,0};
PyObject* values[2] = {0,0};
if (unlikely(__pyx_kwds)) {
Py_ssize_t kw_args;
const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
switch (pos_args) {
case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
CYTHON_FALLTHROUGH;
case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
CYTHON_FALLTHROUGH;
case 0: break;
default: goto __pyx_L5_argtuple_error;
}
kw_args = PyDict_Size(__pyx_kwds);
switch (pos_args) {
case 0:
if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_fn)) != 0)) kw_args--;
else goto __pyx_L5_argtuple_error;
CYTHON_FALLTHROUGH;
case 1:
if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_patched)) != 0)) kw_args--;
else {
__Pyx_RaiseArgtupleInvalid("_get_sync_patched", 1, 2, 2, 1); __PYX_ERR(0, 15, __pyx_L3_error)
}
}
if (unlikely(kw_args > 0)) {
if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_get_sync_patched") < 0)) __PYX_ERR(0, 15, __pyx_L3_error)
}
} else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
goto __pyx_L5_argtuple_error;
} else {
values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
}
__pyx_v_fn = values[0];
__pyx_v_patched = values[1];
}
goto __pyx_L4_argument_unpacking_done;
__pyx_L5_argtuple_error:;
__Pyx_RaiseArgtupleInvalid("_get_sync_patched", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 15, __pyx_L3_error)
__pyx_L3_error:;
__Pyx_AddTraceback("dependency_injector._cwiring._get_sync_patched", __pyx_clineno, __pyx_lineno, __pyx_filename);
__Pyx_RefNannyFinishContext();
return NULL;
__pyx_L4_argument_unpacking_done:;
__pyx_r = __pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(__pyx_self, __pyx_v_fn, __pyx_v_patched);
/* function exit code */ /* function exit code */
__Pyx_RefNannyFinishContext(); __Pyx_RefNannyFinishContext();
@ -3394,7 +3447,7 @@ static PyObject *__pyx_pw_19dependency_injector_8_cwiring_1_get_sync_patched(PyO
} }
/* "dependency_injector/_cwiring.pyx":17 /* "dependency_injector/_cwiring.pyx":17
* def _get_sync_patched(fn): * def _get_sync_patched(fn, patched: PatchedCallable):
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): # <<<<<<<<<<<<<< * def _patched(*args, **kwargs): # <<<<<<<<<<<<<<
* cdef object result * cdef object result
@ -3455,7 +3508,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
* cdef Provider provider * cdef Provider provider
* *
* to_inject = kwargs.copy() # <<<<<<<<<<<<<< * to_inject = kwargs.copy() # <<<<<<<<<<<<<<
* for arg_key, provider in _patched.__injections__.items(): * for arg_key, provider in patched.injections.items():
* if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): * if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
*/ */
__pyx_t_1 = PyDict_Copy(__pyx_v_kwargs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 23, __pyx_L1_error) __pyx_t_1 = PyDict_Copy(__pyx_v_kwargs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 23, __pyx_L1_error)
@ -3466,12 +3519,12 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":24 /* "dependency_injector/_cwiring.pyx":24
* *
* to_inject = kwargs.copy() * to_inject = kwargs.copy()
* for arg_key, provider in _patched.__injections__.items(): # <<<<<<<<<<<<<< * for arg_key, provider in patched.injections.items(): # <<<<<<<<<<<<<<
* if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): * if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
* to_inject[arg_key] = provider() * to_inject[arg_key] = provider()
*/ */
if (unlikely(!__pyx_cur_scope->__pyx_v__patched)) { __Pyx_RaiseClosureNameError("_patched"); __PYX_ERR(0, 24, __pyx_L1_error) } if (unlikely(!__pyx_cur_scope->__pyx_v_patched)) { __Pyx_RaiseClosureNameError("patched"); __PYX_ERR(0, 24, __pyx_L1_error) }
__pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v__patched, __pyx_n_s_injections); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_patched, __pyx_n_s_injections); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2); __Pyx_GOTREF(__pyx_t_2);
__pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_items); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 24, __pyx_L1_error) __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_items); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 24, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_3); __Pyx_GOTREF(__pyx_t_3);
@ -3585,7 +3638,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":25 /* "dependency_injector/_cwiring.pyx":25
* to_inject = kwargs.copy() * to_inject = kwargs.copy()
* for arg_key, provider in _patched.__injections__.items(): * for arg_key, provider in patched.injections.items():
* if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<< * if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<<
* to_inject[arg_key] = provider() * to_inject[arg_key] = provider()
* *
@ -3610,7 +3663,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
if (__pyx_t_9) { if (__pyx_t_9) {
/* "dependency_injector/_cwiring.pyx":26 /* "dependency_injector/_cwiring.pyx":26
* for arg_key, provider in _patched.__injections__.items(): * for arg_key, provider in patched.injections.items():
* if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): * if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
* to_inject[arg_key] = provider() # <<<<<<<<<<<<<< * to_inject[arg_key] = provider() # <<<<<<<<<<<<<<
* *
@ -3641,7 +3694,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":25 /* "dependency_injector/_cwiring.pyx":25
* to_inject = kwargs.copy() * to_inject = kwargs.copy()
* for arg_key, provider in _patched.__injections__.items(): * for arg_key, provider in patched.injections.items():
* if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<< * if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<<
* to_inject[arg_key] = provider() * to_inject[arg_key] = provider()
* *
@ -3651,7 +3704,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":24 /* "dependency_injector/_cwiring.pyx":24
* *
* to_inject = kwargs.copy() * to_inject = kwargs.copy()
* for arg_key, provider in _patched.__injections__.items(): # <<<<<<<<<<<<<< * for arg_key, provider in patched.injections.items(): # <<<<<<<<<<<<<<
* if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): * if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
* to_inject[arg_key] = provider() * to_inject[arg_key] = provider()
*/ */
@ -3663,7 +3716,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
* *
* result = fn(*args, **to_inject) # <<<<<<<<<<<<<< * result = fn(*args, **to_inject) # <<<<<<<<<<<<<<
* *
* if _patched.__closing__: * if patched.closing:
*/ */
if (unlikely(!__pyx_cur_scope->__pyx_v_fn)) { __Pyx_RaiseClosureNameError("fn"); __PYX_ERR(0, 28, __pyx_L1_error) } if (unlikely(!__pyx_cur_scope->__pyx_v_fn)) { __Pyx_RaiseClosureNameError("fn"); __PYX_ERR(0, 28, __pyx_L1_error) }
if (unlikely(__pyx_v_to_inject == Py_None)) { if (unlikely(__pyx_v_to_inject == Py_None)) {
@ -3681,12 +3734,12 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":30 /* "dependency_injector/_cwiring.pyx":30
* result = fn(*args, **to_inject) * result = fn(*args, **to_inject)
* *
* if _patched.__closing__: # <<<<<<<<<<<<<< * if patched.closing: # <<<<<<<<<<<<<<
* for arg_key, provider in _patched.__closing__.items(): * for arg_key, provider in patched.closing.items():
* if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): * if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker):
*/ */
if (unlikely(!__pyx_cur_scope->__pyx_v__patched)) { __Pyx_RaiseClosureNameError("_patched"); __PYX_ERR(0, 30, __pyx_L1_error) } if (unlikely(!__pyx_cur_scope->__pyx_v_patched)) { __Pyx_RaiseClosureNameError("patched"); __PYX_ERR(0, 30, __pyx_L1_error) }
__pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v__patched, __pyx_n_s_closing); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 30, __pyx_L1_error) __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_patched, __pyx_n_s_closing); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 30, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_6);
__pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 30, __pyx_L1_error) __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 30, __pyx_L1_error)
__Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
@ -3694,13 +3747,13 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":31 /* "dependency_injector/_cwiring.pyx":31
* *
* if _patched.__closing__: * if patched.closing:
* for arg_key, provider in _patched.__closing__.items(): # <<<<<<<<<<<<<< * for arg_key, provider in patched.closing.items(): # <<<<<<<<<<<<<<
* if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): * if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker):
* continue * continue
*/ */
if (unlikely(!__pyx_cur_scope->__pyx_v__patched)) { __Pyx_RaiseClosureNameError("_patched"); __PYX_ERR(0, 31, __pyx_L1_error) } if (unlikely(!__pyx_cur_scope->__pyx_v_patched)) { __Pyx_RaiseClosureNameError("patched"); __PYX_ERR(0, 31, __pyx_L1_error) }
__pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v__patched, __pyx_n_s_closing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 31, __pyx_L1_error) __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_patched, __pyx_n_s_closing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 31, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_3); __Pyx_GOTREF(__pyx_t_3);
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error) __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_1);
@ -3813,8 +3866,8 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
__pyx_t_2 = 0; __pyx_t_2 = 0;
/* "dependency_injector/_cwiring.pyx":32 /* "dependency_injector/_cwiring.pyx":32
* if _patched.__closing__: * if patched.closing:
* for arg_key, provider in _patched.__closing__.items(): * for arg_key, provider in patched.closing.items():
* if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<< * if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<<
* continue * continue
* if not isinstance(provider, providers.Resource): * if not isinstance(provider, providers.Resource):
@ -3839,7 +3892,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
if (__pyx_t_9) { if (__pyx_t_9) {
/* "dependency_injector/_cwiring.pyx":33 /* "dependency_injector/_cwiring.pyx":33
* for arg_key, provider in _patched.__closing__.items(): * for arg_key, provider in patched.closing.items():
* if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): * if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker):
* continue # <<<<<<<<<<<<<< * continue # <<<<<<<<<<<<<<
* if not isinstance(provider, providers.Resource): * if not isinstance(provider, providers.Resource):
@ -3848,8 +3901,8 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
goto __pyx_L11_continue; goto __pyx_L11_continue;
/* "dependency_injector/_cwiring.pyx":32 /* "dependency_injector/_cwiring.pyx":32
* if _patched.__closing__: * if patched.closing:
* for arg_key, provider in _patched.__closing__.items(): * for arg_key, provider in patched.closing.items():
* if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<< * if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): # <<<<<<<<<<<<<<
* continue * continue
* if not isinstance(provider, providers.Resource): * if not isinstance(provider, providers.Resource):
@ -3919,8 +3972,8 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":31 /* "dependency_injector/_cwiring.pyx":31
* *
* if _patched.__closing__: * if patched.closing:
* for arg_key, provider in _patched.__closing__.items(): # <<<<<<<<<<<<<< * for arg_key, provider in patched.closing.items(): # <<<<<<<<<<<<<<
* if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): * if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker):
* continue * continue
*/ */
@ -3931,8 +3984,8 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":30 /* "dependency_injector/_cwiring.pyx":30
* result = fn(*args, **to_inject) * result = fn(*args, **to_inject)
* *
* if _patched.__closing__: # <<<<<<<<<<<<<< * if patched.closing: # <<<<<<<<<<<<<<
* for arg_key, provider in _patched.__closing__.items(): * for arg_key, provider in patched.closing.items():
* if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): * if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker):
*/ */
} }
@ -3950,7 +4003,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
goto __pyx_L0; goto __pyx_L0;
/* "dependency_injector/_cwiring.pyx":17 /* "dependency_injector/_cwiring.pyx":17
* def _get_sync_patched(fn): * def _get_sync_patched(fn, patched: PatchedCallable):
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): # <<<<<<<<<<<<<< * def _patched(*args, **kwargs): # <<<<<<<<<<<<<<
* cdef object result * cdef object result
@ -3979,13 +4032,14 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring_17_get_sync_patched__p
/* "dependency_injector/_cwiring.pyx":15 /* "dependency_injector/_cwiring.pyx":15
* *
* *
* def _get_sync_patched(fn): # <<<<<<<<<<<<<< * def _get_sync_patched(fn, patched: PatchedCallable): # <<<<<<<<<<<<<<
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): * def _patched(*args, **kwargs):
*/ */
static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn) { static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn, PyObject *__pyx_v_patched) {
struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *__pyx_cur_scope; struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *__pyx_cur_scope;
PyObject *__pyx_v__patched = 0;
PyObject *__pyx_r = NULL; PyObject *__pyx_r = NULL;
__Pyx_RefNannyDeclarations __Pyx_RefNannyDeclarations
PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_1 = NULL;
@ -4007,10 +4061,13 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTH
__pyx_cur_scope->__pyx_v_fn = __pyx_v_fn; __pyx_cur_scope->__pyx_v_fn = __pyx_v_fn;
__Pyx_INCREF(__pyx_cur_scope->__pyx_v_fn); __Pyx_INCREF(__pyx_cur_scope->__pyx_v_fn);
__Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_fn); __Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_fn);
__pyx_cur_scope->__pyx_v_patched = __pyx_v_patched;
__Pyx_INCREF(__pyx_cur_scope->__pyx_v_patched);
__Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_patched);
/* "dependency_injector/_cwiring.pyx":16 /* "dependency_injector/_cwiring.pyx":16
* *
* def _get_sync_patched(fn): * def _get_sync_patched(fn, patched: PatchedCallable):
* @functools.wraps(fn) # <<<<<<<<<<<<<< * @functools.wraps(fn) # <<<<<<<<<<<<<<
* def _patched(*args, **kwargs): * def _patched(*args, **kwargs):
* cdef object result * cdef object result
@ -4037,7 +4094,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTH
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
/* "dependency_injector/_cwiring.pyx":17 /* "dependency_injector/_cwiring.pyx":17
* def _get_sync_patched(fn): * def _get_sync_patched(fn, patched: PatchedCallable):
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): # <<<<<<<<<<<<<< * def _patched(*args, **kwargs): # <<<<<<<<<<<<<<
* cdef object result * cdef object result
@ -4061,8 +4118,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTH
if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error) if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__Pyx_GIVEREF(__pyx_t_1); __pyx_v__patched = __pyx_t_1;
__pyx_cur_scope->__pyx_v__patched = __pyx_t_1;
__pyx_t_1 = 0; __pyx_t_1 = 0;
/* "dependency_injector/_cwiring.pyx":39 /* "dependency_injector/_cwiring.pyx":39
@ -4073,14 +4129,14 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTH
* *
*/ */
__Pyx_XDECREF(__pyx_r); __Pyx_XDECREF(__pyx_r);
__Pyx_INCREF(__pyx_cur_scope->__pyx_v__patched); __Pyx_INCREF(__pyx_v__patched);
__pyx_r = __pyx_cur_scope->__pyx_v__patched; __pyx_r = __pyx_v__patched;
goto __pyx_L0; goto __pyx_L0;
/* "dependency_injector/_cwiring.pyx":15 /* "dependency_injector/_cwiring.pyx":15
* *
* *
* def _get_sync_patched(fn): # <<<<<<<<<<<<<< * def _get_sync_patched(fn, patched: PatchedCallable): # <<<<<<<<<<<<<<
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): * def _patched(*args, **kwargs):
*/ */
@ -4094,6 +4150,7 @@ static PyObject *__pyx_pf_19dependency_injector_8_cwiring__get_sync_patched(CYTH
__Pyx_AddTraceback("dependency_injector._cwiring._get_sync_patched", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_AddTraceback("dependency_injector._cwiring._get_sync_patched", __pyx_clineno, __pyx_lineno, __pyx_filename);
__pyx_r = NULL; __pyx_r = NULL;
__pyx_L0:; __pyx_L0:;
__Pyx_XDECREF(__pyx_v__patched);
__Pyx_DECREF(((PyObject *)__pyx_cur_scope)); __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
__Pyx_XGIVEREF(__pyx_r); __Pyx_XGIVEREF(__pyx_r);
__Pyx_RefNannyFinishContext(); __Pyx_RefNannyFinishContext();
@ -4125,7 +4182,7 @@ static PyObject *__pyx_pw_19dependency_injector_8_cwiring_3_async_inject(PyObjec
__Pyx_RefNannyDeclarations __Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("_async_inject (wrapper)", 0); __Pyx_RefNannySetupContext("_async_inject (wrapper)", 0);
{ {
static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_fn,&__pyx_n_s_args,&__pyx_n_s_kwargs,&__pyx_n_s_injections_2,&__pyx_n_s_closings,0}; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_fn,&__pyx_n_s_args,&__pyx_n_s_kwargs,&__pyx_n_s_injections,&__pyx_n_s_closings,0};
PyObject* values[5] = {0,0,0,0,0}; PyObject* values[5] = {0,0,0,0,0};
if (unlikely(__pyx_kwds)) { if (unlikely(__pyx_kwds)) {
Py_ssize_t kw_args; Py_ssize_t kw_args;
@ -4163,7 +4220,7 @@ static PyObject *__pyx_pw_19dependency_injector_8_cwiring_3_async_inject(PyObjec
} }
CYTHON_FALLTHROUGH; CYTHON_FALLTHROUGH;
case 3: case 3:
if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_injections_2)) != 0)) kw_args--; if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_injections)) != 0)) kw_args--;
else { else {
__Pyx_RaiseArgtupleInvalid("_async_inject", 1, 5, 5, 3); __PYX_ERR(0, 42, __pyx_L3_error) __Pyx_RaiseArgtupleInvalid("_async_inject", 1, 5, 5, 3); __PYX_ERR(0, 42, __pyx_L3_error)
} }
@ -11430,8 +11487,8 @@ static PyObject *__pyx_tp_new_19dependency_injector_8_cwiring___pyx_scope_struct
static void __pyx_tp_dealloc_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched(PyObject *o) { static void __pyx_tp_dealloc_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched(PyObject *o) {
struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *p = (struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o; struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *p = (struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o;
PyObject_GC_UnTrack(o); PyObject_GC_UnTrack(o);
Py_CLEAR(p->__pyx_v__patched);
Py_CLEAR(p->__pyx_v_fn); Py_CLEAR(p->__pyx_v_fn);
Py_CLEAR(p->__pyx_v_patched);
if (CYTHON_COMPILING_IN_CPYTHON && ((__pyx_freecount_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched < 8) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched)))) { if (CYTHON_COMPILING_IN_CPYTHON && ((__pyx_freecount_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched < 8) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched)))) {
__pyx_freelist_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched[__pyx_freecount_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched++] = ((struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o); __pyx_freelist_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched[__pyx_freecount_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched++] = ((struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o);
} else { } else {
@ -11442,24 +11499,24 @@ static void __pyx_tp_dealloc_19dependency_injector_8_cwiring___pyx_scope_struct_
static int __pyx_tp_traverse_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched(PyObject *o, visitproc v, void *a) { static int __pyx_tp_traverse_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched(PyObject *o, visitproc v, void *a) {
int e; int e;
struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *p = (struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o; struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *p = (struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o;
if (p->__pyx_v__patched) {
e = (*v)(p->__pyx_v__patched, a); if (e) return e;
}
if (p->__pyx_v_fn) { if (p->__pyx_v_fn) {
e = (*v)(p->__pyx_v_fn, a); if (e) return e; e = (*v)(p->__pyx_v_fn, a); if (e) return e;
} }
if (p->__pyx_v_patched) {
e = (*v)(p->__pyx_v_patched, a); if (e) return e;
}
return 0; return 0;
} }
static int __pyx_tp_clear_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched(PyObject *o) { static int __pyx_tp_clear_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched(PyObject *o) {
PyObject* tmp; PyObject* tmp;
struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *p = (struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o; struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *p = (struct __pyx_obj_19dependency_injector_8_cwiring___pyx_scope_struct___get_sync_patched *)o;
tmp = ((PyObject*)p->__pyx_v__patched);
p->__pyx_v__patched = Py_None; Py_INCREF(Py_None);
Py_XDECREF(tmp);
tmp = ((PyObject*)p->__pyx_v_fn); tmp = ((PyObject*)p->__pyx_v_fn);
p->__pyx_v_fn = Py_None; Py_INCREF(Py_None); p->__pyx_v_fn = Py_None; Py_INCREF(Py_None);
Py_XDECREF(tmp); Py_XDECREF(tmp);
tmp = ((PyObject*)p->__pyx_v_patched);
p->__pyx_v_patched = Py_None; Py_INCREF(Py_None);
Py_XDECREF(tmp);
return 0; return 0;
} }
@ -12266,6 +12323,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
{&__pyx_n_s_GeneratorType, __pyx_k_GeneratorType, sizeof(__pyx_k_GeneratorType), 0, 0, 1, 1}, {&__pyx_n_s_GeneratorType, __pyx_k_GeneratorType, sizeof(__pyx_k_GeneratorType), 0, 0, 1, 1},
{&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1},
{&__pyx_n_s_Marker, __pyx_k_Marker, sizeof(__pyx_k_Marker), 0, 0, 1, 1}, {&__pyx_n_s_Marker, __pyx_k_Marker, sizeof(__pyx_k_Marker), 0, 0, 1, 1},
{&__pyx_n_s_PatchedCallable, __pyx_k_PatchedCallable, sizeof(__pyx_k_PatchedCallable), 0, 0, 1, 1},
{&__pyx_n_s_Pyx_CFunc_object____object, __pyx_k_Pyx_CFunc_object____object, sizeof(__pyx_k_Pyx_CFunc_object____object), 0, 0, 1, 1}, {&__pyx_n_s_Pyx_CFunc_object____object, __pyx_k_Pyx_CFunc_object____object, sizeof(__pyx_k_Pyx_CFunc_object____object), 0, 0, 1, 1},
{&__pyx_n_s_Pyx_CFunc_void____object____ob, __pyx_k_Pyx_CFunc_void____object____ob, sizeof(__pyx_k_Pyx_CFunc_void____object____ob), 0, 0, 1, 1}, {&__pyx_n_s_Pyx_CFunc_void____object____ob, __pyx_k_Pyx_CFunc_void____object____ob, sizeof(__pyx_k_Pyx_CFunc_void____object____ob), 0, 0, 1, 1},
{&__pyx_n_s_Pyx_CFunc_void____object____ob_2, __pyx_k_Pyx_CFunc_void____object____ob_2, sizeof(__pyx_k_Pyx_CFunc_void____object____ob_2), 0, 0, 1, 1}, {&__pyx_n_s_Pyx_CFunc_void____object____ob_2, __pyx_k_Pyx_CFunc_void____object____ob_2, sizeof(__pyx_k_Pyx_CFunc_void____object____ob_2), 0, 0, 1, 1},
@ -12312,7 +12370,6 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
{&__pyx_n_s_index, __pyx_k_index, sizeof(__pyx_k_index), 0, 0, 1, 1}, {&__pyx_n_s_index, __pyx_k_index, sizeof(__pyx_k_index), 0, 0, 1, 1},
{&__pyx_n_s_injection, __pyx_k_injection, sizeof(__pyx_k_injection), 0, 0, 1, 1}, {&__pyx_n_s_injection, __pyx_k_injection, sizeof(__pyx_k_injection), 0, 0, 1, 1},
{&__pyx_n_s_injections, __pyx_k_injections, sizeof(__pyx_k_injections), 0, 0, 1, 1}, {&__pyx_n_s_injections, __pyx_k_injections, sizeof(__pyx_k_injections), 0, 0, 1, 1},
{&__pyx_n_s_injections_2, __pyx_k_injections_2, sizeof(__pyx_k_injections_2), 0, 0, 1, 1},
{&__pyx_n_s_inspect, __pyx_k_inspect, sizeof(__pyx_k_inspect), 0, 0, 1, 1}, {&__pyx_n_s_inspect, __pyx_k_inspect, sizeof(__pyx_k_inspect), 0, 0, 1, 1},
{&__pyx_n_s_items, __pyx_k_items, sizeof(__pyx_k_items), 0, 0, 1, 1}, {&__pyx_n_s_items, __pyx_k_items, sizeof(__pyx_k_items), 0, 0, 1, 1},
{&__pyx_n_s_kwargs, __pyx_k_kwargs, sizeof(__pyx_k_kwargs), 0, 0, 1, 1}, {&__pyx_n_s_kwargs, __pyx_k_kwargs, sizeof(__pyx_k_kwargs), 0, 0, 1, 1},
@ -12320,6 +12377,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
{&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1},
{&__pyx_n_s_partial, __pyx_k_partial, sizeof(__pyx_k_partial), 0, 0, 1, 1}, {&__pyx_n_s_partial, __pyx_k_partial, sizeof(__pyx_k_partial), 0, 0, 1, 1},
{&__pyx_n_s_patched, __pyx_k_patched, sizeof(__pyx_k_patched), 0, 0, 1, 1}, {&__pyx_n_s_patched, __pyx_k_patched, sizeof(__pyx_k_patched), 0, 0, 1, 1},
{&__pyx_n_s_patched_2, __pyx_k_patched_2, sizeof(__pyx_k_patched_2), 0, 0, 1, 1},
{&__pyx_n_s_provide, __pyx_k_provide, sizeof(__pyx_k_provide), 0, 0, 1, 1}, {&__pyx_n_s_provide, __pyx_k_provide, sizeof(__pyx_k_provide), 0, 0, 1, 1},
{&__pyx_n_s_provider, __pyx_k_provider, sizeof(__pyx_k_provider), 0, 0, 1, 1}, {&__pyx_n_s_provider, __pyx_k_provider, sizeof(__pyx_k_provider), 0, 0, 1, 1},
{&__pyx_n_s_providers, __pyx_k_providers, sizeof(__pyx_k_providers), 0, 0, 1, 1}, {&__pyx_n_s_providers, __pyx_k_providers, sizeof(__pyx_k_providers), 0, 0, 1, 1},
@ -12358,7 +12416,7 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
__Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
/* "dependency_injector/_cwiring.pyx":17 /* "dependency_injector/_cwiring.pyx":17
* def _get_sync_patched(fn): * def _get_sync_patched(fn, patched: PatchedCallable):
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): # <<<<<<<<<<<<<< * def _patched(*args, **kwargs): # <<<<<<<<<<<<<<
* cdef object result * cdef object result
@ -12367,7 +12425,7 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
__pyx_tuple_ = PyTuple_Pack(6, __pyx_n_s_args, __pyx_n_s_kwargs, __pyx_n_s_result, __pyx_n_s_to_inject, __pyx_n_s_arg_key, __pyx_n_s_provider); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 17, __pyx_L1_error) __pyx_tuple_ = PyTuple_Pack(6, __pyx_n_s_args, __pyx_n_s_kwargs, __pyx_n_s_result, __pyx_n_s_to_inject, __pyx_n_s_arg_key, __pyx_n_s_provider); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 17, __pyx_L1_error)
__Pyx_GOTREF(__pyx_tuple_); __Pyx_GOTREF(__pyx_tuple_);
__Pyx_GIVEREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_);
__pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(0, 0, 6, 0, CO_OPTIMIZED|CO_NEWLOCALS|CO_VARARGS|CO_VARKEYWORDS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_src_dependency_injector__cwiring, __pyx_n_s_patched, 17, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 17, __pyx_L1_error) __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(0, 0, 6, 0, CO_OPTIMIZED|CO_NEWLOCALS|CO_VARARGS|CO_VARKEYWORDS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_src_dependency_injector__cwiring, __pyx_n_s_patched_2, 17, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 17, __pyx_L1_error)
/* "cfunc.to_py":65 /* "cfunc.to_py":65
* @cname("__Pyx_CFunc_void____object____object____object____object___to_py") * @cname("__Pyx_CFunc_void____object____object____object____object___to_py")
@ -12396,14 +12454,14 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
/* "dependency_injector/_cwiring.pyx":15 /* "dependency_injector/_cwiring.pyx":15
* *
* *
* def _get_sync_patched(fn): # <<<<<<<<<<<<<< * def _get_sync_patched(fn, patched: PatchedCallable): # <<<<<<<<<<<<<<
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): * def _patched(*args, **kwargs):
*/ */
__pyx_tuple__14 = PyTuple_Pack(3, __pyx_n_s_fn, __pyx_n_s_patched, __pyx_n_s_patched); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(0, 15, __pyx_L1_error) __pyx_tuple__14 = PyTuple_Pack(4, __pyx_n_s_fn, __pyx_n_s_patched, __pyx_n_s_patched_2, __pyx_n_s_patched_2); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(0, 15, __pyx_L1_error)
__Pyx_GOTREF(__pyx_tuple__14); __Pyx_GOTREF(__pyx_tuple__14);
__Pyx_GIVEREF(__pyx_tuple__14); __Pyx_GIVEREF(__pyx_tuple__14);
__pyx_codeobj__15 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_src_dependency_injector__cwiring, __pyx_n_s_get_sync_patched, 15, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__15)) __PYX_ERR(0, 15, __pyx_L1_error) __pyx_codeobj__15 = (PyObject*)__Pyx_PyCode_New(2, 0, 4, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_src_dependency_injector__cwiring, __pyx_n_s_get_sync_patched, 15, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__15)) __PYX_ERR(0, 15, __pyx_L1_error)
/* "dependency_injector/_cwiring.pyx":42 /* "dependency_injector/_cwiring.pyx":42
* *
@ -12412,7 +12470,7 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
* cdef object result * cdef object result
* cdef dict to_inject * cdef dict to_inject
*/ */
__pyx_tuple__17 = PyTuple_Pack(18, __pyx_n_s_fn, __pyx_n_s_args, __pyx_n_s_kwargs, __pyx_n_s_injections_2, __pyx_n_s_closings, __pyx_n_s_result, __pyx_n_s_to_inject, __pyx_n_s_to_inject_await, __pyx_n_s_to_close_await, __pyx_n_s_arg_key, __pyx_n_s_provider, __pyx_n_s_provide, __pyx_n_s_async_to_inject, __pyx_n_s_injection, __pyx_n_s__16, __pyx_n_s_shutdown, __pyx_n_s_genexpr, __pyx_n_s_genexpr); if (unlikely(!__pyx_tuple__17)) __PYX_ERR(0, 42, __pyx_L1_error) __pyx_tuple__17 = PyTuple_Pack(18, __pyx_n_s_fn, __pyx_n_s_args, __pyx_n_s_kwargs, __pyx_n_s_injections, __pyx_n_s_closings, __pyx_n_s_result, __pyx_n_s_to_inject, __pyx_n_s_to_inject_await, __pyx_n_s_to_close_await, __pyx_n_s_arg_key, __pyx_n_s_provider, __pyx_n_s_provide, __pyx_n_s_async_to_inject, __pyx_n_s_injection, __pyx_n_s__16, __pyx_n_s_shutdown, __pyx_n_s_genexpr, __pyx_n_s_genexpr); if (unlikely(!__pyx_tuple__17)) __PYX_ERR(0, 42, __pyx_L1_error)
__Pyx_GOTREF(__pyx_tuple__17); __Pyx_GOTREF(__pyx_tuple__17);
__Pyx_GIVEREF(__pyx_tuple__17); __Pyx_GIVEREF(__pyx_tuple__17);
__pyx_codeobj__3 = (PyObject*)__Pyx_PyCode_New(5, 0, 18, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__17, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_src_dependency_injector__cwiring, __pyx_n_s_async_inject, 42, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__3)) __PYX_ERR(0, 42, __pyx_L1_error) __pyx_codeobj__3 = (PyObject*)__Pyx_PyCode_New(5, 0, 18, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__17, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_src_dependency_injector__cwiring, __pyx_n_s_async_inject, 42, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__3)) __PYX_ERR(0, 42, __pyx_L1_error)
@ -12994,7 +13052,7 @@ if (!__Pyx_RefNanny) {
* import types * import types
* *
* from . import providers # <<<<<<<<<<<<<< * from . import providers # <<<<<<<<<<<<<<
* from .wiring import _Marker * from .wiring import _Marker, PatchedCallable
* *
*/ */
__pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error) __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)
@ -13014,15 +13072,18 @@ if (!__Pyx_RefNanny) {
/* "dependency_injector/_cwiring.pyx":10 /* "dependency_injector/_cwiring.pyx":10
* *
* from . import providers * from . import providers
* from .wiring import _Marker # <<<<<<<<<<<<<< * from .wiring import _Marker, PatchedCallable # <<<<<<<<<<<<<<
* *
* from .providers cimport Provider * from .providers cimport Provider
*/ */
__pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 10, __pyx_L1_error) __pyx_t_2 = PyList_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 10, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2); __Pyx_GOTREF(__pyx_t_2);
__Pyx_INCREF(__pyx_n_s_Marker); __Pyx_INCREF(__pyx_n_s_Marker);
__Pyx_GIVEREF(__pyx_n_s_Marker); __Pyx_GIVEREF(__pyx_n_s_Marker);
PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_Marker); PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_Marker);
__Pyx_INCREF(__pyx_n_s_PatchedCallable);
__Pyx_GIVEREF(__pyx_n_s_PatchedCallable);
PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_PatchedCallable);
__pyx_t_1 = __Pyx_Import(__pyx_n_s_wiring, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error) __pyx_t_1 = __Pyx_Import(__pyx_n_s_wiring, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
@ -13030,12 +13091,16 @@ if (!__Pyx_RefNanny) {
__Pyx_GOTREF(__pyx_t_2); __Pyx_GOTREF(__pyx_t_2);
if (PyDict_SetItem(__pyx_d, __pyx_n_s_Marker, __pyx_t_2) < 0) __PYX_ERR(0, 10, __pyx_L1_error) if (PyDict_SetItem(__pyx_d, __pyx_n_s_Marker, __pyx_t_2) < 0) __PYX_ERR(0, 10, __pyx_L1_error)
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_PatchedCallable); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 10, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2);
if (PyDict_SetItem(__pyx_d, __pyx_n_s_PatchedCallable, __pyx_t_2) < 0) __PYX_ERR(0, 10, __pyx_L1_error)
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
/* "dependency_injector/_cwiring.pyx":15 /* "dependency_injector/_cwiring.pyx":15
* *
* *
* def _get_sync_patched(fn): # <<<<<<<<<<<<<< * def _get_sync_patched(fn, patched: PatchedCallable): # <<<<<<<<<<<<<<
* @functools.wraps(fn) * @functools.wraps(fn)
* def _patched(*args, **kwargs): * def _patched(*args, **kwargs):
*/ */
@ -13145,6 +13210,148 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
return result; return result;
} }
/* RaiseArgTupleInvalid */
static void __Pyx_RaiseArgtupleInvalid(
const char* func_name,
int exact,
Py_ssize_t num_min,
Py_ssize_t num_max,
Py_ssize_t num_found)
{
Py_ssize_t num_expected;
const char *more_or_less;
if (num_found < num_min) {
num_expected = num_min;
more_or_less = "at least";
} else {
num_expected = num_max;
more_or_less = "at most";
}
if (exact) {
more_or_less = "exactly";
}
PyErr_Format(PyExc_TypeError,
"%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)",
func_name, more_or_less, num_expected,
(num_expected == 1) ? "" : "s", num_found);
}
/* RaiseDoubleKeywords */
static void __Pyx_RaiseDoubleKeywordsError(
const char* func_name,
PyObject* kw_name)
{
PyErr_Format(PyExc_TypeError,
#if PY_MAJOR_VERSION >= 3
"%s() got multiple values for keyword argument '%U'", func_name, kw_name);
#else
"%s() got multiple values for keyword argument '%s'", func_name,
PyString_AsString(kw_name));
#endif
}
/* ParseKeywords */
static int __Pyx_ParseOptionalKeywords(
PyObject *kwds,
PyObject **argnames[],
PyObject *kwds2,
PyObject *values[],
Py_ssize_t num_pos_args,
const char* function_name)
{
PyObject *key = 0, *value = 0;
Py_ssize_t pos = 0;
PyObject*** name;
PyObject*** first_kw_arg = argnames + num_pos_args;
while (PyDict_Next(kwds, &pos, &key, &value)) {
name = first_kw_arg;
while (*name && (**name != key)) name++;
if (*name) {
values[name-argnames] = value;
continue;
}
name = first_kw_arg;
#if PY_MAJOR_VERSION < 3
if (likely(PyString_Check(key))) {
while (*name) {
if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key))
&& _PyString_Eq(**name, key)) {
values[name-argnames] = value;
break;
}
name++;
}
if (*name) continue;
else {
PyObject*** argname = argnames;
while (argname != first_kw_arg) {
if ((**argname == key) || (
(CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key))
&& _PyString_Eq(**argname, key))) {
goto arg_passed_twice;
}
argname++;
}
}
} else
#endif
if (likely(PyUnicode_Check(key))) {
while (*name) {
int cmp = (**name == key) ? 0 :
#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
(__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 :
#endif
PyUnicode_Compare(**name, key);
if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
if (cmp == 0) {
values[name-argnames] = value;
break;
}
name++;
}
if (*name) continue;
else {
PyObject*** argname = argnames;
while (argname != first_kw_arg) {
int cmp = (**argname == key) ? 0 :
#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
(__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 :
#endif
PyUnicode_Compare(**argname, key);
if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
if (cmp == 0) goto arg_passed_twice;
argname++;
}
}
} else
goto invalid_keyword_type;
if (kwds2) {
if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
} else {
goto invalid_keyword;
}
}
return 0;
arg_passed_twice:
__Pyx_RaiseDoubleKeywordsError(function_name, key);
goto bad;
invalid_keyword_type:
PyErr_Format(PyExc_TypeError,
"%.200s() keywords must be strings", function_name);
goto bad;
invalid_keyword:
PyErr_Format(PyExc_TypeError,
#if PY_MAJOR_VERSION < 3
"%.200s() got an unexpected keyword argument '%.200s'",
function_name, PyString_AsString(key));
#else
"%s() got an unexpected keyword argument '%U'",
function_name, key);
#endif
bad:
return -1;
}
/* KeywordStringCheck */ /* KeywordStringCheck */
static int __Pyx_CheckKeywordStrings( static int __Pyx_CheckKeywordStrings(
PyObject *kwdict, PyObject *kwdict,
@ -14284,148 +14491,6 @@ static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qual
return op; return op;
} }
/* RaiseArgTupleInvalid */
static void __Pyx_RaiseArgtupleInvalid(
const char* func_name,
int exact,
Py_ssize_t num_min,
Py_ssize_t num_max,
Py_ssize_t num_found)
{
Py_ssize_t num_expected;
const char *more_or_less;
if (num_found < num_min) {
num_expected = num_min;
more_or_less = "at least";
} else {
num_expected = num_max;
more_or_less = "at most";
}
if (exact) {
more_or_less = "exactly";
}
PyErr_Format(PyExc_TypeError,
"%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)",
func_name, more_or_less, num_expected,
(num_expected == 1) ? "" : "s", num_found);
}
/* RaiseDoubleKeywords */
static void __Pyx_RaiseDoubleKeywordsError(
const char* func_name,
PyObject* kw_name)
{
PyErr_Format(PyExc_TypeError,
#if PY_MAJOR_VERSION >= 3
"%s() got multiple values for keyword argument '%U'", func_name, kw_name);
#else
"%s() got multiple values for keyword argument '%s'", func_name,
PyString_AsString(kw_name));
#endif
}
/* ParseKeywords */
static int __Pyx_ParseOptionalKeywords(
PyObject *kwds,
PyObject **argnames[],
PyObject *kwds2,
PyObject *values[],
Py_ssize_t num_pos_args,
const char* function_name)
{
PyObject *key = 0, *value = 0;
Py_ssize_t pos = 0;
PyObject*** name;
PyObject*** first_kw_arg = argnames + num_pos_args;
while (PyDict_Next(kwds, &pos, &key, &value)) {
name = first_kw_arg;
while (*name && (**name != key)) name++;
if (*name) {
values[name-argnames] = value;
continue;
}
name = first_kw_arg;
#if PY_MAJOR_VERSION < 3
if (likely(PyString_Check(key))) {
while (*name) {
if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key))
&& _PyString_Eq(**name, key)) {
values[name-argnames] = value;
break;
}
name++;
}
if (*name) continue;
else {
PyObject*** argname = argnames;
while (argname != first_kw_arg) {
if ((**argname == key) || (
(CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key))
&& _PyString_Eq(**argname, key))) {
goto arg_passed_twice;
}
argname++;
}
}
} else
#endif
if (likely(PyUnicode_Check(key))) {
while (*name) {
int cmp = (**name == key) ? 0 :
#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
(__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 :
#endif
PyUnicode_Compare(**name, key);
if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
if (cmp == 0) {
values[name-argnames] = value;
break;
}
name++;
}
if (*name) continue;
else {
PyObject*** argname = argnames;
while (argname != first_kw_arg) {
int cmp = (**argname == key) ? 0 :
#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
(__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 :
#endif
PyUnicode_Compare(**argname, key);
if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
if (cmp == 0) goto arg_passed_twice;
argname++;
}
}
} else
goto invalid_keyword_type;
if (kwds2) {
if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
} else {
goto invalid_keyword;
}
}
return 0;
arg_passed_twice:
__Pyx_RaiseDoubleKeywordsError(function_name, key);
goto bad;
invalid_keyword_type:
PyErr_Format(PyExc_TypeError,
"%.200s() keywords must be strings", function_name);
goto bad;
invalid_keyword:
PyErr_Format(PyExc_TypeError,
#if PY_MAJOR_VERSION < 3
"%.200s() got an unexpected keyword argument '%.200s'",
function_name, PyString_AsString(key));
#else
"%s() got an unexpected keyword argument '%U'",
function_name, key);
#endif
bad:
return -1;
}
/* ArgTypeTest */ /* ArgTypeTest */
static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact)
{ {

View File

@ -7,12 +7,12 @@ import inspect
import types import types
from . import providers from . import providers
from .wiring import _Marker from .wiring import _Marker, PatchedCallable
from .providers cimport Provider from .providers cimport Provider
def _get_sync_patched(fn): def _get_sync_patched(fn, patched: PatchedCallable):
@functools.wraps(fn) @functools.wraps(fn)
def _patched(*args, **kwargs): def _patched(*args, **kwargs):
cdef object result cdef object result
@ -21,14 +21,14 @@ def _get_sync_patched(fn):
cdef Provider provider cdef Provider provider
to_inject = kwargs.copy() to_inject = kwargs.copy()
for arg_key, provider in _patched.__injections__.items(): for arg_key, provider in patched.injections.items():
if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker): if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
to_inject[arg_key] = provider() to_inject[arg_key] = provider()
result = fn(*args, **to_inject) result = fn(*args, **to_inject)
if _patched.__closing__: if patched.closing:
for arg_key, provider in _patched.__closing__.items(): for arg_key, provider in patched.closing.items():
if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker): if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker):
continue continue
if not isinstance(provider, providers.Resource): if not isinstance(provider, providers.Resource):

View File

@ -1,4 +1,5 @@
"""Wiring module.""" """Wiring module."""
import functools import functools
import inspect import inspect
import importlib import importlib
@ -91,20 +92,26 @@ Container = Any
class PatchedRegistry: class PatchedRegistry:
def __init__(self): def __init__(self) -> None:
self._callables: Set[Callable[..., Any]] = set() self._callables: Dict[Callable[..., Any], "PatchedCallable"] = {}
self._attributes: Set[PatchedAttribute] = set() self._attributes: Set[PatchedAttribute] = set()
def add_callable(self, patched: Callable[..., Any]) -> None: def register_callable(self, patched: "PatchedCallable") -> None:
self._callables.add(patched) self._callables[patched.patched] = patched
def get_callables_from_module(self, module: ModuleType) -> Iterator[Callable[..., Any]]: def get_callables_from_module(self, module: ModuleType) -> Iterator[Callable[..., Any]]:
for patched in self._callables: for patched_callable in self._callables.values():
if patched.__module__ != module.__name__: if not patched_callable.is_in_module(module):
continue continue
yield patched yield patched_callable.patched
def add_attribute(self, patched: "PatchedAttribute"): def get_callable(self, fn: Callable[..., Any]) -> "PatchedCallable":
return self._callables.get(fn)
def has_callable(self, fn: Callable[..., Any]) -> bool:
return fn in self._callables
def register_attribute(self, patched: "PatchedAttribute") -> None:
self._attributes.add(patched) self._attributes.add(patched)
def get_attributes_from_module(self, module: ModuleType) -> Iterator["PatchedAttribute"]: def get_attributes_from_module(self, module: ModuleType) -> Iterator["PatchedAttribute"]:
@ -113,16 +120,69 @@ class PatchedRegistry:
continue continue
yield attribute yield attribute
def clear_module_attributes(self, module: ModuleType): def clear_module_attributes(self, module: ModuleType) -> None:
for attribute in self._attributes.copy(): for attribute in self._attributes.copy():
if not attribute.is_in_module(module): if not attribute.is_in_module(module):
continue continue
self._attributes.remove(attribute) self._attributes.remove(attribute)
class PatchedCallable:
__slots__ = (
"patched",
"original",
"reference_injections",
"injections",
"reference_closing",
"closing",
)
def __init__(
self,
patched: Optional[Callable[..., Any]] = None,
original: Optional[Callable[..., Any]] = None,
reference_injections: Optional[Dict[Any, Any]] = None,
reference_closing: Optional[Dict[Any, Any]] = None,
) -> None:
self.patched = patched
self.original = original
if reference_injections is None:
reference_injections = {}
self.reference_injections: Dict[Any, Any] = reference_injections.copy()
self.injections: Dict[Any, Any] = {}
if reference_closing is None:
reference_closing = {}
self.reference_closing: Dict[Any, Any] = reference_closing.copy()
self.closing: Dict[Any, Any] = {}
def is_in_module(self, module: ModuleType) -> bool:
if self.patched is None:
return False
return self.patched.__module__ == module.__name__
def add_injection(self, kwarg: Any, injection: Any) -> None:
self.injections[kwarg] = injection
def add_closing(self, kwarg: Any, injection: Any) -> None:
self.closing[kwarg] = injection
def unwind_injections(self) -> None:
self.injections = {}
self.closing = {}
class PatchedAttribute: class PatchedAttribute:
def __init__(self, member: Any, name: str, marker: "_Marker"): __slots__ = (
"member",
"name",
"marker",
)
def __init__(self, member: Any, name: str, marker: "_Marker") -> None:
self.member = member self.member = member
self.name = name self.name = name
self.marker = marker self.marker = marker
@ -142,7 +202,7 @@ class ProvidersMap:
CONTAINER_STRING_ID = "<container>" CONTAINER_STRING_ID = "<container>"
def __init__(self, container): def __init__(self, container) -> None:
self._container = container self._container = container
self._map = self._create_providers_map( self._map = self._create_providers_map(
current_container=container, current_container=container,
@ -398,7 +458,6 @@ def inject(fn: F) -> F:
"""Decorate callable with injecting decorator.""" """Decorate callable with injecting decorator."""
reference_injections, reference_closing = _fetch_reference_injections(fn) reference_injections, reference_closing = _fetch_reference_injections(fn)
patched = _get_patched(fn, reference_injections, reference_closing) patched = _get_patched(fn, reference_injections, reference_closing)
_patched_registry.add_callable(patched)
return cast(F, patched) return cast(F, patched)
@ -413,7 +472,6 @@ def _patch_fn(
if not reference_injections: if not reference_injections:
return return
fn = _get_patched(fn, reference_injections, reference_closing) fn = _get_patched(fn, reference_injections, reference_closing)
_patched_registry.add_callable(fn)
_bind_injections(fn, providers_map) _bind_injections(fn, providers_map)
@ -439,7 +497,6 @@ def _patch_method(
if not reference_injections: if not reference_injections:
return return
fn = _get_patched(fn, reference_injections, reference_closing) fn = _get_patched(fn, reference_injections, reference_closing)
_patched_registry.add_callable(fn)
_bind_injections(fn, providers_map) _bind_injections(fn, providers_map)
@ -476,7 +533,7 @@ def _patch_attribute(
if provider is None: if provider is None:
return return
_patched_registry.add_attribute(PatchedAttribute(member, name, marker)) _patched_registry.register_attribute(PatchedAttribute(member, name, marker))
if isinstance(marker, Provide): if isinstance(marker, Provide):
instance = provider() instance = provider()
@ -537,27 +594,33 @@ def _fetch_reference_injections( # noqa: C901
def _bind_injections(fn: Callable[..., Any], providers_map: ProvidersMap) -> None: def _bind_injections(fn: Callable[..., Any], providers_map: ProvidersMap) -> None:
for injection, marker in fn.__reference_injections__.items(): patched_callable = _patched_registry.get_callable(fn)
if patched_callable is None:
return
for injection, marker in patched_callable.reference_injections.items():
provider = providers_map.resolve_provider(marker.provider, marker.modifier) provider = providers_map.resolve_provider(marker.provider, marker.modifier)
if provider is None: if provider is None:
continue continue
if isinstance(marker, Provide): if isinstance(marker, Provide):
fn.__injections__[injection] = provider patched_callable.add_injection(injection, provider)
elif isinstance(marker, Provider): elif isinstance(marker, Provider):
if isinstance(provider, providers.Delegate): if isinstance(provider, providers.Delegate):
fn.__injections__[injection] = provider patched_callable.add_injection(injection, provider)
else: else:
fn.__injections__[injection] = provider.provider patched_callable.add_injection(injection, provider.provider)
if injection in fn.__reference_closing__: if injection in patched_callable.reference_closing:
fn.__closing__[injection] = provider patched_callable.add_closing(injection, provider)
def _unbind_injections(fn: Callable[..., Any]) -> None: def _unbind_injections(fn: Callable[..., Any]) -> None:
fn.__injections__ = {} patched_callable = _patched_registry.get_callable(fn)
fn.__closing__ = {} if patched_callable is None:
return
patched_callable.unwind_injections()
def _fetch_modules(package): def _fetch_modules(package):
@ -573,26 +636,32 @@ def _fetch_modules(package):
return modules return modules
def _is_method(member): def _is_method(member) -> bool:
return inspect.ismethod(member) or inspect.isfunction(member) return inspect.ismethod(member) or inspect.isfunction(member)
def _is_marker(member): def _is_marker(member) -> bool:
return isinstance(member, _Marker) return isinstance(member, _Marker)
def _get_patched(fn, reference_injections, reference_closing): def _get_patched(
if inspect.iscoroutinefunction(fn): fn: F,
patched = _get_async_patched(fn) reference_injections: Dict[Any, Any],
else: reference_closing: Dict[Any, Any],
patched = _get_sync_patched(fn) ) -> F:
patched_object = PatchedCallable(
original=fn,
reference_injections=reference_injections,
reference_closing=reference_closing,
)
patched.__wired__ = True if inspect.iscoroutinefunction(fn):
patched.__original__ = fn patched = _get_async_patched(fn, patched_object)
patched.__injections__ = {} else:
patched.__reference_injections__ = reference_injections patched = _get_sync_patched(fn, patched_object)
patched.__closing__ = {}
patched.__reference_closing__ = reference_closing patched_object.patched = patched
_patched_registry.register_callable(patched_object)
return patched return patched
@ -601,8 +670,8 @@ def _is_fastapi_depends(param: Any) -> bool:
return fastapi and isinstance(param, fastapi.params.Depends) return fastapi and isinstance(param, fastapi.params.Depends)
def _is_patched(fn): def _is_patched(fn) -> bool:
return getattr(fn, "__wired__", False) is True return _patched_registry.has_callable(fn)
def _is_declarative_container(instance: Any) -> bool: def _is_declarative_container(instance: Any) -> bool:
@ -630,7 +699,7 @@ class Modifier:
class TypeModifier(Modifier): class TypeModifier(Modifier):
def __init__(self, type_: Type): def __init__(self, type_: Type) -> None:
self.type_ = type_ self.type_ = type_
def modify( def modify(
@ -658,7 +727,7 @@ def as_(type_: Type) -> TypeModifier:
class RequiredModifier(Modifier): class RequiredModifier(Modifier):
def __init__(self): def __init__(self) -> None:
self.type_modifier = None self.type_modifier = None
def as_int(self) -> "RequiredModifier": def as_int(self) -> "RequiredModifier":
@ -714,7 +783,7 @@ class ProvidedInstance(Modifier):
TYPE_ITEM = "item" TYPE_ITEM = "item"
TYPE_CALL = "call" TYPE_CALL = "call"
def __init__(self): def __init__(self) -> None:
self.segments = [] self.segments = []
def __getattr__(self, item): def __getattr__(self, item):
@ -799,32 +868,32 @@ class AutoLoader:
Automatically wire containers when modules are imported. Automatically wire containers when modules are imported.
""" """
def __init__(self): def __init__(self) -> None:
self.containers = [] self.containers = []
self._path_hook = None self._path_hook = None
def register_containers(self, *containers): def register_containers(self, *containers) -> None:
self.containers.extend(containers) self.containers.extend(containers)
if not self.installed: if not self.installed:
self.install() self.install()
def unregister_containers(self, *containers): def unregister_containers(self, *containers) -> None:
for container in containers: for container in containers:
self.containers.remove(container) self.containers.remove(container)
if not self.containers: if not self.containers:
self.uninstall() self.uninstall()
def wire_module(self, module): def wire_module(self, module) -> None:
for container in self.containers: for container in self.containers:
container.wire(modules=[module]) container.wire(modules=[module])
@property @property
def installed(self): def installed(self) -> bool:
return self._path_hook in sys.path_hooks return self._path_hook in sys.path_hooks
def install(self): def install(self) -> None:
if self.installed: if self.installed:
return return
@ -855,7 +924,7 @@ class AutoLoader:
sys.path_importer_cache.clear() sys.path_importer_cache.clear()
importlib.invalidate_caches() importlib.invalidate_caches()
def uninstall(self): def uninstall(self) -> None:
if not self.installed: if not self.installed:
return return
@ -900,14 +969,14 @@ from ._cwiring import _async_inject # noqa
# Wiring uses the following Python wrapper because there is # Wiring uses the following Python wrapper because there is
# no possibility to compile a first-type citizen coroutine in Cython. # no possibility to compile a first-type citizen coroutine in Cython.
def _get_async_patched(fn): def _get_async_patched(fn: F, patched: PatchedCallable) -> F:
@functools.wraps(fn) @functools.wraps(fn)
async def _patched(*args, **kwargs): async def _patched(*args, **kwargs):
return await _async_inject( return await _async_inject(
fn, fn,
args, args,
kwargs, kwargs,
_patched.__injections__, patched.injections,
_patched.__closing__, patched.closing,
) )
return _patched return _patched

View File

@ -0,0 +1,49 @@
"""Test that wiring works properly with @functools.wraps decorator.
See issue for details: https://github.com/ets-labs/python-dependency-injector/issues/454
"""
import functools
from dependency_injector.wiring import inject, Provide
from pytest import fixture
from samples.wiring.container import Container
@fixture
def container():
container = Container()
yield container
container.unwire()
def decorator1(func):
@functools.wraps(func)
@inject
def wrapper(value1: int = Provide[Container.config.value1]):
result = func()
return result + value1
return wrapper
def decorator2(func):
@functools.wraps(func)
@inject
def wrapper(value2: int = Provide[Container.config.value2]):
result = func()
return result + value2
return wrapper
@decorator1
@decorator2
def sample():
return 2
def test_wraps(container: Container):
container.wire(modules=[__name__])
container.config.from_dict({"value1": 42, "value2": 15})
assert sample() == 2 + 42 + 15