From: Senthil Kumaran Date: Sat, 9 Jan 2016 07:43:29 +0000 (-0800) Subject: Issue #22138: Fix mock.patch behavior when patching descriptors. Restore X-Git-Tag: v3.6.0a1~809^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=81bc927da7f1b2cc0d2be642810b084666f63264;p=thirdparty%2FPython%2Fcpython.git Issue #22138: Fix mock.patch behavior when patching descriptors. Restore original values after patching. Patch contributed by Sean McCully. --- diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 99ce1e2bf45c..976f663c0a95 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1332,7 +1332,10 @@ class _patch(object): setattr(self.target, self.attribute, self.temp_original) else: delattr(self.target, self.attribute) - if not self.create and not hasattr(self.target, self.attribute): + if not self.create and (not hasattr(self.target, self.attribute) or + self.attribute in ('__doc__', '__module__', + '__defaults__', '__annotations__', + '__kwdefaults__')): # needed for proxy objects like django settings setattr(self.target, self.attribute, self.temp_original) diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index 28fe86b0de99..dfce3696d6ab 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1817,5 +1817,31 @@ class PatchTest(unittest.TestCase): self.assertEqual(stopped, ["three", "two", "one"]) + def test_special_attrs(self): + def foo(x=0): + """TEST""" + return x + with patch.object(foo, '__defaults__', (1, )): + self.assertEqual(foo(), 1) + self.assertEqual(foo(), 0) + + with patch.object(foo, '__doc__', "FUN"): + self.assertEqual(foo.__doc__, "FUN") + self.assertEqual(foo.__doc__, "TEST") + + with patch.object(foo, '__module__', "testpatch2"): + self.assertEqual(foo.__module__, "testpatch2") + self.assertEqual(foo.__module__, 'unittest.test.testmock.testpatch') + + with patch.object(foo, '__annotations__', dict([('s', 1, )])): + self.assertEqual(foo.__annotations__, dict([('s', 1, )])) + self.assertEqual(foo.__annotations__, dict()) + + def foo(*a, x=0): + return x + with patch.object(foo, '__kwdefaults__', dict([('x', 1, )])): + self.assertEqual(foo(), 1) + self.assertEqual(foo(), 0) + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 61b62f7828fc..6c8a8fef1265 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,9 @@ Core and Builtins Library ------- +- Issue #22138: Fix mock.patch behavior when patching descriptors. Restore + original values after patching. Patch contributed by Sean McCully. + - Issue #25672: In the ssl module, enable the SSL_MODE_RELEASE_BUFFERS mode option if it is safe to do so.