Skip to content

Commit

Permalink
pythonGH-120097: Make FrameLocalsProxy a mapping (python#120101)
Browse files Browse the repository at this point in the history
* Register FrameLocalsProxy as a subclass of collections.abc.Mapping

* Allow FrameLocalsProxy to matching mapping patterns
  • Loading branch information
markshannon authored and noahbkim committed Jul 11, 2024
1 parent a8deb37 commit 387aa06
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Lib/_collections_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ def _f(): pass
dict_items = type({}.items())
## misc ##
mappingproxy = type(type.__dict__)
def _get_framelocalsproxy():
return type(sys._getframe().f_locals)
framelocalsproxy = _get_framelocalsproxy()
del _get_framelocalsproxy
generator = type((lambda: (yield))())
## coroutine ##
async def _coro(): pass
Expand Down Expand Up @@ -836,6 +840,7 @@ def __eq__(self, other):
__reversed__ = None

Mapping.register(mappingproxy)
Mapping.register(framelocalsproxy)


class MappingView(Sized):
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
except ImportError:
_testcapi = None

from collections.abc import Mapping
from test import support
from test.support import import_helper, threading_helper
from test.support.script_helper import assert_python_ok
Expand Down Expand Up @@ -418,6 +419,17 @@ def test_unsupport(self):
with self.assertRaises(TypeError):
copy.deepcopy(d)

def test_is_mapping(self):
x = 1
d = sys._getframe().f_locals
self.assertIsInstance(d, Mapping)
match d:
case {"x": value}:
self.assertEqual(value, 1)
kind = "mapping"
case _:
kind = "other"
self.assertEqual(kind, "mapping")

class TestFrameCApi(unittest.TestCase):
def test_basic(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
``FrameLocalsProxy`` now subclasses ``collections.abc.Mapping`` and can be
matched as a mapping in ``match`` statements
2 changes: 1 addition & 1 deletion Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ PyTypeObject PyFrameLocalsProxy_Type = {
.tp_as_mapping = &framelocalsproxy_as_mapping,
.tp_getattro = PyObject_GenericGetAttr,
.tp_setattro = PyObject_GenericSetAttr,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MAPPING,
.tp_traverse = framelocalsproxy_visit,
.tp_clear = framelocalsproxy_tp_clear,
.tp_richcompare = framelocalsproxy_richcompare,
Expand Down

0 comments on commit 387aa06

Please sign in to comment.