mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-24 18:43:58 +03:00
Add isfuture() and iscoroutine() optimization
This commit is contained in:
parent
f0c55cda22
commit
ae1d00d107
4
setup.py
4
setup.py
|
@ -58,6 +58,10 @@ setup(name="dependency-injector",
|
||||||
["src/dependency_injector/providers.c"],
|
["src/dependency_injector/providers.c"],
|
||||||
define_macros=list(defined_macros.items()),
|
define_macros=list(defined_macros.items()),
|
||||||
extra_compile_args=["-O2"]),
|
extra_compile_args=["-O2"]),
|
||||||
|
Extension("dependency_injector._cwiring",
|
||||||
|
["src/dependency_injector/_cwiring.c"],
|
||||||
|
define_macros=list(defined_macros.items()),
|
||||||
|
extra_compile_args=["-O2"]),
|
||||||
],
|
],
|
||||||
install_requires=requirements,
|
install_requires=requirements,
|
||||||
extras_require={
|
extras_require={
|
||||||
|
|
5971
src/dependency_injector/_cwiring.c
Normal file
5971
src/dependency_injector/_cwiring.c
Normal file
File diff suppressed because it is too large
Load Diff
1
src/dependency_injector/_cwiring.pxd
Normal file
1
src/dependency_injector/_cwiring.pxd
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"""Wiring optimizations module."""
|
51
src/dependency_injector/_cwiring.pyx
Normal file
51
src/dependency_injector/_cwiring.pyx
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
"""Wiring optimizations module."""
|
||||||
|
|
||||||
|
import copy
|
||||||
|
import functools
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
|
from . import providers
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info[0] == 3: # pragma: no cover
|
||||||
|
CLASS_TYPES = (type,)
|
||||||
|
else: # pragma: no cover
|
||||||
|
CLASS_TYPES = (type, types.ClassType)
|
||||||
|
|
||||||
|
copy._deepcopy_dispatch[types.MethodType] = \
|
||||||
|
lambda obj, memo: type(obj)(obj.im_func,
|
||||||
|
copy.deepcopy(obj.im_self, memo),
|
||||||
|
obj.im_class)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sync_patched(fn):
|
||||||
|
@functools.wraps(fn)
|
||||||
|
def _patched(*args, **kwargs):
|
||||||
|
cdef dict to_inject = kwargs.copy()
|
||||||
|
for injection, provider in _patched.__injections__.items():
|
||||||
|
if injection not in kwargs \
|
||||||
|
or _is_fastapi_default_arg_injection(injection, kwargs):
|
||||||
|
to_inject[injection] = provider()
|
||||||
|
|
||||||
|
result = fn(*args, **to_inject)
|
||||||
|
|
||||||
|
for injection, provider in _patched.__closing__.items():
|
||||||
|
if injection in kwargs \
|
||||||
|
and not _is_fastapi_default_arg_injection(injection, kwargs):
|
||||||
|
continue
|
||||||
|
if not isinstance(provider, providers.Resource):
|
||||||
|
continue
|
||||||
|
provider.shutdown()
|
||||||
|
|
||||||
|
return result
|
||||||
|
return _patched
|
||||||
|
|
||||||
|
|
||||||
|
cdef bint _is_fastapi_default_arg_injection(object injection, dict kwargs):
|
||||||
|
"""Check if injection is FastAPI injection of the default argument."""
|
||||||
|
return injection in kwargs and _is_marker(kwargs[injection])
|
||||||
|
|
||||||
|
|
||||||
|
cdef bint _is_marker(object instance):
|
||||||
|
return getattr(instance, "__IS_MARKER__", False) is True
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -10,6 +10,10 @@ import functools
|
||||||
cimport cython
|
cimport cython
|
||||||
|
|
||||||
|
|
||||||
|
cdef set __iscoroutine_typecache
|
||||||
|
cdef tuple __COROUTINE_TYPES
|
||||||
|
|
||||||
|
|
||||||
# Base providers
|
# Base providers
|
||||||
cdef class Provider(object):
|
cdef class Provider(object):
|
||||||
cdef tuple __overridden
|
cdef tuple __overridden
|
||||||
|
@ -551,19 +555,19 @@ cdef inline object __call(
|
||||||
tuple injection_kwargs,
|
tuple injection_kwargs,
|
||||||
int injection_kwargs_len,
|
int injection_kwargs_len,
|
||||||
):
|
):
|
||||||
args = __provide_positional_args(
|
cdef object args = __provide_positional_args(
|
||||||
context_args,
|
context_args,
|
||||||
injection_args,
|
injection_args,
|
||||||
injection_args_len,
|
injection_args_len,
|
||||||
)
|
)
|
||||||
kwargs = __provide_keyword_args(
|
cdef object kwargs = __provide_keyword_args(
|
||||||
context_kwargs,
|
context_kwargs,
|
||||||
injection_kwargs,
|
injection_kwargs,
|
||||||
injection_kwargs_len,
|
injection_kwargs_len,
|
||||||
)
|
)
|
||||||
|
|
||||||
is_future_args = __is_future_or_coroutine(args)
|
cdef bint is_future_args = __is_future_or_coroutine(args)
|
||||||
is_future_kwargs = __is_future_or_coroutine(kwargs)
|
cdef bint is_future_kwargs = __is_future_or_coroutine(kwargs)
|
||||||
|
|
||||||
if is_future_args or is_future_kwargs:
|
if is_future_args or is_future_kwargs:
|
||||||
future_args = args if is_future_args else __future_result(args)
|
future_args = args if is_future_args else __future_result(args)
|
||||||
|
@ -643,9 +647,26 @@ cdef inline object __factory_call(Factory self, tuple args, dict kwargs):
|
||||||
|
|
||||||
|
|
||||||
cdef inline bint __is_future_or_coroutine(object instance):
|
cdef inline bint __is_future_or_coroutine(object instance):
|
||||||
if asyncio is None:
|
return __isfuture(instance) or __iscoroutine(instance)
|
||||||
|
|
||||||
|
|
||||||
|
cdef inline bint __isfuture(object obj):
|
||||||
|
return hasattr(obj.__class__, "_asyncio_future_blocking") and obj._asyncio_future_blocking is not None
|
||||||
|
|
||||||
|
|
||||||
|
cdef inline bint __iscoroutine(object obj):
|
||||||
|
if type(obj) in __iscoroutine_typecache:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if isinstance(obj, __COROUTINE_TYPES):
|
||||||
|
# Just in case we don't want to cache more than 100
|
||||||
|
# positive types. That shouldn't ever happen, unless
|
||||||
|
# someone stressing the system on purpose.
|
||||||
|
if len(__iscoroutine_typecache) < 100:
|
||||||
|
__iscoroutine_typecache.add(type(obj))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
return False
|
return False
|
||||||
return asyncio.isfuture(instance) or asyncio.iscoroutine(instance)
|
|
||||||
|
|
||||||
|
|
||||||
cdef inline object __future_result(object instance):
|
cdef inline object __future_result(object instance):
|
||||||
|
|
|
@ -145,6 +145,9 @@ cdef int ASYNC_MODE_UNDEFINED = 0
|
||||||
cdef int ASYNC_MODE_ENABLED = 1
|
cdef int ASYNC_MODE_ENABLED = 1
|
||||||
cdef int ASYNC_MODE_DISABLED = 2
|
cdef int ASYNC_MODE_DISABLED = 2
|
||||||
|
|
||||||
|
cdef set __iscoroutine_typecache = set()
|
||||||
|
cdef tuple __COROUTINE_TYPES = asyncio.coroutines._COROUTINE_TYPES if asyncio else tuple()
|
||||||
|
|
||||||
|
|
||||||
cdef class Provider(object):
|
cdef class Provider(object):
|
||||||
"""Base provider class.
|
"""Base provider class.
|
||||||
|
@ -220,13 +223,13 @@ cdef class Provider(object):
|
||||||
else:
|
else:
|
||||||
result = self._provide(args, kwargs)
|
result = self._provide(args, kwargs)
|
||||||
|
|
||||||
if self.is_async_mode_disabled():
|
if self.__async_mode == ASYNC_MODE_DISABLED:
|
||||||
return result
|
return result
|
||||||
elif self.is_async_mode_enabled():
|
elif self.__async_mode == ASYNC_MODE_ENABLED:
|
||||||
if __is_future_or_coroutine(result):
|
if __is_future_or_coroutine(result):
|
||||||
return result
|
return result
|
||||||
return __future_result(result)
|
return __future_result(result)
|
||||||
elif self.is_async_mode_undefined():
|
elif self.__async_mode == ASYNC_MODE_UNDEFINED:
|
||||||
if __is_future_or_coroutine(result):
|
if __is_future_or_coroutine(result):
|
||||||
self.enable_async_mode()
|
self.enable_async_mode()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -600,27 +600,29 @@ def _get_patched(fn, reference_injections, reference_closing):
|
||||||
return patched
|
return patched
|
||||||
|
|
||||||
|
|
||||||
def _get_sync_patched(fn):
|
from ._cwiring import _get_sync_patched
|
||||||
@functools.wraps(fn)
|
|
||||||
def _patched(*args, **kwargs):
|
|
||||||
to_inject = kwargs.copy()
|
|
||||||
for injection, provider in _patched.__injections__.items():
|
|
||||||
if injection not in kwargs \
|
|
||||||
or _is_fastapi_default_arg_injection(injection, kwargs):
|
|
||||||
to_inject[injection] = provider()
|
|
||||||
|
|
||||||
result = fn(*args, **to_inject)
|
# def _get_sync_patched(fn):
|
||||||
|
# @functools.wraps(fn)
|
||||||
for injection, provider in _patched.__closing__.items():
|
# def _patched(*args, **kwargs):
|
||||||
if injection in kwargs \
|
# to_inject = kwargs.copy()
|
||||||
and not _is_fastapi_default_arg_injection(injection, kwargs):
|
# for injection, provider in _patched.__injections__.items():
|
||||||
continue
|
# if injection not in kwargs \
|
||||||
if not isinstance(provider, providers.Resource):
|
# or _is_fastapi_default_arg_injection(injection, kwargs):
|
||||||
continue
|
# to_inject[injection] = provider()
|
||||||
provider.shutdown()
|
#
|
||||||
|
# result = fn(*args, **to_inject)
|
||||||
return result
|
#
|
||||||
return _patched
|
# for injection, provider in _patched.__closing__.items():
|
||||||
|
# if injection in kwargs \
|
||||||
|
# and not _is_fastapi_default_arg_injection(injection, kwargs):
|
||||||
|
# continue
|
||||||
|
# if not isinstance(provider, providers.Resource):
|
||||||
|
# continue
|
||||||
|
# provider.shutdown()
|
||||||
|
#
|
||||||
|
# return result
|
||||||
|
# return _patched
|
||||||
|
|
||||||
|
|
||||||
def _get_async_patched(fn):
|
def _get_async_patched(fn):
|
||||||
|
@ -828,6 +830,8 @@ class ClassGetItemMeta(GenericMeta):
|
||||||
|
|
||||||
class _Marker(Generic[T], metaclass=ClassGetItemMeta):
|
class _Marker(Generic[T], metaclass=ClassGetItemMeta):
|
||||||
|
|
||||||
|
__IS_MARKER__ = True
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: Union[providers.Provider, Container, str],
|
provider: Union[providers.Provider, Container, str],
|
||||||
|
|
Loading…
Reference in New Issue
Block a user