mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 01:26:51 +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
|
||||
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
|
||||
------
|
||||
- Optimize injections and wiring from x1.5 to x7 times depending on the use case.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Top-level package."""
|
||||
|
||||
__version__ = "4.39.0"
|
||||
__version__ = "4.39.1"
|
||||
"""Version number.
|
||||
|
||||
:type: str
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,23 +9,27 @@ import types
|
|||
from . import providers
|
||||
from .wiring import _Marker
|
||||
|
||||
from .providers cimport Provider
|
||||
|
||||
|
||||
def _get_sync_patched(fn):
|
||||
@functools.wraps(fn)
|
||||
def _patched(*args, **kwargs):
|
||||
cdef object result
|
||||
cdef dict to_inject
|
||||
cdef object arg_key
|
||||
cdef Provider provider
|
||||
|
||||
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()
|
||||
for arg_key, provider in _patched.__injections__.items():
|
||||
if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
|
||||
to_inject[arg_key] = 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):
|
||||
for arg_key, provider in _patched.__closing__.items():
|
||||
if arg_key in kwargs and not isinstance(kwargs[arg_key], _Marker):
|
||||
continue
|
||||
if not isinstance(provider, providers.Resource):
|
||||
continue
|
||||
|
@ -35,49 +39,45 @@ def _get_sync_patched(fn):
|
|||
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 = []
|
||||
async def _async_inject(object fn, tuple args, dict kwargs, dict injections, dict closings):
|
||||
cdef object result
|
||||
cdef dict to_inject
|
||||
cdef list to_inject_await = []
|
||||
cdef list to_close_await = []
|
||||
cdef object arg_key
|
||||
cdef Provider provider
|
||||
|
||||
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
|
||||
to_inject = kwargs.copy()
|
||||
for arg_key, provider in injections.items():
|
||||
if arg_key not in kwargs or isinstance(kwargs[arg_key], _Marker):
|
||||
provide = provider()
|
||||
if provider.is_async_mode_enabled():
|
||||
to_inject_await.append((arg_key, provide))
|
||||
elif _isawaitable(provide):
|
||||
to_inject_await.append((arg_key, provide))
|
||||
else:
|
||||
to_inject[arg_key] = 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
|
||||
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)
|
||||
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)
|
||||
if closings:
|
||||
for arg_key, provider in closings.items():
|
||||
if arg_key in kwargs and isinstance(kwargs[arg_key], _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)
|
||||
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
|
||||
return result
|
||||
|
||||
|
||||
cdef bint _isawaitable(object instance):
|
||||
|
|
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 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 void _copy_overridings(self, Provider copied, dict memo)
|
||||
|
||||
|
|
|
@ -406,15 +406,15 @@ cdef class Provider(object):
|
|||
"""
|
||||
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."""
|
||||
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."""
|
||||
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."""
|
||||
return self.__async_mode == ASYNC_MODE_UNDEFINED
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""Wiring module."""
|
||||
|
||||
import functools
|
||||
import inspect
|
||||
import importlib
|
||||
import importlib.machinery
|
||||
|
@ -895,4 +895,19 @@ _loader = AutoLoader()
|
|||
|
||||
# Optimizations
|
||||
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