New submission from Jason R. Coombs <jar...@jaraco.com>:
Originally [reported in testing-cabal/mock#405](https://github.com/testing-cabal/mock/issues/405), I believe I've discovered an inconsistency that manifests as a flaw: `patch` and `patch.object` allow the target to be specified as string referring to the target object and this object is resolved at the time the patch effected, not when the patch is declared. `patch.dict` contrarily seems to resolve the dict eagerly, when the patch is declared. Observe with this pytest: ``` import mock target = dict(a=1) @mock.patch.dict('test_patch_dict.target', dict(b=2)) def test_after_patch(): assert target == dict(a=2, b=2) target = dict(a=2) ``` Here's the output: ``` $ rwt mock pytest -- -m pytest test_patch_dict.py Collecting mock Using cached mock-2.0.0-py2.py3-none-any.whl Collecting pbr>=0.11 (from mock) Using cached pbr-3.0.0-py2.py3-none-any.whl Collecting six>=1.9 (from mock) Using cached six-1.10.0-py2.py3-none-any.whl Installing collected packages: pbr, six, mock Successfully installed mock-2.0.0 pbr-3.0.0 six-1.10.0 ====================================== test session starts ======================================= platform darwin -- Python 3.6.1, pytest-3.0.5, py-1.4.33, pluggy-0.4.0 rootdir: /Users/jaraco, inifile: collected 1 items test_patch_dict.py F ============================================ FAILURES ============================================ ________________________________________ test_after_patch ________________________________________ @mock.patch.dict('test_patch_dict.target', dict(b=2)) def test_after_patch(): > assert target == dict(a=2, b=2) E assert {'a': 2} == {'a': 2, 'b': 2} E Omitting 1 identical items, use -v to show E Right contains more items: E {'b': 2} E Use -v to get the full diff test_patch_dict.py:8: AssertionError ==================================== 1 failed in 0.05 seconds ==================================== ``` The target is unpatched because `test_patch_dict.target` was resolved during decoration rather than during test run. Removing the initial assignment of `target = dict(a=1)`, the failure is thus: ``` ______________________________ ERROR collecting test_patch_dict.py _______________________________ ImportError while importing test module '/Users/jaraco/test_patch_dict.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/rwt-pcm3552g/mock/mock.py:1197: in _dot_lookup return getattr(thing, comp) E AttributeError: module 'test_patch_dict' has no attribute 'target' During handling of the above exception, another exception occurred: <frozen importlib._bootstrap>:942: in _find_and_load_unlocked ??? E AttributeError: module 'test_patch_dict' has no attribute '__path__' During handling of the above exception, another exception occurred: test_patch_dict.py:4: in <module> @mock.patch.dict('test_patch_dict.target', dict(b=2)) /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/rwt-pcm3552g/mock/mock.py:1708: in __init__ in_dict = _importer(in_dict) /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/rwt-pcm3552g/mock/mock.py:1210: in _importer thing = _dot_lookup(thing, comp, import_path) /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/rwt-pcm3552g/mock/mock.py:1199: in _dot_lookup __import__(import_path) E ModuleNotFoundError: No module named 'test_patch_dict.target'; 'test_patch_dict' is not a package !!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ==================================== 1 error in 0.41 seconds ===================================== ``` Is there any reason `patch.dict` doesn't have a similar deferred resolution behavior as its sister methods? ---------- components: Library (Lib) messages: 331937 nosy: jason.coombs priority: normal severity: normal status: open title: patch.dict resolves in_dict eagerly (should be late resolved) _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue35512> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com