From 3bdabf14d85e7157e0237168a816e4c88e15b06f Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 5 Jun 2024 10:31:27 +0100 Subject: [PATCH 1/4] Make FrameLocalsProxy subclass collections.abc.Mapping --- Lib/_collections_abc.py | 4 ++++ Lib/test/test_frame.py | 12 ++++++++++++ Objects/frameobject.c | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index 1135e17e379059..15ed72ba65b9cf 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -85,6 +85,9 @@ def _f(): pass dict_items = type({}.items()) ## misc ## mappingproxy = type(type.__dict__) +def get_framelocalsproxy(): + return type(sys._getframe().f_locals) +framelocalsproxy = get_framelocalsproxy() generator = type((lambda: (yield))()) ## coroutine ## async def _coro(): pass @@ -836,6 +839,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 aee8d374b22710..b61fa46fd9e3bf 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -13,6 +13,7 @@ except ImportError: _testcapi = None +from collections.abc import Mapping from test import support from test.support import import_helper, threading_helper, Py_GIL_DISABLED from test.support.script_helper import assert_python_ok @@ -420,6 +421,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/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, From ca491ef264e8d5539a8e23a4b103d154a274999c Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 5 Jun 2024 10:32:50 +0100 Subject: [PATCH 2/4] add news --- .../2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst 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 From 544090d6bbceea501672df53952bb17ad937f538 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 7 Jun 2024 16:45:43 +0100 Subject: [PATCH 3/4] Update Lib/_collections_abc.py Co-authored-by: Nikita Sobolev --- Lib/_collections_abc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index 15ed72ba65b9cf..1fcfab38e52198 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -87,7 +87,8 @@ def _f(): pass mappingproxy = type(type.__dict__) def get_framelocalsproxy(): return type(sys._getframe().f_locals) -framelocalsproxy = get_framelocalsproxy() +framelocalsproxy = _get_framelocalsproxy() +del _get_framelocalsproxy generator = type((lambda: (yield))()) ## coroutine ## async def _coro(): pass From d25a8b36905e7f2de6240a6f8eab6d51f52ce0f7 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 10 Jun 2024 09:30:19 +0100 Subject: [PATCH 4/4] Fix renaming --- Lib/_collections_abc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index 1fcfab38e52198..75252b3a87f9c4 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -85,7 +85,7 @@ def _f(): pass dict_items = type({}.items()) ## misc ## mappingproxy = type(type.__dict__) -def get_framelocalsproxy(): +def _get_framelocalsproxy(): return type(sys._getframe().f_locals) framelocalsproxy = _get_framelocalsproxy() del _get_framelocalsproxy