]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-84753: Make inspect.iscoroutinefunction() work with AsyncMock (GH-94050) (GH-94461)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 30 Jun 2022 18:02:15 +0000 (11:02 -0700)
committerGitHub <noreply@github.com>
Thu, 30 Jun 2022 18:02:15 +0000 (20:02 +0200)
The inspect version was not working with unittest.mock.AsyncMock.

The fix introduces special-casing of AsyncMock in
`inspect.iscoroutinefunction` equivalent to the one
performed in `asyncio.iscoroutinefunction`.

Co-authored-by: Ɓukasz Langa <lukasz@langa.pl>
(cherry picked from commit 4261b6bffc0b8bb5c6d4d80578a81b7520f4aefc)

Co-authored-by: Mehdi ABAAKOUK <sileht@sileht.net>
Lib/inspect.py
Lib/test/test_asyncio/test_tasks.py
Lib/test/test_inspect.py
Lib/unittest/mock.py
Misc/NEWS.d/next/Library/2022-06-21-11-40-31.gh-issue-84753.FW1pxO.rst [new file with mode: 0644]

index c5881cc808d21ab321b251d77db1cb9e7fd46ded..01df575e4bfee425c97b878dae698d72704606ec 100644 (file)
@@ -294,7 +294,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)
 
index 0007b44a220c475a13c6a07dfd3b8fc16ce08918..05a822ba458b7f8d0d73671d0f683da8729c89bb 100644 (file)
@@ -1723,6 +1723,7 @@ class BaseTaskTests:
         self.assertTrue(asyncio.iscoroutinefunction(fn2))
 
         self.assertFalse(asyncio.iscoroutinefunction(mock.Mock()))
+        self.assertTrue(asyncio.iscoroutinefunction(mock.AsyncMock()))
 
     def test_yield_vs_yield_from(self):
         fut = self.new_future(self.loop)
index 28e4f5b4a718a4fd7263944b8aab6723825b211a..eaefe946e8963fe73a8a289473752f1b91bdcda9 100644 (file)
@@ -188,6 +188,10 @@ class TestPredicates(IsTestBase):
                     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(
@@ -196,6 +200,10 @@ class TestPredicates(IsTestBase):
                     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(
@@ -204,6 +212,12 @@ class TestPredicates(IsTestBase):
                     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(
index 7152f86ed96945e9757e2f3eb2d6fa01e443c9de..3f7185b9671e4fcb8e0f60be2435c73f3d3470f9 100644 (file)
@@ -2186,6 +2186,10 @@ class AsyncMockMixin(Base):
         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 (file)
index 0000000..f701d2a
--- /dev/null
@@ -0,0 +1,3 @@
+: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.