summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTian Gao <gaogaotiantian@hotmail.com>2024-05-10 22:53:10 (GMT)
committerGitHub <noreply@github.com>2024-05-10 22:53:10 (GMT)
commit35c436186b849f8f2f9fb866c59015c9d034d448 (patch)
tree7546150928886fe4527122625682ecc69dd10835
parentb88889e9ffd7b2d2bdac75aecbf14e37fd68e337 (diff)
downloadcpython-35c436186b849f8f2f9fb866c59015c9d034d448.zip
cpython-35c436186b849f8f2f9fb866c59015c9d034d448.tar.gz
cpython-35c436186b849f8f2f9fb866c59015c9d034d448.tar.bz2
gh-118921: Add `copy()` method for `FrameLocalsProxy` (#118923)
-rw-r--r--Lib/test/test_frame.py12
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-05-10-19-54-18.gh-issue-118921.O4ztZG.rst1
-rw-r--r--Objects/frameobject.c19
3 files changed, 29 insertions, 3 deletions
diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py
index 2122553..aee8d37 100644
--- a/Lib/test/test_frame.py
+++ b/Lib/test/test_frame.py
@@ -371,6 +371,15 @@ class TestFrameLocals(unittest.TestCase):
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.assertIsInstance(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 @@ class TestFrameLocals(unittest.TestCase):
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/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 0000000..39ccf47
--- /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.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index d7fcb19..64fded8 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -638,6 +638,23 @@ framelocalsproxy_setdefault(PyObject* self, PyObject *const *args, Py_ssize_t na
}
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))
{
PyObject *result = framelocalsproxy_keys(self, NULL);
@@ -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,