Message329345
Is this being worked on or can I try fixing this?
My analysis so far is as below :
1. For functions : inspect.signature looks for attribute __signature__ for functions and while creating the mock for a function since we already have the signature we can set __signature__ attribute during _set_signature. I don't know why __signature__ was set. I downloaded mock from GitHub to look at the actual mocksignature implementation which uses lambda signature: _mock_signature to form a mock function which I hope is done here too with a function constructed and evald with sig.bind used for parameter checking. I am still new to the mocksignature internals so I couldn't understand how mocksignature worked.
2. For class and partial functions _check_signature is called and __call__ is overriden in the mock class to check for signature during initialization acting like a constructor. The actual signature will have self along with rest of the parameters but _get_signature_object checks for __init__ and skips the self thus the constructor signature skips self to return a partial function which makes comparing actual constructor call with self and the partial function signature without self to fail.
Attaching a sample patch with tests. Hope I am on the right track and guidance would help. I am changing the version to 3.8
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index a9c82dcb5d..8cbef0e514 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -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
Initial set of tests where partial function and class test fails :
def test_spec_inspect_signature(self):
def foo(a: int, b: int=10, *, c:int) -> int:
return a b c
mock = create_autospec(foo)
assert inspect.getfullargspec(mock) == inspect.getfullargspec(foo)
self.assertRaises(TypeError, mock, 1)
def test_spec_inspect_signature_partial(self):
def foo(a: int, b: int=10, *, c:int) -> int:
return a b c
import functools
partial_object = functools.partial(foo, 1)
mock = create_autospec(partial_object)
assert inspect.getfullargspec(mock) == inspect.getfullargspec(partial_object) # Fails
self.assertRaises(TypeError, partial_object)
def test_spec_inspect_signature_class(self):
class Bar:
def __init__(self, a: int):
self.a = a
mock = create_autospec(Bar)
assert inspect.getfullargspec(mock) == inspect.getfullargspec(Bar) # Fails since mock signature has no self
self.assertRaises(TypeError, mock)
self._check_someclass_mock(mock) |
|
Date |
User |
Action |
Args |
2018-11-06 05:38:27 | xtreak | set | recipients:
+ xtreak, cjw296, michael.foord |
2018-11-06 05:38:27 | xtreak | set | messageid: <1541482707.6.0.788709270274.issue17185@psf.upfronthosting.co.za> |
2018-11-06 05:38:27 | xtreak | link | issue17185 messages |
2018-11-06 05:38:27 | xtreak | create | |
|