[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