bpo-40421: Add PyFrame_GetCode() function (GH-19757)
PyFrame_GetCode(frame): return a borrowed reference to the frame code. Replace frame->f_code with PyFrame_GetCode(frame) in most code, except in frameobject.c, genobject.c and ceval.c. Also add PyFrame_GetLineNumber() to the limited C API.
This commit is contained in:
parent
b8f704d219
commit
a42ca74fa3
|
@ -1074,8 +1074,10 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
|
||||||
|
|
||||||
.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
|
.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
|
||||||
|
|
||||||
Get the current frame of the Python thread state *tstate*. It can be
|
Get a borrowed reference to the current frame of the Python thread state
|
||||||
``NULL`` if no frame is currently executing.
|
*tstate*.
|
||||||
|
|
||||||
|
Return ``NULL`` if no frame is currently executing.
|
||||||
|
|
||||||
See also :c:func:`PyEval_GetFrame`.
|
See also :c:func:`PyEval_GetFrame`.
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,15 @@ Reflection
|
||||||
See also :c:func:`PyThreadState_GetFrame`.
|
See also :c:func:`PyThreadState_GetFrame`.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: int PyFrame_GetCode(PyFrameObject *frame)
|
||||||
|
|
||||||
|
Return a borrowed reference to the *frame* code.
|
||||||
|
|
||||||
|
*frame* must not be ``NULL``.
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame)
|
.. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame)
|
||||||
|
|
||||||
Return the line number that *frame* is currently executing.
|
Return the line number that *frame* is currently executing.
|
||||||
|
|
|
@ -537,6 +537,10 @@ Optimizations
|
||||||
Build and C API Changes
|
Build and C API Changes
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
* New :c:func:`PyFrame_GetCode` function: return a borrowed reference to the
|
||||||
|
frame code.
|
||||||
|
(Contributed by Victor Stinner in :issue:`40421`.)
|
||||||
|
|
||||||
* Add :c:func:`PyFrame_GetLineNumber` to the limited C API.
|
* Add :c:func:`PyFrame_GetLineNumber` to the limited C API.
|
||||||
(Contributed by Victor Stinner in :issue:`40421`.)
|
(Contributed by Victor Stinner in :issue:`40421`.)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ typedef struct _frame PyFrameObject;
|
||||||
/* Return the line of code the frame is currently executing. */
|
/* Return the line of code the frame is currently executing. */
|
||||||
PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
|
PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyCodeObject *) PyFrame_GetCode(PyFrameObject *frame);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
New :c:func:`PyFrame_GetCode` function: return a borrowed reference to the
|
||||||
|
frame code.
|
|
@ -1,5 +1,4 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "frameobject.h"
|
|
||||||
#include "rotatingtree.h"
|
#include "rotatingtree.h"
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
@ -388,14 +387,16 @@ profiler_callback(PyObject *self, PyFrameObject *frame, int what,
|
||||||
|
|
||||||
/* the 'frame' of a called function is about to start its execution */
|
/* the 'frame' of a called function is about to start its execution */
|
||||||
case PyTrace_CALL:
|
case PyTrace_CALL:
|
||||||
ptrace_enter_call(self, (void *)frame->f_code,
|
{
|
||||||
(PyObject *)frame->f_code);
|
PyCodeObject *code = PyFrame_GetCode(frame);
|
||||||
|
ptrace_enter_call(self, (void *)code, (PyObject *)code);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* the 'frame' of a called function is about to finish
|
/* the 'frame' of a called function is about to finish
|
||||||
(either normally or with an exception) */
|
(either normally or with an exception) */
|
||||||
case PyTrace_RETURN:
|
case PyTrace_RETURN:
|
||||||
ptrace_leave_call(self, (void *)frame->f_code);
|
ptrace_leave_call(self, (void *)PyFrame_GetCode(frame));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* case PyTrace_EXCEPTION:
|
/* case PyTrace_EXCEPTION:
|
||||||
|
|
|
@ -346,7 +346,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
|
||||||
lineno = 0;
|
lineno = 0;
|
||||||
frame->lineno = (unsigned int)lineno;
|
frame->lineno = (unsigned int)lineno;
|
||||||
|
|
||||||
code = pyframe->f_code;
|
code = PyFrame_GetCode(pyframe);
|
||||||
if (code == NULL) {
|
if (code == NULL) {
|
||||||
#ifdef TRACE_DEBUG
|
#ifdef TRACE_DEBUG
|
||||||
tracemalloc_error("failed to get the code object of the frame");
|
tracemalloc_error("failed to get the code object of the frame");
|
||||||
|
|
|
@ -1222,3 +1222,10 @@ _PyFrame_DebugMallocStats(FILE *out)
|
||||||
numfree, sizeof(PyFrameObject));
|
numfree, sizeof(PyFrameObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyCodeObject *
|
||||||
|
PyFrame_GetCode(PyFrameObject *frame)
|
||||||
|
{
|
||||||
|
assert(frame != NULL);
|
||||||
|
return frame->f_code;
|
||||||
|
}
|
||||||
|
|
|
@ -8033,13 +8033,13 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
PyFrameObject *f;
|
PyFrameObject *f;
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
Py_ssize_t i, n;
|
Py_ssize_t i, n;
|
||||||
f = _PyThreadState_GET()->frame;
|
f = PyThreadState_GetFrame(_PyThreadState_GET());
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"super(): no current frame");
|
"super(): no current frame");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
co = f->f_code;
|
co = PyFrame_GetCode(f);
|
||||||
if (co == NULL) {
|
if (co == NULL) {
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"super(): no code object");
|
"super(): no code object");
|
||||||
|
|
|
@ -762,7 +762,6 @@ is_internal_frame(PyFrameObject *frame)
|
||||||
{
|
{
|
||||||
static PyObject *importlib_string = NULL;
|
static PyObject *importlib_string = NULL;
|
||||||
static PyObject *bootstrap_string = NULL;
|
static PyObject *bootstrap_string = NULL;
|
||||||
PyObject *filename;
|
|
||||||
int contains;
|
int contains;
|
||||||
|
|
||||||
if (importlib_string == NULL) {
|
if (importlib_string == NULL) {
|
||||||
|
@ -780,14 +779,23 @@ is_internal_frame(PyFrameObject *frame)
|
||||||
Py_INCREF(bootstrap_string);
|
Py_INCREF(bootstrap_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame == NULL || frame->f_code == NULL ||
|
if (frame == NULL) {
|
||||||
frame->f_code->co_filename == NULL) {
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyCodeObject *code = PyFrame_GetCode(frame);
|
||||||
|
if (code == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *filename = code->co_filename;
|
||||||
|
if (filename == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
filename = frame->f_code->co_filename;
|
|
||||||
if (!PyUnicode_Check(filename)) {
|
if (!PyUnicode_Check(filename)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
contains = PyUnicode_Contains(filename, importlib_string);
|
contains = PyUnicode_Contains(filename, importlib_string);
|
||||||
if (contains < 0) {
|
if (contains < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -846,7 +854,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
globals = f->f_globals;
|
globals = f->f_globals;
|
||||||
*filename = f->f_code->co_filename;
|
*filename = PyFrame_GetCode(f)->co_filename;
|
||||||
Py_INCREF(*filename);
|
Py_INCREF(*filename);
|
||||||
*lineno = PyFrame_GetLineNumber(f);
|
*lineno = PyFrame_GetLineNumber(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "errcode.h"
|
#include "errcode.h"
|
||||||
#include "marshal.h"
|
#include "marshal.h"
|
||||||
#include "code.h"
|
#include "code.h"
|
||||||
#include "frameobject.h"
|
|
||||||
#include "importdl.h"
|
#include "importdl.h"
|
||||||
#include "pydtrace.h"
|
#include "pydtrace.h"
|
||||||
|
|
||||||
|
@ -1536,7 +1535,7 @@ remove_importlib_frames(PyThreadState *tstate)
|
||||||
PyTracebackObject *traceback = (PyTracebackObject *)tb;
|
PyTracebackObject *traceback = (PyTracebackObject *)tb;
|
||||||
PyObject *next = (PyObject *) traceback->tb_next;
|
PyObject *next = (PyObject *) traceback->tb_next;
|
||||||
PyFrameObject *frame = traceback->tb_frame;
|
PyFrameObject *frame = traceback->tb_frame;
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = PyFrame_GetCode(frame);
|
||||||
int now_in_importlib;
|
int now_in_importlib;
|
||||||
|
|
||||||
assert(PyTraceBack_Check(tb));
|
assert(PyTraceBack_Check(tb));
|
||||||
|
|
|
@ -560,24 +560,23 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
||||||
tb = tb->tb_next;
|
tb = tb->tb_next;
|
||||||
}
|
}
|
||||||
while (tb != NULL && err == 0) {
|
while (tb != NULL && err == 0) {
|
||||||
|
PyCodeObject *code = PyFrame_GetCode(tb->tb_frame);
|
||||||
if (last_file == NULL ||
|
if (last_file == NULL ||
|
||||||
tb->tb_frame->f_code->co_filename != last_file ||
|
code->co_filename != last_file ||
|
||||||
last_line == -1 || tb->tb_lineno != last_line ||
|
last_line == -1 || tb->tb_lineno != last_line ||
|
||||||
last_name == NULL || tb->tb_frame->f_code->co_name != last_name) {
|
last_name == NULL || code->co_name != last_name) {
|
||||||
if (cnt > TB_RECURSIVE_CUTOFF) {
|
if (cnt > TB_RECURSIVE_CUTOFF) {
|
||||||
err = tb_print_line_repeated(f, cnt);
|
err = tb_print_line_repeated(f, cnt);
|
||||||
}
|
}
|
||||||
last_file = tb->tb_frame->f_code->co_filename;
|
last_file = code->co_filename;
|
||||||
last_line = tb->tb_lineno;
|
last_line = tb->tb_lineno;
|
||||||
last_name = tb->tb_frame->f_code->co_name;
|
last_name = code->co_name;
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
cnt++;
|
cnt++;
|
||||||
if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) {
|
if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) {
|
||||||
err = tb_displayline(f,
|
err = tb_displayline(f, code->co_filename, tb->tb_lineno,
|
||||||
tb->tb_frame->f_code->co_filename,
|
code->co_name);
|
||||||
tb->tb_lineno,
|
|
||||||
tb->tb_frame->f_code->co_name);
|
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = PyErr_CheckSignals();
|
err = PyErr_CheckSignals();
|
||||||
}
|
}
|
||||||
|
@ -756,7 +755,7 @@ dump_frame(int fd, PyFrameObject *frame)
|
||||||
PyCodeObject *code;
|
PyCodeObject *code;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
code = frame->f_code;
|
code = PyFrame_GetCode(frame);
|
||||||
PUTS(fd, " File ");
|
PUTS(fd, " File ");
|
||||||
if (code != NULL && code->co_filename != NULL
|
if (code != NULL && code->co_filename != NULL
|
||||||
&& PyUnicode_Check(code->co_filename))
|
&& PyUnicode_Check(code->co_filename))
|
||||||
|
|
Loading…
Reference in New Issue