From aa0348d8589c3761b73704f81d1077a044b9e663 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Fri, 10 May 2024 12:52:17 -0700 Subject: [PATCH 1/3] Add copy() method for FrameLocalsProxy --- Lib/test/test_frame.py | 12 +++++++++--- Objects/frameobject.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index 212255374bddd1..ad0304104f6e3b 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -371,6 +371,15 @@ def test_local_objects(self): f_locals['o'] = f_locals['k'] self.assertEqual(o, 'a.b.c') + def test_copy(self): + x = 0 + d = sys._getframe().f_locals + d_copy = d.copy() + self.assertIs(type(d_copy), dict) + self.assertEqual(d_copy['x'], 0) + d_copy['x'] = 1 + self.assertEqual(x, 0) + def test_update_with_self(self): def f(): f_locals = sys._getframe().f_locals @@ -405,9 +414,6 @@ def test_sizeof(self): def test_unsupport(self): x = 1 d = sys._getframe().f_locals - with self.assertRaises(AttributeError): - d.copy() - with self.assertRaises(TypeError): copy.copy(d) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index d7fcb1925d286c..64fded85de1468 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -637,6 +637,23 @@ framelocalsproxy_setdefault(PyObject* self, PyObject *const *args, Py_ssize_t na return result; } +static PyObject* +framelocalsproxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject* result = PyDict_New(); + + if (result == NULL) { + return NULL; + } + + if (PyDict_Update(result, self) < 0) { + Py_DECREF(result); + return NULL; + } + + return result; +} + static PyObject* framelocalsproxy_reversed(PyObject *self, void *Py_UNUSED(ignored)) { @@ -677,6 +694,8 @@ static PyMethodDef framelocalsproxy_methods[] = { NULL}, {"__reversed__", _PyCFunction_CAST(framelocalsproxy_reversed), METH_NOARGS, NULL}, + {"copy", _PyCFunction_CAST(framelocalsproxy_copy), METH_NOARGS, + NULL}, {"keys", _PyCFunction_CAST(framelocalsproxy_keys), METH_NOARGS, NULL}, {"values", _PyCFunction_CAST(framelocalsproxy_values), METH_NOARGS, From 3ecbe358d41e387befbbdb83b725998be1ad00ac Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 19:54:21 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2024-05-10-19-54-18.gh-issue-118921.O4ztZG.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-05-10-19-54-18.gh-issue-118921.O4ztZG.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-10-19-54-18.gh-issue-118921.O4ztZG.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-10-19-54-18.gh-issue-118921.O4ztZG.rst new file mode 100644 index 00000000000000..39ccf472067cfd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-10-19-54-18.gh-issue-118921.O4ztZG.rst @@ -0,0 +1 @@ +Add ``copy()`` method for ``FrameLocalsProxy`` which returns a snapshot ``dict`` for local variables. From 75b71213a784553f23bfd0f8c0fb3263946893eb Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Fri, 10 May 2024 15:07:03 -0700 Subject: [PATCH 3/3] Use assertIsInstance --- Lib/test/test_frame.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index ad0304104f6e3b..aee8d374b22710 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -375,7 +375,7 @@ def test_copy(self): x = 0 d = sys._getframe().f_locals d_copy = d.copy() - self.assertIs(type(d_copy), dict) + self.assertIsInstance(d_copy, dict) self.assertEqual(d_copy['x'], 0) d_copy['x'] = 1 self.assertEqual(x, 0)