summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXtreak <tir.karthi@gmail.com>2019-02-24 18:54:49 (GMT)
committerChris Withers <chris@withers.org>2019-02-24 18:54:49 (GMT)
commita875ea58b29fbf510f9790ae1653eeaa47dc0de8 (patch)
tree076c625afd240521c200df9b98485846f32687a4
parentaeca373b339e0ea9739536ce6b43bd90f3b89873 (diff)
downloadcpython-a875ea58b29fbf510f9790ae1653eeaa47dc0de8.zip
cpython-a875ea58b29fbf510f9790ae1653eeaa47dc0de8.tar.gz
cpython-a875ea58b29fbf510f9790ae1653eeaa47dc0de8.tar.bz2
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
-rw-r--r--Lib/unittest/mock.py4
-rw-r--r--Lib/unittest/test/testmock/support.py3
-rw-r--r--Lib/unittest/test/testmock/testpatch.py17
-rw-r--r--Misc/NEWS.d/next/Library/2019-02-24-00-04-10.bpo-35512.eWDjCJ.rst3
4 files changed, 25 insertions, 2 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 8f46050..ccbcd35 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -1620,8 +1620,6 @@ class _patch_dict(object):
"""
def __init__(self, in_dict, values=(), clear=False, **kwargs):
- if isinstance(in_dict, str):
- in_dict = _importer(in_dict)
self.in_dict = in_dict
# support any argument supported by dict(...) constructor
self.values = dict(values)
@@ -1662,6 +1660,8 @@ class _patch_dict(object):
def _patch_dict(self):
values = self.values
+ if isinstance(self.in_dict, str):
+ self.in_dict = _importer(self.in_dict)
in_dict = self.in_dict
clear = self.clear
diff --git a/Lib/unittest/test/testmock/support.py b/Lib/unittest/test/testmock/support.py
index c7ad20b..f146be2 100644
--- a/Lib/unittest/test/testmock/support.py
+++ b/Lib/unittest/test/testmock/support.py
@@ -1,3 +1,6 @@
+target = {'foo': 'FOO'}
+
+
def is_instance(obj, klass):
"""Version of is_instance that doesn't access __class__"""
return issubclass(type(obj), klass)
diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py
index f052257..c484adb 100644
--- a/Lib/unittest/test/testmock/testpatch.py
+++ b/Lib/unittest/test/testmock/testpatch.py
@@ -664,6 +664,23 @@ class PatchTest(unittest.TestCase):
test()
+ def test_patch_dict_decorator_resolution(self):
+ # bpo-35512: Ensure that patch with a string target resolves to
+ # the new dictionary during function call
+ original = support.target.copy()
+
+ @patch.dict('unittest.test.testmock.support.target', {'bar': 'BAR'})
+ def test():
+ self.assertEqual(support.target, {'foo': 'BAZ', 'bar': 'BAR'})
+
+ try:
+ support.target = {'foo': 'BAZ'}
+ test()
+ self.assertEqual(support.target, {'foo': 'BAZ'})
+ finally:
+ support.target = original
+
+
def test_patch_descriptor(self):
# would be some effort to fix this - we could special case the
# builtin descriptors: classmethod, property, staticmethod
diff --git a/Misc/NEWS.d/next/Library/2019-02-24-00-04-10.bpo-35512.eWDjCJ.rst b/Misc/NEWS.d/next/Library/2019-02-24-00-04-10.bpo-35512.eWDjCJ.rst
new file mode 100644
index 0000000..8281b1b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-02-24-00-04-10.bpo-35512.eWDjCJ.rst
@@ -0,0 +1,3 @@
+:func:`unittest.mock.patch.dict` used as a decorator with string target
+resolves the target during function call instead of during decorator
+construction. Patch by Karthikeyan Singaravelan.