-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-94912: deprecate asyncio.iscoroutinefunction when it behaves differently to inspect.iscoroutinefunction #94923
Changes from all commits
1a39312
56c6ed4
2b837c8
aedef3f
a4c0767
5402f43
d792bf9
dafc2ff
f839f14
e9d2eb3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ | |
import sys | ||
import builtins | ||
import pkgutil | ||
from asyncio import iscoroutinefunction | ||
from inspect import iscoroutinefunction | ||
from types import CodeType, ModuleType, MethodType | ||
from unittest.util import safe_repr | ||
from functools import wraps, partial | ||
|
@@ -197,6 +197,33 @@ def checksig(*args, **kwargs): | |
_setup_func(funcopy, mock, sig) | ||
return funcopy | ||
|
||
def _set_async_signature(mock, original, instance=False, is_async_mock=False): | ||
# creates an async function with signature (*args, **kwargs) that delegates to a | ||
# mock. It still does signature checking by calling a lambda with the same | ||
# signature as the original. | ||
|
||
skipfirst = isinstance(original, type) | ||
result = _get_signature_object(original, instance, skipfirst) | ||
if result is None: | ||
return mock | ||
func, sig = result | ||
def checksig(*args, **kwargs): | ||
sig.bind(*args, **kwargs) | ||
_copy_func_details(func, checksig) | ||
|
||
name = original.__name__ | ||
if not name.isidentifier(): | ||
name = 'funcopy' | ||
context = {'_checksig_': checksig, 'mock': mock} | ||
src = """async def %s(*args, **kwargs): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is to fix #94924 |
||
_checksig_(*args, **kwargs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is another very subtle change - before the signature was checked when the function was called - and now the signature is checked when the coro is primed, but I think this is a better behavior and worth it to allow |
||
return await mock(*args, **kwargs)""" % name | ||
exec (src, context) | ||
funcopy = context[name] | ||
_setup_func(funcopy, mock, sig) | ||
_setup_async_mock(funcopy) | ||
return funcopy | ||
|
||
|
||
def _setup_func(funcopy, mock, sig): | ||
funcopy.mock = mock | ||
|
@@ -248,7 +275,6 @@ def reset_mock(): | |
|
||
|
||
def _setup_async_mock(mock): | ||
mock._is_coroutine = asyncio.coroutines._is_coroutine | ||
mock.await_count = 0 | ||
mock.await_args = None | ||
mock.await_args_list = _CallList() | ||
|
@@ -2162,13 +2188,6 @@ class AsyncMockMixin(Base): | |
|
||
def __init__(self, /, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
# iscoroutinefunction() checks _is_coroutine property to say if an | ||
# object is a coroutine. Without this check it looks to see if it is a | ||
# function/method, which in this case it is not (since it is an | ||
# AsyncMock). | ||
# It is set through __dict__ because when spec_set is True, this | ||
# attribute is likely undefined. | ||
self.__dict__['_is_coroutine'] = asyncio.coroutines._is_coroutine | ||
self.__dict__['_mock_await_count'] = 0 | ||
self.__dict__['_mock_await_args'] = None | ||
self.__dict__['_mock_await_args_list'] = _CallList() | ||
|
@@ -2681,9 +2700,10 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, | |
if isinstance(spec, FunctionTypes): | ||
# should only happen at the top level because we don't | ||
# recurse for functions | ||
mock = _set_signature(mock, spec) | ||
if is_async_func: | ||
_setup_async_mock(mock) | ||
mock = _set_async_signature(mock, spec) | ||
else: | ||
mock = _set_signature(mock, spec) | ||
else: | ||
_check_signature(spec, mock, is_type, instance) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
make ``asyncio.iscoroutinefunction`` a deprecated alias of ``inspect.iscoroutinefunction`` and remove ``asyncio.coroutines._is_coroutine`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will insist on objects being real awaitables rather than virtual awaitables - eg: