◐ Shell
clean mode source ↗

gh-141004: Document unstable executable kind macros in `pyframe.h` by Yashp002 · Pull Request #143490 · python/cpython

@Yashp002

@Yashp002 Yashp002 commented

Jan 6, 2026

edited by github-actions Bot

Loading

gh-141004: Document unstable executable kind macros in pyframe.h

This PR documents the PyUnstable_EXECUTABLE_KIND_* macros and the PyUnstable_ExecutableKinds array in Doc/c-api/frame.rst. These were listed as undocumented in the parent issue.


📚 Documentation preview 📚: https://cpython-previews--143490.org.readthedocs.build/

StanFromIreland

Index for the "skip" kind in ``PyUnstable_ExecutableKinds``.
Indicates that the frame's code object should be skipped.

.. versionadded:: 3.12

Choose a reason for hiding this comment

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

9c03215 was not backported to 3.12?

@encukou

These are rather useless without docs for PyUnstable_ExecutableKinds.
Once you document that, you can associate the macros with it, like for example Py_MOD_GIL_USED with Py_mod_gil.

@Yashp002

@encukou ok, makes sense. I'll add the documentation for PyUnstable_ExecutableKinds and link these macros to it. Thanks :)

encukou

Comment on lines +255 to +257

An enumeration of the different kinds of executables (code objects) in a frame.
This can be one of the constants :c:macro:`PyUnstable_EXECUTABLE_KIND_SKIP`
or :c:macro:`PyUnstable_EXECUTABLE_KIND_PY_FUNCTION`.

Choose a reason for hiding this comment

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

It's an array, not an enum.
Could you document what it's useful for or how to use it? That part isn't very clear to me.

Choose a reason for hiding this comment

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

Please go through what i've mentioned below and let me know if its perfectly appropriate, and as soon I recieve the heads up i'll update and commit:

.. c:var:: PyUnstable_ExecutableKinds

An array of executable kinds (executor types) for frames, used for internal
debugging and tracing. The entries are indexed by the constants
:c:macro:PyUnstable_EXECUTABLE_KIND_SKIP or
:c:macro:PyUnstable_EXECUTABLE_KIND_PY_FUNCTION.

This can be used to identify the type of the code object associated with a frame.

.. versionadded:: 3.13

Choose a reason for hiding this comment

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

Could @encukou or @StanFromIreland please review my suggestion above and correct it if its wrong or gimme the green light to commit this ⬆️

Choose a reason for hiding this comment

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

I'd prefer some words on why/how you'd use this.

You can say “The entries are indexed by the following constants:”, and indent the docs for the constants. Since the entries are all similar, you could even use a compact table, like in code object flags.

ZeroIntensity

Choose a reason for hiding this comment

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

You need to update ignored_c_api.txt here too.

Comment on lines +296 to +298

Choose a reason for hiding this comment

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

Too many blank lines.


.. c:macro:: PyUnstable_EXECUTABLE_KIND_PY_FUNCTION

Index for the "Python function" kind in ``PyUnstable_ExecutableKinds``.

Choose a reason for hiding this comment

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

These should be links via :c:data:`PyUnstable_ExecutableKinds`

@Yashp002

test_asyncio.test_sendfile port conflict - unrelated to docs.

@StanFromIreland

We don't need those tests to run at all really, we can (I think) exclude the ignore file from triggering the run-tests condition.

Edit: See #143583.

@Yashp002

We don't need those tests to run at all really, we can (I think) exclude the ignore file from triggering the run-tests condition.

Edit: See #143583.

Can the same be said for #143492
and #143494 then? @StanFromIreland

@Yashp002

@encukou

This part is not clear to me:

Tools like debuggers and profilers can use this to identify the type of execution
context associated with a frame (e.g. to filter out internal frames).

I assume “frame” refers to PyFrameObject?
How do you use this array to filter out internal frames?


Once the docs say what the function is for and how to use it, there are some presentation issues to fix up:

There are now two descriptions for PyUnstable_EXECUTABLE_KIND_SKIP: on in list-table and one below. Choose one. If you need a full/sentence, use individual entries; if you only need a few words then the table makes sense.
Either way, indent the macro docs so they're under PyUnstable_ExecutableKinds, and use .. c:namespace:: NULL (see elsewhere in the docs for examples).

@Yashp002

@encukou Since PyUnstable_EXECUTABLE_KIND_SKIP has only a couple words, should I just keep the list-table description and remove the one below completely?
image
as in the description of it below.

Also, Yes the frame refers to PyFrameObject and I'll be adding a sentence below saying "The frame should be skipped by tools.
- The frame corresponds to a standard Py function"

    Also, to check for internal frames:
    perf_map = PyUnstable_GetPerfMapFile()
    for i, kind in enumerate(perf_map):
       if kind == PyUnstable_EXECUTABLE_KIND_SKIP:
          skip_frame(i) 
          
          It's from the Cpython source code

Should i go ahead with above mentioned changes?
Also, my indents with c:macro: are fine right? or have i missed something

@encukou

Since PyUnstable_EXECUTABLE_KIND_SKIP has only a couple words, should I just keep the list-table description and remove the one below completely?

Yes. But switch to the .. c:macro: syntax rather than :c:macro:, so this is a definition.

Example code would be very helpful, yes. Please test that it works, though.

StanFromIreland

debugging and tracing.

Tools like debuggers and profilers can use this to identify the type of execution
context associated with a frame (e.g. to filter out internal frames).

Choose a reason for hiding this comment

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

Please do not use latin abbreviations, see our style guide for more information.

Choose a reason for hiding this comment

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

Yeah you mentioned this before, I'm sorry it slipped my mind, fixing now.

* - .. c:macro:: PyUnstable_EXECUTABLE_KIND_PY_FUNCTION
- The frame corresponds to a standard Python function.

.. versionadded:: 3.13

Choose a reason for hiding this comment

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

The .. versionadded:: ... should be the last thing in a function's/macro's/type's/etc. doc, please move it after the example.

encukou

.. code-block:: c

// Check if a frame should be skipped
if (kind == PyUnstable_EXECUTABLE_KIND_SKIP) {

Choose a reason for hiding this comment

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

What is kind? How do you get it?

Choose a reason for hiding this comment

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

@encukou kind here refers to the executable kind field stored in the frame's executor (e.g. _PyFrame_GetExecutableKind(frame))
Do you think it's better to explicitly show _PyFrame_GetExecutableKind (if exposed), or should I just remove the example block to avoid confusion?

Choose a reason for hiding this comment

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

Yes, explicitly show your _PyFrame_GetExecutableKind. We'll also need to make it public (or at least unstable) if we want users to use it.

@Yashp002

@encukou could u check if these changes are satisfactory

@encukou

How did you check that the example code works?

@Yashp002

@encukou
i've made changes to

modified: Doc/c-api/frame.rst
modified: Include/cpython/frameobject.h
modified: Modules/_testcapi/frame.c
modified: Python/frame.c

the tests seem to pass and the build works

vstinner

return PyLong_FromLong(kind);
}

return PyLong_FromLong(kind);

Choose a reason for hiding this comment

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

This test emits a DeprecationWarning:

ERROR: test_my_doc_example (test.test_capi.test_misc.Test_testcapi.test_my_doc_example)
----------------------------------------------------------------------
DeprecationWarning: It is deprecated to return a value that is not None from a test case (<built-in function test_my_doc_example> returned 'int')

Choose a reason for hiding this comment

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

@vstinner Honestly, i think im a little stuck on this issue, could you help?

@github-actions

This PR is stale because it has been open for 30 days with no activity.