From 694627344a4732890ff87010312369fdcdf08b6f Mon Sep 17 00:00:00 2001 From: Mehdi Abaakouk Date: Tue, 21 Jun 2022 11:29:57 +0200 Subject: [PATCH 1/2] gh-84753: sync iscoroutinefunction of asyncio and inspect module The inspect version was not working with unittest.mock.AsyncMock. This change moves the asyncio fix for AsyncMock in inspect module and make asyncio.iscoroutinefunction an alias of inspect.iscoroutinefunction. --- Lib/inspect.py | 2 +- Lib/test/test_asyncio/test_tasks.py | 1 + Lib/test/test_inspect.py | 14 ++++++++++++++ Lib/unittest/mock.py | 4 ++++ .../2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst | 1 + 5 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst diff --git a/Lib/inspect.py b/Lib/inspect.py index 6e744712f014b1..cbc0632484b832 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -395,7 +395,7 @@ def _has_code_flag(f, flag): while ismethod(f): f = f.__func__ f = functools._unwrap_partial(f) - if not isfunction(f): + if not (isfunction(f) or _signature_is_functionlike(f)): return False return bool(f.__code__.co_flags & flag) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 69cecb3ab12070..bde4defdf0129e 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1649,6 +1649,7 @@ async def fn2(): self.assertTrue(asyncio.iscoroutinefunction(fn2)) self.assertFalse(asyncio.iscoroutinefunction(mock.Mock())) + self.assertTrue(asyncio.iscoroutinefunction(mock.AsyncMock())) def test_coroutine_non_gen_function(self): async def func(): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index ae1842704d37df..be9f29e04ae110 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -202,6 +202,10 @@ def test_iscoroutine(self): gen_coroutine_function_example)))) self.assertTrue(inspect.isgenerator(gen_coro)) + self.assertFalse( + inspect.iscoroutinefunction(unittest.mock.Mock())) + self.assertTrue( + inspect.iscoroutinefunction(unittest.mock.AsyncMock())) self.assertTrue( inspect.iscoroutinefunction(coroutine_function_example)) self.assertTrue( @@ -210,6 +214,10 @@ def test_iscoroutine(self): coroutine_function_example)))) self.assertTrue(inspect.iscoroutine(coro)) + self.assertFalse( + inspect.isgeneratorfunction(unittest.mock.Mock())) + self.assertFalse( + inspect.isgeneratorfunction(unittest.mock.AsyncMock())) self.assertFalse( inspect.isgeneratorfunction(coroutine_function_example)) self.assertFalse( @@ -218,6 +226,12 @@ def test_iscoroutine(self): coroutine_function_example)))) self.assertFalse(inspect.isgenerator(coro)) + self.assertFalse( + inspect.isasyncgenfunction(unittest.mock.Mock())) + self.assertFalse( + inspect.isasyncgenfunction(unittest.mock.AsyncMock())) + self.assertFalse( + inspect.isasyncgenfunction(coroutine_function_example)) self.assertTrue( inspect.isasyncgenfunction(async_generator_function_example)) self.assertTrue( diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 8262b7170b76b4..cd46fea5162aba 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2175,6 +2175,10 @@ def __init__(self, /, *args, **kwargs): code_mock = NonCallableMock(spec_set=CodeType) code_mock.co_flags = inspect.CO_COROUTINE self.__dict__['__code__'] = code_mock + self.__dict__['__name__'] = 'AsyncMock' + self.__dict__['__defaults__'] = tuple() + self.__dict__['__kwdefaults__'] = {} + self.__dict__['__annotations__'] = None async def _execute_mock_call(self, /, *args, **kwargs): # This is nearly just like super(), except for special handling diff --git a/Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst b/Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst new file mode 100644 index 00000000000000..d3e93a54f7dc86 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst @@ -0,0 +1 @@ +inspect.iscoroutinefunction() now works with unittest.mock.AsyncMock From 812d7f34c33ec612f29932eed129caaeee37c0a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Thu, 30 Jun 2022 18:25:28 +0200 Subject: [PATCH 2/2] Make Blurb clearer --- .../Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst b/Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst index d3e93a54f7dc86..f701d2a1afeb85 100644 --- a/Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst +++ b/Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst @@ -1 +1,3 @@ -inspect.iscoroutinefunction() now works with unittest.mock.AsyncMock +:func:`inspect.iscoroutinefunction` now properly returns ``True`` when an instance +of :class:`unittest.mock.AsyncMock` is passed to it. This makes it consistent with +behavior of :func:`asyncio.iscoroutinefunction`. Patch by Mehdi ABAAKOUK.