diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 5b8e7441403538..373e1d5f64d87b 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -738,7 +738,7 @@ def __delattr__(self, name): obj = self._mock_children.get(name, _missing) if name in self.__dict__: - super().__delattr__(name) + _safe_super(NonCallableMock, self).__delattr__(name) elif obj is _deleted: raise AttributeError(name) if obj is not _missing: diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 447a502b57d6eb..2f50236d1ece1a 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1811,6 +1811,44 @@ def foo(a, b): self.assertRaises(TypeError, mock.child, 1) self.assertEqual(mock.mock_calls, [call.child(1, 2)]) + def test_isinstance_under_settrace(self): + # bpo-36593 : __class__ is not set for a class that has __class__ + # property defined when it's used with sys.settrace(trace) set. + # Delete the module to force reimport with tracing function set + # restore the old reference later since there are other tests that are + # dependent on unittest.mock.patch. In testpatch.PatchTest + # test_patch_dict_test_prefix and test_patch_test_prefix not restoring + # causes the objects patched to go out of sync + + old_patch = unittest.mock.patch + + # Directly using __setattr__ on unittest.mock causes current imported + # reference to be updated. Use a lambda so that during cleanup the + # re-imported new reference is updated. + self.addCleanup(lambda patch: setattr(unittest.mock, 'patch', patch), + old_patch) + + with patch.dict('sys.modules'): + del sys.modules['unittest.mock'] + + def trace(frame, event, arg): + return trace + + sys.settrace(trace) + self.addCleanup(sys.settrace, None) + + from unittest.mock import ( + Mock, MagicMock, NonCallableMock, NonCallableMagicMock + ) + + mocks = [ + Mock, MagicMock, NonCallableMock, NonCallableMagicMock + ] + + for mock in mocks: + obj = mock(spec=Something) + self.assertIsInstance(obj, Something) + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2019-04-11-22-11-24.bpo-36598.hfzDUl.rst b/Misc/NEWS.d/next/Library/2019-04-11-22-11-24.bpo-36598.hfzDUl.rst new file mode 100644 index 00000000000000..2a798020913695 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-11-22-11-24.bpo-36598.hfzDUl.rst @@ -0,0 +1,2 @@ +Fix ``isinstance`` check for Mock objects with spec when the code is +executed under tracing. Patch by Karthikeyan Singaravelan.