Issue #22138: Fix mock.patch behavior when patching descriptors. Restore

original values after patching.

Patch contributed by Sean McCully.
This commit is contained in:
Senthil Kumaran 2016-01-08 23:43:29 -08:00
parent cbe6356c42
commit 81bc927da7
3 changed files with 33 additions and 1 deletions

View File

@ -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)

View File

@ -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()

View File

@ -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.