Skip to content

Commit a875ea5

Browse files
tirkarthicjw296
authored andcommitted
bpo-35512: Resolve string target to patch.dict decorator during function call GH#12000
* Resolve string target to patch.dict during function call * Add NEWS entry * Remove unneeded call * Restore original value for support.target and refactor assertions * Add extra assertion to verify unpatched dict
1 parent aeca373 commit a875ea5

File tree

4 files changed

+25
-2
lines changed

4 files changed

+25
-2
lines changed

Lib/unittest/mock.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1620,8 +1620,6 @@ class _patch_dict(object):
16201620
"""
16211621

16221622
def __init__(self, in_dict, values=(), clear=False, **kwargs):
1623-
if isinstance(in_dict, str):
1624-
in_dict = _importer(in_dict)
16251623
self.in_dict = in_dict
16261624
# support any argument supported by dict(...) constructor
16271625
self.values = dict(values)
@@ -1662,6 +1660,8 @@ def __enter__(self):
16621660

16631661
def _patch_dict(self):
16641662
values = self.values
1663+
if isinstance(self.in_dict, str):
1664+
self.in_dict = _importer(self.in_dict)
16651665
in_dict = self.in_dict
16661666
clear = self.clear
16671667

Lib/unittest/test/testmock/support.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
target = {'foo': 'FOO'}
2+
3+
14
def is_instance(obj, klass):
25
"""Version of is_instance that doesn't access __class__"""
36
return issubclass(type(obj), klass)

Lib/unittest/test/testmock/testpatch.py

+17
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,23 @@ def test():
664664
test()
665665

666666

667+
def test_patch_dict_decorator_resolution(self):
668+
# bpo-35512: Ensure that patch with a string target resolves to
669+
# the new dictionary during function call
670+
original = support.target.copy()
671+
672+
@patch.dict('unittest.test.testmock.support.target', {'bar': 'BAR'})
673+
def test():
674+
self.assertEqual(support.target, {'foo': 'BAZ', 'bar': 'BAR'})
675+
676+
try:
677+
support.target = {'foo': 'BAZ'}
678+
test()
679+
self.assertEqual(support.target, {'foo': 'BAZ'})
680+
finally:
681+
support.target = original
682+
683+
667684
def test_patch_descriptor(self):
668685
# would be some effort to fix this - we could special case the
669686
# builtin descriptors: classmethod, property, staticmethod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:func:`unittest.mock.patch.dict` used as a decorator with string target
2+
resolves the target during function call instead of during decorator
3+
construction. Patch by Karthikeyan Singaravelan.

0 commit comments

Comments
 (0)