gh-136492: Add FrameLocalsProxyType to types (GH-136546)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
This commit is contained in:
@@ -333,6 +333,16 @@ Standard names are defined for the following types:
|
||||
:attr:`tb.tb_frame <traceback.tb_frame>` if ``tb`` is a traceback object.
|
||||
|
||||
|
||||
.. data:: FrameLocalsProxyType
|
||||
|
||||
The type of frame locals proxy objects, as found on the
|
||||
:attr:`frame.f_locals` attribute.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. seealso:: :pep:`667`
|
||||
|
||||
|
||||
.. data:: GetSetDescriptorType
|
||||
|
||||
The type of objects defined in extension modules with ``PyGetSetDef``, such
|
||||
|
||||
@@ -312,6 +312,15 @@ tarfile
|
||||
and :cve:`2025-4435`.)
|
||||
|
||||
|
||||
types
|
||||
------
|
||||
|
||||
* Expose the write-through :func:`locals` proxy type
|
||||
as :data:`types.FrameLocalsProxyType`.
|
||||
This represents the type of the :attr:`frame.f_locals` attribute,
|
||||
as described in :pep:`667`.
|
||||
|
||||
|
||||
unittest
|
||||
--------
|
||||
|
||||
|
||||
@@ -5786,6 +5786,7 @@ class TestSignatureDefinitions(unittest.TestCase):
|
||||
'AsyncGeneratorType': {'athrow'},
|
||||
'CoroutineType': {'throw'},
|
||||
'GeneratorType': {'throw'},
|
||||
'FrameLocalsProxyType': {'setdefault', 'pop', 'get'},
|
||||
}
|
||||
self._test_module_has_signatures(types,
|
||||
unsupported_signature=unsupported_signature,
|
||||
|
||||
@@ -53,6 +53,7 @@ class TypesTests(unittest.TestCase):
|
||||
'AsyncGeneratorType', 'BuiltinFunctionType', 'BuiltinMethodType',
|
||||
'CapsuleType', 'CellType', 'ClassMethodDescriptorType', 'CodeType',
|
||||
'CoroutineType', 'EllipsisType', 'FrameType', 'FunctionType',
|
||||
'FrameLocalsProxyType',
|
||||
'GeneratorType', 'GenericAlias', 'GetSetDescriptorType',
|
||||
'LambdaType', 'MappingProxyType', 'MemberDescriptorType',
|
||||
'MethodDescriptorType', 'MethodType', 'MethodWrapperType',
|
||||
@@ -711,6 +712,16 @@ class TypesTests(unittest.TestCase):
|
||||
"""
|
||||
assert_python_ok("-c", code)
|
||||
|
||||
def test_frame_locals_proxy_type(self):
|
||||
self.assertIsInstance(types.FrameLocalsProxyType, type)
|
||||
self.assertIsInstance(types.FrameLocalsProxyType.__doc__, str)
|
||||
self.assertEqual(types.FrameLocalsProxyType.__module__, 'builtins')
|
||||
self.assertEqual(types.FrameLocalsProxyType.__name__, 'FrameLocalsProxy')
|
||||
|
||||
frame = inspect.currentframe()
|
||||
self.assertIsNotNone(frame)
|
||||
self.assertIsInstance(frame.f_locals, types.FrameLocalsProxyType)
|
||||
|
||||
|
||||
class UnionTests(unittest.TestCase):
|
||||
|
||||
|
||||
@@ -58,7 +58,10 @@ except ImportError:
|
||||
raise TypeError
|
||||
except TypeError as exc:
|
||||
TracebackType = type(exc.__traceback__)
|
||||
FrameType = type(exc.__traceback__.tb_frame)
|
||||
|
||||
_f = (lambda: sys._getframe())()
|
||||
FrameType = type(_f)
|
||||
FrameLocalsProxyType = type(_f.f_locals)
|
||||
|
||||
GetSetDescriptorType = type(FunctionType.__code__)
|
||||
MemberDescriptorType = type(FunctionType.__globals__)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Expose :pep:`667`'s :data:`~types.FrameLocalsProxyType` in the :mod:`types` module.
|
||||
@@ -28,6 +28,7 @@ _types_exec(PyObject *m)
|
||||
EXPORT_STATIC_TYPE("CoroutineType", PyCoro_Type);
|
||||
EXPORT_STATIC_TYPE("EllipsisType", PyEllipsis_Type);
|
||||
EXPORT_STATIC_TYPE("FrameType", PyFrame_Type);
|
||||
EXPORT_STATIC_TYPE("FrameLocalsProxyType", PyFrameLocalsProxy_Type);
|
||||
EXPORT_STATIC_TYPE("FunctionType", PyFunction_Type);
|
||||
EXPORT_STATIC_TYPE("GeneratorType", PyGen_Type);
|
||||
EXPORT_STATIC_TYPE("GenericAlias", Py_GenericAliasType);
|
||||
|
||||
@@ -913,6 +913,15 @@ static PyMethodDef framelocalsproxy_methods[] = {
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(framelocalsproxy_doc,
|
||||
"FrameLocalsProxy($frame)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Create a write-through view of the locals dictionary for a frame.\n"
|
||||
"\n"
|
||||
" frame\n"
|
||||
" the frame object to wrap.");
|
||||
|
||||
PyTypeObject PyFrameLocalsProxy_Type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
.tp_name = "FrameLocalsProxy",
|
||||
@@ -933,6 +942,7 @@ PyTypeObject PyFrameLocalsProxy_Type = {
|
||||
.tp_alloc = PyType_GenericAlloc,
|
||||
.tp_new = framelocalsproxy_new,
|
||||
.tp_free = PyObject_GC_Del,
|
||||
.tp_doc = framelocalsproxy_doc,
|
||||
};
|
||||
|
||||
PyObject *
|
||||
|
||||
Reference in New Issue
Block a user