Skip to content

Commit 35c4361

Browse files
gh-118921: Add copy() method for FrameLocalsProxy (#118923)
1 parent b88889e commit 35c4361

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

Diff for: Lib/test/test_frame.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,15 @@ def test_local_objects(self):
371371
f_locals['o'] = f_locals['k']
372372
self.assertEqual(o, 'a.b.c')
373373

374+
def test_copy(self):
375+
x = 0
376+
d = sys._getframe().f_locals
377+
d_copy = d.copy()
378+
self.assertIsInstance(d_copy, dict)
379+
self.assertEqual(d_copy['x'], 0)
380+
d_copy['x'] = 1
381+
self.assertEqual(x, 0)
382+
374383
def test_update_with_self(self):
375384
def f():
376385
f_locals = sys._getframe().f_locals
@@ -405,9 +414,6 @@ def test_sizeof(self):
405414
def test_unsupport(self):
406415
x = 1
407416
d = sys._getframe().f_locals
408-
with self.assertRaises(AttributeError):
409-
d.copy()
410-
411417
with self.assertRaises(TypeError):
412418
copy.copy(d)
413419

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ``copy()`` method for ``FrameLocalsProxy`` which returns a snapshot ``dict`` for local variables.

Diff for: Objects/frameobject.c

+19
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,23 @@ framelocalsproxy_setdefault(PyObject* self, PyObject *const *args, Py_ssize_t na
637637
return result;
638638
}
639639

640+
static PyObject*
641+
framelocalsproxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
642+
{
643+
PyObject* result = PyDict_New();
644+
645+
if (result == NULL) {
646+
return NULL;
647+
}
648+
649+
if (PyDict_Update(result, self) < 0) {
650+
Py_DECREF(result);
651+
return NULL;
652+
}
653+
654+
return result;
655+
}
656+
640657
static PyObject*
641658
framelocalsproxy_reversed(PyObject *self, void *Py_UNUSED(ignored))
642659
{
@@ -677,6 +694,8 @@ static PyMethodDef framelocalsproxy_methods[] = {
677694
NULL},
678695
{"__reversed__", _PyCFunction_CAST(framelocalsproxy_reversed), METH_NOARGS,
679696
NULL},
697+
{"copy", _PyCFunction_CAST(framelocalsproxy_copy), METH_NOARGS,
698+
NULL},
680699
{"keys", _PyCFunction_CAST(framelocalsproxy_keys), METH_NOARGS,
681700
NULL},
682701
{"values", _PyCFunction_CAST(framelocalsproxy_values), METH_NOARGS,

0 commit comments

Comments
 (0)