[Python-checkins] bpo-46836: Move PyFrameObject to pycore_frame.h (GH-31530)
vstinner
webhook-mailer at python.org
Fri Feb 25 06:53:30 EST 2022
https://github.com/python/cpython/commit/18b5dd68c6b616257ae243c0b6bb965ffc885a23
commit: 18b5dd68c6b616257ae243c0b6bb965ffc885a23
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-02-25T12:53:19+01:00
summary:
bpo-46836: Move PyFrameObject to pycore_frame.h (GH-31530)
Move the PyFrameObject type definition (struct _frame) to the
internal C API pycore_frame.h header file.
files:
A Misc/NEWS.d/next/C API/2022-02-23-16-13-17.bpo-46836.ZYyPF_.rst
M Doc/c-api/veryhigh.rst
M Doc/whatsnew/3.11.rst
M Include/cpython/frameobject.h
M Include/internal/pycore_frame.h
diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst
index 5b8735de75e9d..2f5720d493d79 100644
--- a/Doc/c-api/veryhigh.rst
+++ b/Doc/c-api/veryhigh.rst
@@ -288,8 +288,16 @@ the same library that the Python runtime is using.
.. c:type:: PyFrameObject
- The C structure of the objects used to describe frame objects. The
- fields of this type are subject to change at any time.
+ The C structure of the objects used to describe frame objects.
+
+ The structure is only part of the internal C API: fields should not be
+ access directly. Use getter functions like :c:func:`PyFrame_GetCode` and
+ :c:func:`PyFrame_GetBack`.
+
+ Debuggers and profilers can use the limited C API to access this structure.
+
+ .. versionchanged:: 3.11
+ The structure moved to the internal C API headers.
.. c:function:: PyObject* PyEval_EvalFrame(PyFrameObject *f)
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 0556a44d4c7d4..3f73bdfa3020f 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -837,40 +837,40 @@ Porting to Python 3.11
which are not available in the limited C API.
(Contributed by Victor Stinner in :issue:`46007`.)
-* Changes of the private :c:type:`PyFrameObject` structure members.
+* The :c:type:`PyFrameObject` structure member has been moved to the internal C
+ API headers.
- While the documentation notes that the fields of ``PyFrameObject`` are
- subject to change at any time, they have been stable for a long time
- and were used in several popular extensions.
- In Python 3.11, the frame struct was reorganized to allow performance
- optimizations. Rather than reading the fields directly, extensions should
- use functions:
+ While the documentation notes that the :c:type:`PyFrameObject` fields are
+ subject to change at any time, they have been stable for a long time and were
+ used in several popular extensions.
- * ``f_code``: removed, use :c:func:`PyFrame_GetCode` instead.
- Warning: the function returns a :term:`strong reference`, need to call
- :c:func:`Py_DECREF`.
- * ``f_back``: changed (see below), use :c:func:`PyFrame_GetBack`.
- * ``f_builtins``: removed,
- use ``PyObject_GetAttrString((PyObject*)frame, "f_builtins")``.
- * ``f_globals``: removed,
- use ``PyObject_GetAttrString((PyObject*)frame, "f_globals")``.
- * ``f_locals``: removed,
- use ``PyObject_GetAttrString((PyObject*)frame, "f_locals")``.
- * ``f_lasti``: removed,
- use ``PyObject_GetAttrString((PyObject*)frame, "f_lasti")``.
- Code using ``f_lasti`` with ``PyCode_Addr2Line()`` should use
+ In Python 3.11, the frame struct was reorganized to allow performance
+ optimizations. Some fields were removed entirely, as they were details of the
+ old implementation.
+
+ :c:type:`PyFrameObject` fields:
+
+ * ``f_back``: use :c:func:`PyFrame_GetBack`.
+ * ``f_blockstack``: removed.
+ * ``f_builtins``: use ``PyObject_GetAttrString((PyObject*)frame, "f_builtins")``.
+ * ``f_code``: use :c:func:`PyFrame_GetCode`.
+ * ``f_gen``: removed.
+ * ``f_globals``: use ``PyObject_GetAttrString((PyObject*)frame, "f_globals")``.
+ * ``f_iblock``: removed.
+ * ``f_lasti``: use ``PyObject_GetAttrString((PyObject*)frame, "f_lasti")``.
+ Code using ``f_lasti`` with ``PyCode_Addr2Line()`` must use
:c:func:`PyFrame_GetLineNumber` instead.
-
- The following fields were removed entirely, as they were details
- of the old implementation:
-
- * ``f_valuesstack``
- * ``f_stackdepth``
- * ``f_gen``
- * ``f_iblock``
- * ``f_state``
- * ``f_blockstack``
- * ``f_localsplus``
+ * ``f_lineno``: use :c:func:`PyFrame_GetLineNumber`
+ * ``f_locals``: use ``PyObject_GetAttrString((PyObject*)frame, "f_locals")``.
+ * ``f_stackdepth``: removed.
+ * ``f_state``: no public API (renamed to ``f_frame.f_state``).
+ * ``f_trace``: no public API.
+ * ``f_trace_lines``: use ``PyObject_GetAttrString((PyObject*)frame, "f_trace_lines")``
+ (it also be modified).
+ * ``f_trace_opcodes``: use ``PyObject_GetAttrString((PyObject*)frame, "f_trace_opcodes")``
+ (it also be modified).
+ * ``f_localsplus``: no public API (renamed to ``f_frame.localsplus``).
+ * ``f_valuestack``: removed.
The Python frame object is now created lazily. A side effect is that the
``f_back`` member must not be accessed directly, since its value is now also
@@ -897,9 +897,9 @@ Porting to Python 3.11
}
#endif
- Or use `the pythoncapi_compat project
- <https://github.com/pythoncapi/pythoncapi_compat>`__ to get these APIs
- on older Python versions.
+ Or use the `pythoncapi_compat project
+ <https://github.com/pythoncapi/pythoncapi_compat>`__ to get these two
+ functions on older Python versions.
* Changes of the :c:type:`PyThreadState` structure members:
diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h
index 3d862d9deb000..e69209686bee0 100644
--- a/Include/cpython/frameobject.h
+++ b/Include/cpython/frameobject.h
@@ -4,19 +4,6 @@
# error "this header file must not be included directly"
#endif
-struct _frame {
- PyObject_HEAD
- PyFrameObject *f_back; /* previous frame, or NULL */
- struct _interpreter_frame *f_frame; /* points to the frame data */
- PyObject *f_trace; /* Trace function */
- int f_lineno; /* Current line number. Only valid if non-zero */
- char f_trace_lines; /* Emit per-line trace events? */
- char f_trace_opcodes; /* Emit per-opcode trace events? */
- char f_owns_frame; /* This frame owns the frame */
- /* The frame data, if this frame object owns the frame */
- PyObject *_f_frame_data[1];
-};
-
/* Standard object interface */
PyAPI_DATA(PyTypeObject) PyFrame_Type;
diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index 1ad156290a55e..09d41222b61fc 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -6,6 +6,18 @@ extern "C" {
#include <stdbool.h>
+struct _frame {
+ PyObject_HEAD
+ PyFrameObject *f_back; /* previous frame, or NULL */
+ struct _interpreter_frame *f_frame; /* points to the frame data */
+ PyObject *f_trace; /* Trace function */
+ int f_lineno; /* Current line number. Only valid if non-zero */
+ char f_trace_lines; /* Emit per-line trace events? */
+ char f_trace_opcodes; /* Emit per-opcode trace events? */
+ char f_owns_frame; /* This frame owns the frame */
+ /* The frame data, if this frame object owns the frame */
+ PyObject *_f_frame_data[1];
+};
/* runtime lifecycle */
diff --git a/Misc/NEWS.d/next/C API/2022-02-23-16-13-17.bpo-46836.ZYyPF_.rst b/Misc/NEWS.d/next/C API/2022-02-23-16-13-17.bpo-46836.ZYyPF_.rst
new file mode 100644
index 0000000000000..2867bfd518c33
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2022-02-23-16-13-17.bpo-46836.ZYyPF_.rst
@@ -0,0 +1,2 @@
+Move the :c:type:`PyFrameObject` type definition (``struct _frame``) to the
+internal C API ``pycore_frame.h`` header file. Patch by Victor Stinner.
More information about the Python-checkins
mailing list