mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-25 11:04:01 +03:00
Hotfix issue #574, bump version to 4.39.1
This commit is contained in:
parent
13cae77d57
commit
cfed30cf07
|
@ -7,6 +7,12 @@ that were made in every particular version.
|
||||||
From version 0.7.6 *Dependency Injector* framework strictly
|
From version 0.7.6 *Dependency Injector* framework strictly
|
||||||
follows `Semantic versioning`_
|
follows `Semantic versioning`_
|
||||||
|
|
||||||
|
4.39.1
|
||||||
|
------
|
||||||
|
- Fix bug `#574 <https://github.com/ets-labs/python-dependency-injector/issues/574>`_:
|
||||||
|
"``@inject`` breaks ``inspect.iscoroutinefunction``". Thanks to
|
||||||
|
`@burritoatspoton (Rafał Burczyński) <https://github.com/burritoatspoton>`_ for reporting the issue.
|
||||||
|
|
||||||
4.39.0
|
4.39.0
|
||||||
------
|
------
|
||||||
- Optimize injections and wiring from x1.5 to x7 times depending on the use case.
|
- Optimize injections and wiring from x1.5 to x7 times depending on the use case.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Top-level package."""
|
"""Top-level package."""
|
||||||
|
|
||||||
__version__ = "4.39.0"
|
__version__ = "4.39.1"
|
||||||
"""Version number.
|
"""Version number.
|
||||||
|
|
||||||
:type: str
|
:type: str
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,23 +9,27 @@ import types
|
||||||
from . import providers
|
from . import providers
|
||||||
from .wiring import _Marker
|
from .wiring import _Marker
|
||||||
|
|
||||||
|
from .providers cimport Provider
|
||||||
|
|
||||||
|
|
||||||
def _get_sync_patched(fn):
|
def _get_sync_patched(fn):
|
||||||
@functools.wraps(fn)
|
@functools.wraps(fn)
|
||||||
def _patched(*args, **kwargs):
|
def _patched(*args, **kwargs):
|
||||||
cdef object result
|
cdef object result
|
||||||
cdef dict to_inject
|
cdef dict to_inject
|
||||||
|
cdef object arg_key
|
||||||
|
cdef Provider provider
|
||||||
|
|
||||||
to_inject = kwargs.copy()
|
to_inject = kwargs.copy()
|
||||||
for injection, provider in _patched.__injections__.items():
|
for arg_key, provider in _patched.__injections__.items():
|
||||||
if injection not in kwargs or isinstance(kwargs[injection], _Marker):
|
if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
|
||||||
to_inject[injection] = provider()
|
to_inject[arg_key] = provider()
|
||||||
|
|
||||||
result = fn(*args, **to_inject)
|
result = fn(*args, **to_inject)
|
||||||
|
|
||||||
if _patched.__closing__:
|
if _patched.__closing__:
|
||||||
for injection, provider in _patched.__closing__.items():
|
for arg_key, provider in _patched.__closing__.items():
|
||||||
if injection in kwargs and not isinstance(kwargs[injection], _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):
|
||||||
continue
|
continue
|
||||||
|
@ -35,22 +39,24 @@ def _get_sync_patched(fn):
|
||||||
return _patched
|
return _patched
|
||||||
|
|
||||||
|
|
||||||
def _get_async_patched(fn):
|
async def _async_inject(object fn, tuple args, dict kwargs, dict injections, dict closings):
|
||||||
@functools.wraps(fn)
|
|
||||||
async def _patched(*args, **kwargs):
|
|
||||||
cdef object result
|
cdef object result
|
||||||
cdef dict to_inject
|
cdef dict to_inject
|
||||||
cdef list to_inject_await = []
|
cdef list to_inject_await = []
|
||||||
cdef list to_close_await = []
|
cdef list to_close_await = []
|
||||||
|
cdef object arg_key
|
||||||
|
cdef Provider provider
|
||||||
|
|
||||||
to_inject = kwargs.copy()
|
to_inject = kwargs.copy()
|
||||||
for injection, provider in _patched.__injections__.items():
|
for arg_key, provider in injections.items():
|
||||||
if injection not in kwargs or isinstance(kwargs[injection], _Marker):
|
if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
|
||||||
provide = provider()
|
provide = provider()
|
||||||
if _isawaitable(provide):
|
if provider.is_async_mode_enabled():
|
||||||
to_inject_await.append((injection, provide))
|
to_inject_await.append((arg_key, provide))
|
||||||
|
elif _isawaitable(provide):
|
||||||
|
to_inject_await.append((arg_key, provide))
|
||||||
else:
|
else:
|
||||||
to_inject[injection] = provide
|
to_inject[arg_key] = provide
|
||||||
|
|
||||||
if to_inject_await:
|
if to_inject_await:
|
||||||
async_to_inject = await asyncio.gather(*(provide for _, provide in to_inject_await))
|
async_to_inject = await asyncio.gather(*(provide for _, provide in to_inject_await))
|
||||||
|
@ -59,10 +65,9 @@ def _get_async_patched(fn):
|
||||||
|
|
||||||
result = await fn(*args, **to_inject)
|
result = await fn(*args, **to_inject)
|
||||||
|
|
||||||
if _patched.__closing__:
|
if closings:
|
||||||
for injection, provider in _patched.__closing__.items():
|
for arg_key, provider in closings.items():
|
||||||
if injection in kwargs \
|
if arg_key in kwargs and isinstance(kwargs[arg_key], _Marker):
|
||||||
and isinstance(kwargs[injection], _Marker):
|
|
||||||
continue
|
continue
|
||||||
if not isinstance(provider, providers.Resource):
|
if not isinstance(provider, providers.Resource):
|
||||||
continue
|
continue
|
||||||
|
@ -74,11 +79,6 @@ def _get_async_patched(fn):
|
||||||
|
|
||||||
return result
|
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):
|
cdef bint _isawaitable(object instance):
|
||||||
"""Return true if object can be passed to an ``await`` expression."""
|
"""Return true if object can be passed to an ``await`` expression."""
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -25,6 +25,10 @@ cdef class Provider(object):
|
||||||
cdef tuple __overrides
|
cdef tuple __overrides
|
||||||
cdef int __async_mode
|
cdef int __async_mode
|
||||||
|
|
||||||
|
cpdef bint is_async_mode_enabled(self)
|
||||||
|
cpdef bint is_async_mode_disabled(self)
|
||||||
|
cpdef bint is_async_mode_undefined(self)
|
||||||
|
|
||||||
cpdef object _provide(self, tuple args, dict kwargs)
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
cpdef void _copy_overridings(self, Provider copied, dict memo)
|
cpdef void _copy_overridings(self, Provider copied, dict memo)
|
||||||
|
|
||||||
|
|
|
@ -406,15 +406,15 @@ cdef class Provider(object):
|
||||||
"""
|
"""
|
||||||
self.__async_mode = ASYNC_MODE_UNDEFINED
|
self.__async_mode = ASYNC_MODE_UNDEFINED
|
||||||
|
|
||||||
def is_async_mode_enabled(self):
|
cpdef bint is_async_mode_enabled(self):
|
||||||
"""Check if async mode is enabled."""
|
"""Check if async mode is enabled."""
|
||||||
return self.__async_mode == ASYNC_MODE_ENABLED
|
return self.__async_mode == ASYNC_MODE_ENABLED
|
||||||
|
|
||||||
def is_async_mode_disabled(self):
|
cpdef bint is_async_mode_disabled(self):
|
||||||
"""Check if async mode is disabled."""
|
"""Check if async mode is disabled."""
|
||||||
return self.__async_mode == ASYNC_MODE_DISABLED
|
return self.__async_mode == ASYNC_MODE_DISABLED
|
||||||
|
|
||||||
def is_async_mode_undefined(self):
|
cpdef bint is_async_mode_undefined(self):
|
||||||
"""Check if async mode is undefined."""
|
"""Check if async mode is undefined."""
|
||||||
return self.__async_mode == ASYNC_MODE_UNDEFINED
|
return self.__async_mode == ASYNC_MODE_UNDEFINED
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
"""Wiring module."""
|
"""Wiring module."""
|
||||||
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import importlib
|
import importlib
|
||||||
import importlib.machinery
|
import importlib.machinery
|
||||||
|
@ -895,4 +895,19 @@ _loader = AutoLoader()
|
||||||
|
|
||||||
# Optimizations
|
# Optimizations
|
||||||
from ._cwiring import _get_sync_patched # noqa
|
from ._cwiring import _get_sync_patched # noqa
|
||||||
from ._cwiring import _get_async_patched # noqa
|
from ._cwiring import _async_inject # noqa
|
||||||
|
|
||||||
|
|
||||||
|
# Wiring uses the following Python wrapper because there is
|
||||||
|
# no possibility to compile a first-type citizen coroutine in Cython.
|
||||||
|
def _get_async_patched(fn):
|
||||||
|
@functools.wraps(fn)
|
||||||
|
async def _patched(*args, **kwargs):
|
||||||
|
return await _async_inject(
|
||||||
|
fn,
|
||||||
|
args,
|
||||||
|
kwargs,
|
||||||
|
_patched.__injections__,
|
||||||
|
_patched.__closing__,
|
||||||
|
)
|
||||||
|
return _patched
|
||||||
|
|
22
tests/unit/wiring/test_introspection_py36.py
Normal file
22
tests/unit/wiring/test_introspection_py36.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
"""Tests for compatibility of @inject-patched functions with asyncio and inspect module checks."""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
from dependency_injector.wiring import inject
|
||||||
|
|
||||||
|
|
||||||
|
def test_asyncio_iscoroutinefunction():
|
||||||
|
@inject
|
||||||
|
async def foo():
|
||||||
|
...
|
||||||
|
|
||||||
|
assert asyncio.iscoroutinefunction(foo)
|
||||||
|
|
||||||
|
|
||||||
|
def test_inspect_iscoroutinefunction():
|
||||||
|
@inject
|
||||||
|
async def foo():
|
||||||
|
...
|
||||||
|
|
||||||
|
assert inspect.iscoroutinefunction(foo)
|
Loading…
Reference in New Issue
Block a user