[Python-checkins] gh-96127: Fix `inspect.signature` call on mocks (#96335)

cjw296 webhook-mailer at python.org
Sat Jan 7 05:49:21 EST 2023


https://github.com/python/cpython/commit/9e7d7266ecdcccc02385fe4ccb094f3444102e26
commit: 9e7d7266ecdcccc02385fe4ccb094f3444102e26
branch: main
author: Nikita Sobolev <mail at sobolevn.me>
committer: cjw296 <chris at withers.org>
date: 2023-01-07T10:49:15Z
summary:

gh-96127: Fix `inspect.signature` call on mocks (#96335)

files:
A Misc/NEWS.d/next/Library/2022-08-27-10-35-50.gh-issue-96127.8RdLre.rst
M Lib/test/test_inspect.py
M Lib/unittest/mock.py

diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 1b589c8df2a2..aa757241aca9 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -3283,6 +3283,25 @@ def test_signature_on_lambdas(self):
                          ((('a', 10, ..., "positional_or_keyword"),),
                           ...))
 
+    def test_signature_on_mocks(self):
+        # https://github.com/python/cpython/issues/96127
+        for mock in (
+            unittest.mock.Mock(),
+            unittest.mock.AsyncMock(),
+            unittest.mock.MagicMock(),
+        ):
+            with self.subTest(mock=mock):
+                self.assertEqual(str(inspect.signature(mock)), '(*args, **kwargs)')
+
+    def test_signature_on_noncallable_mocks(self):
+        for mock in (
+            unittest.mock.NonCallableMock(),
+            unittest.mock.NonCallableMagicMock(),
+        ):
+            with self.subTest(mock=mock):
+                with self.assertRaises(TypeError):
+                    inspect.signature(mock)
+
     def test_signature_equality(self):
         def foo(a, *, b:int) -> float: pass
         self.assertFalse(inspect.signature(foo) == 42)
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index b3c0e28c698b..0f93cb53c3d5 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -2217,7 +2217,15 @@ def __init__(self, /, *args, **kwargs):
         code_mock = NonCallableMock(spec_set=_CODE_ATTRS)
         code_mock.__dict__["_spec_class"] = CodeType
         code_mock.__dict__["_spec_signature"] = _CODE_SIG
-        code_mock.co_flags = inspect.CO_COROUTINE
+        code_mock.co_flags = (
+            inspect.CO_COROUTINE
+            + inspect.CO_VARARGS
+            + inspect.CO_VARKEYWORDS
+        )
+        code_mock.co_argcount = 0
+        code_mock.co_varnames = ('args', 'kwargs')
+        code_mock.co_posonlyargcount = 0
+        code_mock.co_kwonlyargcount = 0
         self.__dict__['__code__'] = code_mock
         self.__dict__['__name__'] = 'AsyncMock'
         self.__dict__['__defaults__'] = tuple()
diff --git a/Misc/NEWS.d/next/Library/2022-08-27-10-35-50.gh-issue-96127.8RdLre.rst b/Misc/NEWS.d/next/Library/2022-08-27-10-35-50.gh-issue-96127.8RdLre.rst
new file mode 100644
index 000000000000..79edd8fd5d8f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-08-27-10-35-50.gh-issue-96127.8RdLre.rst
@@ -0,0 +1,2 @@
+``inspect.signature`` was raising ``TypeError`` on call with mock objects.
+Now it correctly returns ``(*args, **kwargs)`` as infered signature.



More information about the Python-checkins mailing list