https://github.com/python/cpython/commit/fa291a35eb29c53958aa5d2e2b58aea2441ffca8
commit: fa291a35eb29c53958aa5d2e2b58aea2441ffca8
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: cjw296 <[email protected]>
date: 2024-06-11T06:01:02Z
summary:
[3.12] gh-119600: mock: do not access attributes of original when new_callable
is set (GH-119601) (#120335)
gh-119600: mock: do not access attributes of original when new_callable is set
(GH-119601)
In order to patch flask.g e.g. as in GH-84982, that
proxies getattr must not be invoked. For that,
mock must not try to read from the original
object. In some cases that is unavoidable, e.g.
when doing autospec. However, patch("flask.g",
new_callable=MagicMock) should be entirely safe.
(cherry picked from commit 422c4fc855afd18bcc6415902ea1d85a50cb7ce1)
Co-authored-by: Robert Collins <[email protected]>
files:
A Misc/NEWS.d/next/Library/2024-06-10-14-00-40.gh-issue-119600.jJMf4C.rst
M Lib/test/test_unittest/testmock/support.py
M Lib/test/test_unittest/testmock/testpatch.py
M Lib/unittest/mock.py
diff --git a/Lib/test/test_unittest/testmock/support.py
b/Lib/test/test_unittest/testmock/support.py
index 49986d65dc47af..6c535b7944f261 100644
--- a/Lib/test/test_unittest/testmock/support.py
+++ b/Lib/test/test_unittest/testmock/support.py
@@ -14,3 +14,14 @@ def wibble(self): pass
class X(object):
pass
+
+# A standin for weurkzeug.local.LocalProxy - issue 119600
+def _inaccessible(*args, **kwargs):
+ raise AttributeError
+
+
+class OpaqueProxy:
+ __getattribute__ = _inaccessible
+
+
+g = OpaqueProxy()
diff --git a/Lib/test/test_unittest/testmock/testpatch.py
b/Lib/test/test_unittest/testmock/testpatch.py
index be75fda7826af1..f26e74ce0bc1ba 100644
--- a/Lib/test/test_unittest/testmock/testpatch.py
+++ b/Lib/test/test_unittest/testmock/testpatch.py
@@ -2045,6 +2045,13 @@ def test(): pass
with self.assertRaises(TypeError):
test()
+ def test_patch_proxy_object(self):
+ @patch("test.test_unittest.testmock.support.g",
new_callable=MagicMock())
+ def test(_):
+ pass
+
+ test()
+
if __name__ == '__main__':
unittest.main()
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 486e0c634b82c1..854010c7fb893e 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -1478,13 +1478,12 @@ def __enter__(self):
if isinstance(original, type):
# If we're patching out a class and there is a spec
inherit = True
- if spec is None and _is_async_obj(original):
- Klass = AsyncMock
- else:
- Klass = MagicMock
- _kwargs = {}
+
+ # Determine the Klass to use
if new_callable is not None:
Klass = new_callable
+ elif spec is None and _is_async_obj(original):
+ Klass = AsyncMock
elif spec is not None or spec_set is not None:
this_spec = spec
if spec_set is not None:
@@ -1497,7 +1496,12 @@ def __enter__(self):
Klass = AsyncMock
elif not_callable:
Klass = NonCallableMagicMock
+ else:
+ Klass = MagicMock
+ else:
+ Klass = MagicMock
+ _kwargs = {}
if spec is not None:
_kwargs['spec'] = spec
if spec_set is not None:
diff --git
a/Misc/NEWS.d/next/Library/2024-06-10-14-00-40.gh-issue-119600.jJMf4C.rst
b/Misc/NEWS.d/next/Library/2024-06-10-14-00-40.gh-issue-119600.jJMf4C.rst
new file mode 100644
index 00000000000000..04c9ca9c3fd737
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-06-10-14-00-40.gh-issue-119600.jJMf4C.rst
@@ -0,0 +1,2 @@
+Fix :func:`unittest.mock.patch` to not read attributes of the target when
+``new_callable`` is set. Patch by Robert Collins.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]