https://github.com/python/cpython/commit/d1c673b658977a8e6236feee579308e0ed6a0187
commit: d1c673b658977a8e6236feee579308e0ed6a0187
branch: main
author: Mark Shannon <m...@hotpy.org>
committer: markshannon <m...@hotpy.org>
date: 2024-06-19T17:54:13+01:00
summary:

GH-120097: Make FrameLocalsProxy a mapping (#120101)

* Register FrameLocalsProxy as a subclass of collections.abc.Mapping

* Allow FrameLocalsProxy to matching mapping patterns

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst
M Lib/_collections_abc.py
M Lib/test/test_frame.py
M Objects/frameobject.c

diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py
index 1135e17e379059..75252b3a87f9c4 100644
--- a/Lib/_collections_abc.py
+++ b/Lib/_collections_abc.py
@@ -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
@@ -836,6 +840,7 @@ def __eq__(self, other):
     __reversed__ = None
 
 Mapping.register(mappingproxy)
+Mapping.register(framelocalsproxy)
 
 
 class MappingView(Sized):
diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py
index 42f93822a3df60..b7ef6cefaabbc0 100644
--- a/Lib/test/test_frame.py
+++ b/Lib/test/test_frame.py
@@ -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
@@ -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):
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst
new file mode 100644
index 00000000000000..39d829bb0ed310
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst 
@@ -0,0 +1,2 @@
+``FrameLocalsProxy`` now subclasses ``collections.abc.Mapping`` and can be
+matched as a mapping in ``match`` statements
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 5c65007dae46d2..860669cfb7d674 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -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,

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to