[issue32952] Add __qualname__ for attributes of Mock instances

Karthikeyan Singaravelan report at bugs.python.org
Fri Dec 13 06:03:27 EST 2019


Karthikeyan Singaravelan <tir.karthi at gmail.com> added the comment:

create_autospec already does recursive spec setting on the class and it has the attributes/methods mocked to retain attributes but doesn't copy the metadata of the original methods to the mock itself. I am not sure spec_set needs to do more stuff than simple attribute level checks making it more heavy to resemble autospeccing and there is an issue for that already. Currently we don't copy __qualname__ to the mock at [0]. 

The func metadata are copied to checksig and during __call__ checksig is used but it's not usable outside and I am not sure we need to do it. The fix to do _copy_func_details(func, mock) below that would copy the function attributes to the actual mock thus accessing the attributes for the mock making below example work.


from unittest.mock import MagicMock, create_autospec, patch

class SomeClass(object):

    def some_method(self):
        print("Hi!")

if __name__ == "__main__":
    ins = SomeClass()
    assert ins.some_method.__qualname__ == "SomeClass.some_method"

    with patch('__main__.SomeClass', autospec=True) as mocked:
        obj = SomeClass()
        assert obj.some_method.__qualname__ == "SomeClass.some_method"
        obj.some_method()
        obj.some_method.assert_called_once()


Copy metadata patch : 

diff --git Lib/unittest/mock.py Lib/unittest/mock.py
index cd5a2aeb60..ea1c6c84ac 100644
--- Lib/unittest/mock.py
+++ Lib/unittest/mock.py
@@ -117,6 +117,7 @@ def _check_signature(func, mock, skipfirst, instance=False):
     def checksig(self, /, *args, **kwargs):
         sig.bind(*args, **kwargs)
     _copy_func_details(func, checksig)
+    _copy_func_details(func, mock)
     type(mock)._mock_check_sig = checksig
     type(mock).__signature__ = sig

@@ -127,6 +128,7 @@ def _copy_func_details(func, funcopy):
     for attribute in (
         '__name__', '__doc__', '__text_signature__',
         '__module__', '__defaults__', '__kwdefaults__',
+        '__qualname__'
     ):
         try:
             setattr(funcopy, attribute, getattr(func, attribute))

[0] https://github.com/python/cpython/blob/025a602af7ee284d8db6955c26016f3f27d35536/Lib/unittest/mock.py#L124
[1] https://github.com/python/cpython/blob/025a602af7ee284d8db6955c26016f3f27d35536/Lib/unittest/mock.py#L119

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue32952>
_______________________________________


More information about the Python-bugs-list mailing list