mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 09:57:37 +03:00 
			
		
		
		
	Optimization r1 (#571)
* Add isfuture() and iscoroutine() optimization * Apply async mode optimization * Wiring changes * Add optimization for wiring of async coroutines * Remove unused imports * Update changelog * Refactor async mode checks
This commit is contained in:
		
							parent
							
								
									f0c55cda22
								
							
						
					
					
						commit
						77b5cdebd3
					
				| 
						 | 
					@ -9,6 +9,7 @@ follows `Semantic versioning`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Develop
 | 
					Develop
 | 
				
			||||||
-------
 | 
					-------
 | 
				
			||||||
 | 
					- Optimize synchronous and asynchronous injections and wiring from x1.5 to x7 times depending on the use case.
 | 
				
			||||||
- Fix bug `#569 <https://github.com/ets-labs/python-dependency-injector/issues/569>`_:
 | 
					- Fix bug `#569 <https://github.com/ets-labs/python-dependency-injector/issues/569>`_:
 | 
				
			||||||
  "numpy.typing.NDArray breaks wiring". Thanks to
 | 
					  "numpy.typing.NDArray breaks wiring". Thanks to
 | 
				
			||||||
  `@VKFisher (Vlad Fisher) <https://github.com/VKFisher>`_ for reporting the issue and providing a fix.
 | 
					  `@VKFisher (Vlad Fisher) <https://github.com/VKFisher>`_ for reporting the issue and providing a fix.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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={
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										9381
									
								
								src/dependency_injector/_cwiring.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9381
									
								
								src/dependency_injector/_cwiring.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										88
									
								
								src/dependency_injector/_cwiring.pyx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/dependency_injector/_cwiring.pyx
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,88 @@
 | 
				
			||||||
 | 
					"""Wiring optimizations module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import asyncio
 | 
				
			||||||
 | 
					import collections.abc
 | 
				
			||||||
 | 
					import functools
 | 
				
			||||||
 | 
					import inspect
 | 
				
			||||||
 | 
					import types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from . import providers
 | 
				
			||||||
 | 
					from .wiring import _Marker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _get_sync_patched(fn):
 | 
				
			||||||
 | 
					    @functools.wraps(fn)
 | 
				
			||||||
 | 
					    def _patched(*args, **kwargs):
 | 
				
			||||||
 | 
					        cdef object result
 | 
				
			||||||
 | 
					        cdef dict to_inject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        to_inject = kwargs.copy()
 | 
				
			||||||
 | 
					        for injection, provider in _patched.__injections__.items():
 | 
				
			||||||
 | 
					            if injection not in kwargs or isinstance(kwargs[injection], _Marker):
 | 
				
			||||||
 | 
					                to_inject[injection] = provider()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = fn(*args, **to_inject)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if _patched.__closing__:
 | 
				
			||||||
 | 
					            for injection, provider in _patched.__closing__.items():
 | 
				
			||||||
 | 
					                if injection in kwargs and not isinstance(kwargs[injection], _Marker):
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                if not isinstance(provider, providers.Resource):
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                provider.shutdown()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    return _patched
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _get_async_patched(fn):
 | 
				
			||||||
 | 
					    @functools.wraps(fn)
 | 
				
			||||||
 | 
					    async def _patched(*args, **kwargs):
 | 
				
			||||||
 | 
					        cdef object result
 | 
				
			||||||
 | 
					        cdef dict to_inject
 | 
				
			||||||
 | 
					        cdef list to_inject_await = []
 | 
				
			||||||
 | 
					        cdef list to_close_await = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        to_inject = kwargs.copy()
 | 
				
			||||||
 | 
					        for injection, provider in _patched.__injections__.items():
 | 
				
			||||||
 | 
					            if injection not in kwargs or isinstance(kwargs[injection], _Marker):
 | 
				
			||||||
 | 
					                provide = provider()
 | 
				
			||||||
 | 
					                if _isawaitable(provide):
 | 
				
			||||||
 | 
					                    to_inject_await.append((injection, provide))
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    to_inject[injection] = provide
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if to_inject_await:
 | 
				
			||||||
 | 
					            async_to_inject = await asyncio.gather(*(provide for _, provide in to_inject_await))
 | 
				
			||||||
 | 
					            for provide, (injection, _) in zip(async_to_inject, to_inject_await):
 | 
				
			||||||
 | 
					                to_inject[injection] = provide
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = await fn(*args, **to_inject)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if _patched.__closing__:
 | 
				
			||||||
 | 
					            for injection, provider in _patched.__closing__.items():
 | 
				
			||||||
 | 
					                if injection in kwargs \
 | 
				
			||||||
 | 
					                        and isinstance(kwargs[injection], _Marker):
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                if not isinstance(provider, providers.Resource):
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                shutdown = provider.shutdown()
 | 
				
			||||||
 | 
					                if _isawaitable(shutdown):
 | 
				
			||||||
 | 
					                    to_close_await.append(shutdown)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await asyncio.gather(*to_close_await)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Hotfix for iscoroutinefunction() for Cython < 3.0.0; can be removed after migration to Cython 3.0.0+
 | 
				
			||||||
 | 
					    _patched._is_coroutine = asyncio.coroutines._is_coroutine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return _patched
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cdef bint _isawaitable(object instance):
 | 
				
			||||||
 | 
					    """Return true if object can be passed to an ``await`` expression."""
 | 
				
			||||||
 | 
					    return (isinstance(instance, types.CoroutineType) or
 | 
				
			||||||
 | 
					            isinstance(instance, types.GeneratorType) and
 | 
				
			||||||
 | 
					            bool(instance.gi_code.co_flags & inspect.CO_ITERABLE_COROUTINE) or
 | 
				
			||||||
 | 
					            isinstance(instance, collections.abc.Awaitable))
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -10,6 +10,14 @@ import functools
 | 
				
			||||||
cimport cython
 | 
					cimport cython
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cdef int ASYNC_MODE_UNDEFINED
 | 
				
			||||||
 | 
					cdef int ASYNC_MODE_ENABLED
 | 
				
			||||||
 | 
					cdef int ASYNC_MODE_DISABLED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
| 
						 | 
					@ -383,11 +391,13 @@ cdef inline object __provide_positional_args(
 | 
				
			||||||
        tuple args,
 | 
					        tuple args,
 | 
				
			||||||
        tuple inj_args,
 | 
					        tuple inj_args,
 | 
				
			||||||
        int inj_args_len,
 | 
					        int inj_args_len,
 | 
				
			||||||
 | 
					        int async_mode,
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    cdef int index
 | 
					    cdef int index
 | 
				
			||||||
    cdef list positional_args = []
 | 
					    cdef list positional_args = []
 | 
				
			||||||
    cdef list future_args = []
 | 
					    cdef list future_args = []
 | 
				
			||||||
    cdef PositionalInjection injection
 | 
					    cdef PositionalInjection injection
 | 
				
			||||||
 | 
					    cdef object value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if inj_args_len == 0:
 | 
					    if inj_args_len == 0:
 | 
				
			||||||
        return args
 | 
					        return args
 | 
				
			||||||
| 
						 | 
					@ -397,7 +407,7 @@ cdef inline object __provide_positional_args(
 | 
				
			||||||
        value = __get_value(injection)
 | 
					        value = __get_value(injection)
 | 
				
			||||||
        positional_args.append(value)
 | 
					        positional_args.append(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if __is_future_or_coroutine(value):
 | 
					        if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
 | 
				
			||||||
            future_args.append((index, value))
 | 
					            future_args.append((index, value))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    positional_args.extend(args)
 | 
					    positional_args.extend(args)
 | 
				
			||||||
| 
						 | 
					@ -414,6 +424,7 @@ cdef inline object __provide_keyword_args(
 | 
				
			||||||
        dict kwargs,
 | 
					        dict kwargs,
 | 
				
			||||||
        tuple inj_kwargs,
 | 
					        tuple inj_kwargs,
 | 
				
			||||||
        int inj_kwargs_len,
 | 
					        int inj_kwargs_len,
 | 
				
			||||||
 | 
					        int async_mode,
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    cdef int index
 | 
					    cdef int index
 | 
				
			||||||
    cdef object name
 | 
					    cdef object name
 | 
				
			||||||
| 
						 | 
					@ -428,7 +439,7 @@ cdef inline object __provide_keyword_args(
 | 
				
			||||||
            name = __get_name(kw_injection)
 | 
					            name = __get_name(kw_injection)
 | 
				
			||||||
            value = __get_value(kw_injection)
 | 
					            value = __get_value(kw_injection)
 | 
				
			||||||
            kwargs[name] = value
 | 
					            kwargs[name] = value
 | 
				
			||||||
            if __is_future_or_coroutine(value):
 | 
					            if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
 | 
				
			||||||
                future_kwargs.append((name, value))
 | 
					                future_kwargs.append((name, value))
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        kwargs, prefixed = __separate_prefixed_kwargs(kwargs)
 | 
					        kwargs, prefixed = __separate_prefixed_kwargs(kwargs)
 | 
				
			||||||
| 
						 | 
					@ -447,7 +458,7 @@ cdef inline object __provide_keyword_args(
 | 
				
			||||||
                value = __get_value(kw_injection)
 | 
					                value = __get_value(kw_injection)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            kwargs[name] = value
 | 
					            kwargs[name] = value
 | 
				
			||||||
            if __is_future_or_coroutine(value):
 | 
					            if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
 | 
				
			||||||
                future_kwargs.append((name, value))
 | 
					                future_kwargs.append((name, value))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if future_kwargs:
 | 
					    if future_kwargs:
 | 
				
			||||||
| 
						 | 
					@ -550,20 +561,26 @@ cdef inline object __call(
 | 
				
			||||||
        dict context_kwargs,
 | 
					        dict context_kwargs,
 | 
				
			||||||
        tuple injection_kwargs,
 | 
					        tuple injection_kwargs,
 | 
				
			||||||
        int injection_kwargs_len,
 | 
					        int injection_kwargs_len,
 | 
				
			||||||
 | 
					        int async_mode,
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    args = __provide_positional_args(
 | 
					    cdef object args = __provide_positional_args(
 | 
				
			||||||
        context_args,
 | 
					        context_args,
 | 
				
			||||||
        injection_args,
 | 
					        injection_args,
 | 
				
			||||||
        injection_args_len,
 | 
					        injection_args_len,
 | 
				
			||||||
 | 
					        async_mode,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    kwargs = __provide_keyword_args(
 | 
					    cdef object kwargs = __provide_keyword_args(
 | 
				
			||||||
        context_kwargs,
 | 
					        context_kwargs,
 | 
				
			||||||
        injection_kwargs,
 | 
					        injection_kwargs,
 | 
				
			||||||
        injection_kwargs_len,
 | 
					        injection_kwargs_len,
 | 
				
			||||||
 | 
					        async_mode,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    is_future_args = __is_future_or_coroutine(args)
 | 
					    if async_mode == ASYNC_MODE_DISABLED:
 | 
				
			||||||
    is_future_kwargs = __is_future_or_coroutine(kwargs)
 | 
					        return call(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cdef bint is_future_args = __is_future_or_coroutine(args)
 | 
				
			||||||
 | 
					    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)
 | 
				
			||||||
| 
						 | 
					@ -609,7 +626,7 @@ cdef inline object __async_result_callback(object future_result, object future):
 | 
				
			||||||
        future_result.set_result(result)
 | 
					        future_result.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, ):
 | 
				
			||||||
    return __call(
 | 
					    return __call(
 | 
				
			||||||
        self.__provides,
 | 
					        self.__provides,
 | 
				
			||||||
        args,
 | 
					        args,
 | 
				
			||||||
| 
						 | 
					@ -618,13 +635,23 @@ cdef inline object __callable_call(Callable self, tuple args, dict kwargs):
 | 
				
			||||||
        kwargs,
 | 
					        kwargs,
 | 
				
			||||||
        self.__kwargs,
 | 
					        self.__kwargs,
 | 
				
			||||||
        self.__kwargs_len,
 | 
					        self.__kwargs_len,
 | 
				
			||||||
 | 
					        self.__async_mode,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cdef inline object __factory_call(Factory self, tuple args, dict kwargs):
 | 
					cdef inline object __factory_call(Factory self, tuple args, dict kwargs):
 | 
				
			||||||
    cdef object instance
 | 
					    cdef object instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    instance = __callable_call(self.__instantiator, args, kwargs)
 | 
					    instance = __call(
 | 
				
			||||||
 | 
					        self.__instantiator.__provides,
 | 
				
			||||||
 | 
					        args,
 | 
				
			||||||
 | 
					        self.__instantiator.__args,
 | 
				
			||||||
 | 
					        self.__instantiator.__args_len,
 | 
				
			||||||
 | 
					        kwargs,
 | 
				
			||||||
 | 
					        self.__instantiator.__kwargs,
 | 
				
			||||||
 | 
					        self.__instantiator.__kwargs_len,
 | 
				
			||||||
 | 
					        self.__async_mode,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if self.__attributes_len > 0:
 | 
					    if self.__attributes_len > 0:
 | 
				
			||||||
        attributes = __provide_attributes(self.__attributes, self.__attributes_len)
 | 
					        attributes = __provide_attributes(self.__attributes, self.__attributes_len)
 | 
				
			||||||
| 
						 | 
					@ -643,9 +670,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:
 | 
				
			||||||
| 
						 | 
					@ -810,10 +813,10 @@ cdef class Dependency(Provider):
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self._raise_undefined_error()
 | 
					            self._raise_undefined_error()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.is_async_mode_disabled():
 | 
					        if self.__async_mode == ASYNC_MODE_DISABLED:
 | 
				
			||||||
            self._check_instance_type(result)
 | 
					            self._check_instance_type(result)
 | 
				
			||||||
            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):
 | 
				
			||||||
                future_result = asyncio.Future()
 | 
					                future_result = asyncio.Future()
 | 
				
			||||||
                result = asyncio.ensure_future(result)
 | 
					                result = asyncio.ensure_future(result)
 | 
				
			||||||
| 
						 | 
					@ -822,7 +825,7 @@ cdef class Dependency(Provider):
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                self._check_instance_type(result)
 | 
					                self._check_instance_type(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()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3407,7 +3410,7 @@ cdef class List(Provider):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cpdef object _provide(self, tuple args, dict kwargs):
 | 
					    cpdef object _provide(self, tuple args, dict kwargs):
 | 
				
			||||||
        """Return result of provided callable call."""
 | 
					        """Return result of provided callable call."""
 | 
				
			||||||
        return __provide_positional_args(args, self.__args, self.__args_len)
 | 
					        return __provide_positional_args(args, self.__args, self.__args_len, self.__async_mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cdef class Dict(Provider):
 | 
					cdef class Dict(Provider):
 | 
				
			||||||
| 
						 | 
					@ -3533,7 +3536,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 call."""
 | 
					        """Return result of provided callable call."""
 | 
				
			||||||
        return __provide_keyword_args(kwargs, self.__kwargs, self.__kwargs_len)
 | 
					        return __provide_keyword_args(kwargs, self.__kwargs, self.__kwargs_len, self.__async_mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3690,7 +3693,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
    def shutdown(self):
 | 
					    def shutdown(self):
 | 
				
			||||||
        """Shutdown resource."""
 | 
					        """Shutdown resource."""
 | 
				
			||||||
        if not self.__initialized:
 | 
					        if not self.__initialized:
 | 
				
			||||||
            if self.is_async_mode_enabled():
 | 
					            if self.__async_mode == ASYNC_MODE_ENABLED:
 | 
				
			||||||
                result = asyncio.Future()
 | 
					                result = asyncio.Future()
 | 
				
			||||||
                result.set_result(None)
 | 
					                result.set_result(None)
 | 
				
			||||||
                return result
 | 
					                return result
 | 
				
			||||||
| 
						 | 
					@ -3709,7 +3712,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
        self.__initialized = False
 | 
					        self.__initialized = False
 | 
				
			||||||
        self.__shutdowner = None
 | 
					        self.__shutdowner = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.is_async_mode_enabled():
 | 
					        if self.__async_mode == ASYNC_MODE_ENABLED:
 | 
				
			||||||
            result = asyncio.Future()
 | 
					            result = asyncio.Future()
 | 
				
			||||||
            result.set_result(None)
 | 
					            result.set_result(None)
 | 
				
			||||||
            return result
 | 
					            return result
 | 
				
			||||||
| 
						 | 
					@ -3736,6 +3739,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
                kwargs,
 | 
					                kwargs,
 | 
				
			||||||
                self.__kwargs,
 | 
					                self.__kwargs,
 | 
				
			||||||
                self.__kwargs_len,
 | 
					                self.__kwargs_len,
 | 
				
			||||||
 | 
					                self.__async_mode,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            self.__shutdowner = initializer.shutdown
 | 
					            self.__shutdowner = initializer.shutdown
 | 
				
			||||||
        elif self._is_async_resource_subclass(self.__provides):
 | 
					        elif self._is_async_resource_subclass(self.__provides):
 | 
				
			||||||
| 
						 | 
					@ -3748,6 +3752,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
                kwargs,
 | 
					                kwargs,
 | 
				
			||||||
                self.__kwargs,
 | 
					                self.__kwargs,
 | 
				
			||||||
                self.__kwargs_len,
 | 
					                self.__kwargs_len,
 | 
				
			||||||
 | 
					                self.__async_mode,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            self.__initialized = True
 | 
					            self.__initialized = True
 | 
				
			||||||
            return self._create_init_future(async_init, initializer.shutdown)
 | 
					            return self._create_init_future(async_init, initializer.shutdown)
 | 
				
			||||||
| 
						 | 
					@ -3760,6 +3765,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
                kwargs,
 | 
					                kwargs,
 | 
				
			||||||
                self.__kwargs,
 | 
					                self.__kwargs,
 | 
				
			||||||
                self.__kwargs_len,
 | 
					                self.__kwargs_len,
 | 
				
			||||||
 | 
					                self.__async_mode,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            self.__resource = next(initializer)
 | 
					            self.__resource = next(initializer)
 | 
				
			||||||
            self.__shutdowner = initializer.send
 | 
					            self.__shutdowner = initializer.send
 | 
				
			||||||
| 
						 | 
					@ -3772,6 +3778,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
                kwargs,
 | 
					                kwargs,
 | 
				
			||||||
                self.__kwargs,
 | 
					                self.__kwargs,
 | 
				
			||||||
                self.__kwargs_len,
 | 
					                self.__kwargs_len,
 | 
				
			||||||
 | 
					                self.__async_mode,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            self.__initialized = True
 | 
					            self.__initialized = True
 | 
				
			||||||
            return self._create_init_future(initializer)
 | 
					            return self._create_init_future(initializer)
 | 
				
			||||||
| 
						 | 
					@ -3784,6 +3791,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
                kwargs,
 | 
					                kwargs,
 | 
				
			||||||
                self.__kwargs,
 | 
					                self.__kwargs,
 | 
				
			||||||
                self.__kwargs_len,
 | 
					                self.__kwargs_len,
 | 
				
			||||||
 | 
					                self.__async_mode,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            self.__initialized = True
 | 
					            self.__initialized = True
 | 
				
			||||||
            return self._create_async_gen_init_future(initializer)
 | 
					            return self._create_async_gen_init_future(initializer)
 | 
				
			||||||
| 
						 | 
					@ -3796,6 +3804,7 @@ cdef class Resource(Provider):
 | 
				
			||||||
                kwargs,
 | 
					                kwargs,
 | 
				
			||||||
                self.__kwargs,
 | 
					                self.__kwargs,
 | 
				
			||||||
                self.__kwargs_len,
 | 
					                self.__kwargs_len,
 | 
				
			||||||
 | 
					                self.__async_mode,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            raise Error("Unknown type of resource initializer")
 | 
					            raise Error("Unknown type of resource initializer")
 | 
				
			||||||
| 
						 | 
					@ -4510,6 +4519,7 @@ cdef class MethodCaller(Provider):
 | 
				
			||||||
            kwargs,
 | 
					            kwargs,
 | 
				
			||||||
            self.__kwargs,
 | 
					            self.__kwargs,
 | 
				
			||||||
            self.__kwargs_len,
 | 
					            self.__kwargs_len,
 | 
				
			||||||
 | 
					            self.__async_mode,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _async_provide(self, future_result, args, kwargs, future):
 | 
					    def _async_provide(self, future_result, args, kwargs, future):
 | 
				
			||||||
| 
						 | 
					@ -4523,6 +4533,7 @@ cdef class MethodCaller(Provider):
 | 
				
			||||||
                kwargs,
 | 
					                kwargs,
 | 
				
			||||||
                self.__kwargs,
 | 
					                self.__kwargs,
 | 
				
			||||||
                self.__kwargs_len,
 | 
					                self.__kwargs_len,
 | 
				
			||||||
 | 
					                self.__async_mode,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        except Exception as exception:
 | 
					        except Exception as exception:
 | 
				
			||||||
            future_result.set_exception(exception)
 | 
					            future_result.set_exception(exception)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,5 @@
 | 
				
			||||||
"""Wiring module."""
 | 
					"""Wiring module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import asyncio
 | 
					 | 
				
			||||||
import functools
 | 
					 | 
				
			||||||
import inspect
 | 
					import inspect
 | 
				
			||||||
import importlib
 | 
					import importlib
 | 
				
			||||||
import importlib.machinery
 | 
					import importlib.machinery
 | 
				
			||||||
| 
						 | 
					@ -58,7 +56,6 @@ except ImportError:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from . import providers
 | 
					from . import providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
if sys.version_info[:2] == (3, 5):
 | 
					if sys.version_info[:2] == (3, 5):
 | 
				
			||||||
    warnings.warn(
 | 
					    warnings.warn(
 | 
				
			||||||
        "Dependency Injector will drop support of Python 3.5 after Jan 1st of 2022. "
 | 
					        "Dependency Injector will drop support of Python 3.5 after Jan 1st of 2022. "
 | 
				
			||||||
| 
						 | 
					@ -600,71 +597,6 @@ def _get_patched(fn, reference_injections, reference_closing):
 | 
				
			||||||
    return patched
 | 
					    return patched
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _get_sync_patched(fn):
 | 
					 | 
				
			||||||
    @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)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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):
 | 
					 | 
				
			||||||
    @functools.wraps(fn)
 | 
					 | 
				
			||||||
    async def _patched(*args, **kwargs):
 | 
					 | 
				
			||||||
        to_inject = kwargs.copy()
 | 
					 | 
				
			||||||
        to_inject_await = []
 | 
					 | 
				
			||||||
        to_close_await = []
 | 
					 | 
				
			||||||
        for injection, provider in _patched.__injections__.items():
 | 
					 | 
				
			||||||
            if injection not in kwargs \
 | 
					 | 
				
			||||||
                    or _is_fastapi_default_arg_injection(injection, kwargs):
 | 
					 | 
				
			||||||
                provide = provider()
 | 
					 | 
				
			||||||
                if inspect.isawaitable(provide):
 | 
					 | 
				
			||||||
                    to_inject_await.append((injection, provide))
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    to_inject[injection] = provide
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        async_to_inject = await asyncio.gather(*[provide for _, provide in to_inject_await])
 | 
					 | 
				
			||||||
        for provide, (injection, _) in zip(async_to_inject, to_inject_await):
 | 
					 | 
				
			||||||
            to_inject[injection] = provide
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        result = await 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
 | 
					 | 
				
			||||||
            shutdown = provider.shutdown()
 | 
					 | 
				
			||||||
            if inspect.isawaitable(shutdown):
 | 
					 | 
				
			||||||
                to_close_await.append(shutdown)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        await asyncio.gather(*to_close_await)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return result
 | 
					 | 
				
			||||||
    return _patched
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _is_fastapi_default_arg_injection(injection, kwargs):
 | 
					 | 
				
			||||||
    """Check if injection is FastAPI injection of the default argument."""
 | 
					 | 
				
			||||||
    return injection in kwargs and isinstance(kwargs[injection], _Marker)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _is_fastapi_depends(param: Any) -> bool:
 | 
					def _is_fastapi_depends(param: Any) -> bool:
 | 
				
			||||||
    return fastapi and isinstance(param, fastapi.params.Depends)
 | 
					    return fastapi and isinstance(param, fastapi.params.Depends)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -828,6 +760,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],
 | 
				
			||||||
| 
						 | 
					@ -958,3 +892,7 @@ def is_loader_installed() -> bool:
 | 
				
			||||||
_patched_registry = PatchedRegistry()
 | 
					_patched_registry = PatchedRegistry()
 | 
				
			||||||
_inspect_filter = InspectFilter()
 | 
					_inspect_filter = InspectFilter()
 | 
				
			||||||
_loader = AutoLoader()
 | 
					_loader = AutoLoader()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Optimizations
 | 
				
			||||||
 | 
					from ._cwiring import _get_sync_patched  # noqa
 | 
				
			||||||
 | 
					from ._cwiring import _get_async_patched  # noqa
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user