]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-120097: Make FrameLocalsProxy a mapping (#120101)
authorMark Shannon <mark@hotpy.org>
Wed, 19 Jun 2024 16:54:13 +0000 (17:54 +0100)
committerGitHub <noreply@github.com>
Wed, 19 Jun 2024 16:54:13 +0000 (17:54 +0100)
* Register FrameLocalsProxy as a subclass of collections.abc.Mapping

* Allow FrameLocalsProxy to matching mapping patterns

Lib/_collections_abc.py
Lib/test/test_frame.py
Misc/NEWS.d/next/Core and Builtins/2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst [new file with mode: 0644]
Objects/frameobject.c

index 1135e17e3790590058dc2aaa70d50f0eea8a01d3..75252b3a87f9c4d541a1f4db3ee5628106816906 100644 (file)
@@ -85,6 +85,10 @@ dict_values = type({}.values())
 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 @@ class Mapping(Collection):
     __reversed__ = None
 
 Mapping.register(mappingproxy)
+Mapping.register(framelocalsproxy)
 
 
 class MappingView(Sized):
index 42f93822a3df604d096bf07efe3c74991f23ad75..b7ef6cefaabbc0b46ddcbaf45a5167ae516146c7 100644 (file)
@@ -11,6 +11,7 @@ try:
 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 @@ class TestFrameLocals(unittest.TestCase):
         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 (file)
index 0000000..39d829b
--- /dev/null
@@ -0,0 +1,2 @@
+``FrameLocalsProxy`` now subclasses ``collections.abc.Mapping`` and can be
+matched as a mapping in ``match`` statements
index 5c65007dae46d2b4e812d60c72ec317724d22fba..860669cfb7d6746d160479546c18790602823602 100644 (file)
@@ -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,