8000 bpo-46836: Add Doc/c-api/frame.rst by vstinner · Pull Request #32051 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-46836: Add Doc/c-api/frame.rst #32051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Doc/c-api/concrete.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Other Objects
memoryview.rst
weakref.rst
capsule.rst
frame.rst
gen.rst
coro.rst
contextvars.rst
Expand Down
75 changes: 75 additions & 0 deletions Doc/c-api/frame.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
.. highlight:: c

Frame Objects
-------------

.. c:type:: PyFrameObject

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 internal C API to access this structure
without calling functions, but the internal C API doesn't provide any
backward compatibility warranty.

.. versionchanged:: 3.11
The structure moved to the internal C API headers.

Public members:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be much safer to just say "don't access fields directly".

For example, f_lineno is not valid most of the time, we use it as an internal cache when tracing. f_back can be NULL even if the Python attribute is not None. Setting f_trace_lines or f_trace_opcodes may not do anything, as the change won't visible to the VM.

Copy link
Member Author
@vstinner vstinner Mar 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the PR to clarify that these members are part of the Python API. My idea is just to explain that the Python API can be accessed in C as well.

Setting f_trace_lines or f_trace_opcodes may not do anything, as the change won't visible to the VM.

Well, it's technically possible to do that in pure Python. If there is a bug, it should be either documented or fixed. For example, disallow setting f_trace_lines and f_trace_opcodes.

Currently, f_trace_lines and f_trace_opcodes are not documented. IMO it's better to document them. If there are limits, we can document them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The struct fields cannot be safely accessed by C code. The limit is that you can't do it.
The Python attributes can be safely modified by PyObject_GetAttr etc.


* ``f_back`` (read only): Next outer frame object (this frame's caller).
See also: :c:func:`PyFrame_GetBack`.
* ``f_builtins`` (read only): Builtins namespace seen by this frame.
* ``f_code`` (read only): Code object being executed in this frame.
See also :c:func:`PyFrame_GetCode`.
* ``f_globals`` (read only): Global namespace seen by this frame.
* ``f_lasti`` (read only): Index of last attempted instruction in bytecode.
* ``f_lineno``: Current line number in Python source code.
See also :c:func:`PyFrame_GetLineNumber`.
* ``f_locals`` (read only): Local namespace seen by this frame.
* ``f_trace_lines``: Emit ``PyTrace_LINE`` trace events?
* ``f_trace_opcodes``: Emit ``PyTrace_OPCODE`` trace events?
* ``f_trace``: Tracing function for this frame, or ``None``

The :c:func:`PyObject_GetAttrString` and :c:func:`PyObject_SetAttrString`
functions can be used to get and set these members. For example,
``PyObject_GetAttrString((PyObject*)frame, "f_builtins")`` gets the frame
builtins namespace.

The :c:func:`PyEval_GetFrame` and :c:func:`PyThreadState_GetFrame` functions
can be used to get a frame object.

See also :ref:`Reflection <reflection>`.


.. c:function:: PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)

Get the *frame* next outer frame.

Return a :term:`strong reference`, or ``NULL`` if *frame* has no outer
frame.

*frame* must not be ``NULL``.

.. versionadded:: 3.9


.. c:function:: PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)

Get the *frame* code.

Return a :term:`strong reference`.

*frame* must not be ``NULL``. The result (frame code) cannot be ``NULL``.

.. versionadded:: 3.9


.. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame)

Return the line number that *frame* is currently executing.

*frame* must not be ``NULL``.
29 changes: 0 additions & 29 deletions Doc/c-api/reflection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,35 +31,6 @@ Reflection
See also :c:func:`PyThreadState_GetFrame`.


.. c:function:: PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)

Get the *frame* next outer frame.

Return a :term:`strong reference`, or ``NULL`` if *frame* has no outer frame.

*frame* must not be ``NULL``.

.. versionadded:: 3.9


.. c:function:: PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)

Get the *frame* code.

Return a :term:`strong reference`.

*frame* must not be ``NULL``. The result (frame code) cannot be ``NULL``.

.. versionadded:: 3.9


.. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame)

Return the line number that *frame* is currently executing.

*frame* must not be ``NULL``.


.. c:function:: const char* PyEval_GetFuncName(PyObject *func)

Return the name of *func* if it is a function, class or instance object, else the
Expand Down
14 changes: 0 additions & 14 deletions Doc/c-api/veryhigh.rst
Original file line number Diff line number Diff line change
Expand Up @@ -286,20 +286,6 @@ the same library that the Python runtime is using.
<keyword-only_parameter>` arguments and a closure tuple of cells.


.. c:type:: PyFrameObject

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)

Evaluate an execution frame. This is a simplified interface to
Expand Down
6 changes: 2 additions & 4 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -968,10 +968,8 @@ Porting to Python 3.11
* ``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_trace_lines``: use ``PyObject_GetAttrString((PyObject*)frame, "f_trace_lines")``.
* ``f_trace_opcodes``: use ``PyObject_GetAttrString((PyObject*)frame, "f_trace_opcodes")``.
* ``f_localsplus``: no public API (renamed to ``f_frame.localsplus``).
* ``f_valuestack``: removed.

Expand Down
0