Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f3a9d72

Browse files
bpo-36593: Fix isinstance check for Mock objects with spec executed under tracing (GH-12790)
In Python having a trace function in effect while mock is imported causes isinstance to be wrong for MagicMocks. This is due to the usage of super() in some class methods, as this sets the __class__ attribute. To avoid this, as a workaround, alias the usage of super . (cherry picked from commit 830b43d) Co-authored-by: Xtreak <[email protected]>
1 parent d28aaa7 commit f3a9d72

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

Lib/unittest/mock.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ def __delattr__(self, name):
738738

739739
obj = self._mock_children.get(name, _missing)
740740
if name in self.__dict__:
741-
super().__delattr__(name)
741+
_safe_super(NonCallableMock, self).__delattr__(name)
742742
elif obj is _deleted:
743743
raise AttributeError(name)
744744
if obj is not _missing:

Lib/unittest/test/testmock/testmock.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,44 @@ def foo(a, b):
18111811
self.assertRaises(TypeError, mock.child, 1)
18121812
self.assertEqual(mock.mock_calls, [call.child(1, 2)])
18131813

1814+
def test_isinstance_under_settrace(self):
1815+
# bpo-36593 : __class__ is not set for a class that has __class__
1816+
# property defined when it's used with sys.settrace(trace) set.
1817+
# Delete the module to force reimport with tracing function set
1818+
# restore the old reference later since there are other tests that are
1819+
# dependent on unittest.mock.patch. In testpatch.PatchTest
1820+
# test_patch_dict_test_prefix and test_patch_test_prefix not restoring
1821+
# causes the objects patched to go out of sync
1822+
1823+
old_patch = unittest.mock.patch
1824+
1825+
# Directly using __setattr__ on unittest.mock causes current imported
1826+
# reference to be updated. Use a lambda so that during cleanup the
1827+
# re-imported new reference is updated.
1828+
self.addCleanup(lambda patch: setattr(unittest.mock, 'patch', patch),
1829+
old_patch)
1830+
1831+
with patch.dict('sys.modules'):
1832+
del sys.modules['unittest.mock']
1833+
1834+
def trace(frame, event, arg):
1835+
return trace
1836+
1837+
sys.settrace(trace)
1838+
self.addCleanup(sys.settrace, None)
1839+
1840+
from unittest.mock import (
1841+
Mock, MagicMock, NonCallableMock, NonCallableMagicMock
1842+
)
1843+
1844+
mocks = [
1845+
Mock, MagicMock, NonCallableMock, NonCallableMagicMock
1846+
]
1847+
1848+
for mock in mocks:
1849+
obj = mock(spec=Something)
1850+
self.assertIsInstance(obj, Something)
1851+
18141852

18151853
if __name__ == '__main__':
18161854
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix ``isinstance`` check for Mock objects with spec when the code is
2+
executed under tracing. Patch by Karthikeyan Singaravelan.

0 commit comments

Comments
 (0)