Skip to content

Commit 6a12931

Browse files
miss-islingtontirkarthi
authored andcommitted
bpo-17185: Add __signature__ to mock that can be used by inspect for signature (GH11125)
* 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 (cherry picked from commit f7fa62e) Co-authored-by: Xtreak <tirkarthi@users.noreply.github.com>
1 parent 10cc626 commit 6a12931

3 files changed

Lines changed: 36 additions & 2 deletions

File tree

Lib/unittest/mock.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ def checksig(_mock_self, *args, **kwargs):
102102
sig.bind(*args, **kwargs)
103103
_copy_func_details(func, checksig)
104104
type(mock)._mock_check_sig = checksig
105+
type(mock).__signature__ = sig
105106

106107

107108
def _copy_func_details(func, funcopy):
@@ -171,11 +172,11 @@ def checksig(*args, **kwargs):
171172
return mock(*args, **kwargs)""" % name
172173
exec (src, context)
173174
funcopy = context[name]
174-
_setup_func(funcopy, mock)
175+
_setup_func(funcopy, mock, sig)
175176
return funcopy
176177

177178

178-
def _setup_func(funcopy, mock):
179+
def _setup_func(funcopy, mock, sig):
179180
funcopy.mock = mock
180181

181182
# can't use isinstance with mocks
@@ -223,6 +224,7 @@ def reset_mock():
223224
funcopy.assert_called = assert_called
224225
funcopy.assert_not_called = assert_not_called
225226
funcopy.assert_called_once = assert_called_once
227+
funcopy.__signature__ = sig
226228

227229
mock._mock_delegate = funcopy
228230

Lib/unittest/test/testmock/testhelpers.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import inspect
12
import time
23
import types
34
import unittest
@@ -901,6 +902,35 @@ def __getattr__(self, attribute):
901902
self.assertFalse(hasattr(autospec, '__name__'))
902903

903904

905+
def test_spec_inspect_signature(self):
906+
907+
def myfunc(x, y):
908+
pass
909+
910+
mock = create_autospec(myfunc)
911+
mock(1, 2)
912+
mock(x=1, y=2)
913+
914+
self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(myfunc))
915+
self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)])
916+
self.assertRaises(TypeError, mock, 1)
917+
918+
919+
def test_spec_inspect_signature_annotations(self):
920+
921+
def foo(a: int, b: int=10, *, c:int) -> int:
922+
return a + b + c
923+
924+
mock = create_autospec(foo)
925+
mock(1, 2, c=3)
926+
mock(1, c=3)
927+
928+
self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(foo))
929+
self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)])
930+
self.assertRaises(TypeError, mock, 1)
931+
self.assertRaises(TypeError, mock, 1, 2, 3, c=4)
932+
933+
904934
class TestCallList(unittest.TestCase):
905935

906936
def test_args_list_contains_call_list(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Set ``__signature__`` on mock for :mod:`inspect` to get signature.
2+
Patch by Karthikeyan Singaravelan.

0 commit comments

Comments
 (0)