]> granicus.if.org Git - python/commitdiff
bpo-17185: Add __signature__ to mock that can be used by inspect for signature (GH11048)
authorXtreak <tirkarthi@users.noreply.github.com>
Wed, 12 Dec 2018 07:54:54 +0000 (13:24 +0530)
committerChris Withers <chris@withers.org>
Wed, 12 Dec 2018 07:54:54 +0000 (07:54 +0000)
* Fix partial and partial method signatures in mock

* Add more calls

* Add NEWS entry

* Use assertEquals and fix markup in NEWS

* Refactor branching and add markup reference for functools

* Revert partial object related changes and fix pr comments

Lib/unittest/mock.py
Lib/unittest/test/testmock/testhelpers.py
Misc/NEWS.d/next/Library/2018-12-09-17-04-15.bpo-17185.SfSCJF.rst [new file with mode: 0644]

index 61ed80b976a7b7cfbf4c5e59f090046f8e83cd09..38189c9aec2ea332e4564f6117c3d4ea3ca9859a 100644 (file)
@@ -103,6 +103,7 @@ def _check_signature(func, mock, skipfirst, instance=False):
         sig.bind(*args, **kwargs)
     _copy_func_details(func, checksig)
     type(mock)._mock_check_sig = checksig
+    type(mock).__signature__ = sig
 
 
 def _copy_func_details(func, funcopy):
@@ -172,11 +173,11 @@ def _set_signature(mock, original, instance=False):
     return mock(*args, **kwargs)""" % name
     exec (src, context)
     funcopy = context[name]
-    _setup_func(funcopy, mock)
+    _setup_func(funcopy, mock, sig)
     return funcopy
 
 
-def _setup_func(funcopy, mock):
+def _setup_func(funcopy, mock, sig):
     funcopy.mock = mock
 
     # can't use isinstance with mocks
@@ -224,6 +225,7 @@ def _setup_func(funcopy, mock):
     funcopy.assert_called = assert_called
     funcopy.assert_not_called = assert_not_called
     funcopy.assert_called_once = assert_called_once
+    funcopy.__signature__ = sig
 
     mock._mock_delegate = funcopy
 
index 9388311e3e2517fd9c00df60c54e9f986597a252..745580ef79db9073008637a0096b72a593828033 100644 (file)
@@ -1,3 +1,4 @@
+import inspect
 import time
 import types
 import unittest
@@ -901,6 +902,35 @@ class SpecSignatureTest(unittest.TestCase):
         self.assertFalse(hasattr(autospec, '__name__'))
 
 
+    def test_spec_inspect_signature(self):
+
+        def myfunc(x, y):
+            pass
+
+        mock = create_autospec(myfunc)
+        mock(1, 2)
+        mock(x=1, y=2)
+
+        self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(myfunc))
+        self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)])
+        self.assertRaises(TypeError, mock, 1)
+
+
+    def test_spec_inspect_signature_annotations(self):
+
+        def foo(a: int, b: int=10, *, c:int) -> int:
+            return a + b + c
+
+        mock = create_autospec(foo)
+        mock(1, 2, c=3)
+        mock(1, c=3)
+
+        self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(foo))
+        self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)])
+        self.assertRaises(TypeError, mock, 1)
+        self.assertRaises(TypeError, mock, 1, 2, 3, c=4)
+
+
 class TestCallList(unittest.TestCase):
 
     def test_args_list_contains_call_list(self):
diff --git a/Misc/NEWS.d/next/Library/2018-12-09-17-04-15.bpo-17185.SfSCJF.rst b/Misc/NEWS.d/next/Library/2018-12-09-17-04-15.bpo-17185.SfSCJF.rst
new file mode 100644 (file)
index 0000000..311c6d2
--- /dev/null
@@ -0,0 +1,2 @@
+Set ``__signature__`` on mock for :mod:`inspect` to get signature.
+Patch by Karthikeyan Singaravelan.