diff options
author | Mark Shannon <mark@hotpy.org> | 2024-06-19 16:54:13 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-19 16:54:13 (GMT) |
commit | d1c673b658977a8e6236feee579308e0ed6a0187 (patch) | |
tree | 7202eaae095a36918a8d72503c9bbf9af9786205 | |
parent | 00257c746c447a2e026b5a2a618f0e033fb90111 (diff) | |
download | cpython-d1c673b658977a8e6236feee579308e0ed6a0187.zip cpython-d1c673b658977a8e6236feee579308e0ed6a0187.tar.gz cpython-d1c673b658977a8e6236feee579308e0ed6a0187.tar.bz2 |
GH-120097: Make FrameLocalsProxy a mapping (#120101)
* Register FrameLocalsProxy as a subclass of collections.abc.Mapping
* Allow FrameLocalsProxy to matching mapping patterns
-rw-r--r-- | Lib/_collections_abc.py | 5 | ||||
-rw-r--r-- | Lib/test/test_frame.py | 12 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2024-06-05-10-32-44.gh-issue-120097.9S2klk.rst | 2 | ||||
-rw-r--r-- | Objects/frameobject.c | 2 |
4 files changed, 20 insertions, 1 deletions
diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index 1135e17..75252b3 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -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): diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index 42f9382..b7ef6ce 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -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 index 0000000..39d829b --- /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 5c65007..860669c 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, |