Skip to content

Commit 5405b60

Browse files
markshannonjbower-fb
authored andcommitted
pythonGH-96803: Add three C-API functions to make _PyInterpreterFrame less opaque for users of PEP 523. (pythonGH-96849)
1 parent d3192a2 commit 5405b60

File tree

9 files changed

+48
-8
lines changed

9 files changed

+48
-8
lines changed

Include/cpython/frameobject.h

+17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# error "this header file must not be included directly"
55
#endif
66

7+
struct _PyInterpreterFrame;
8+
79
/* Standard object interface */
810

911
PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *,
@@ -27,3 +29,18 @@ PyAPI_FUNC(int) _PyFrame_IsEntryFrame(PyFrameObject *frame);
2729

2830
PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f);
2931
PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
32+
33+
/* The following functions are for use by debuggers and other tools
34+
* implementing custom frame evaluators with PEP 523. */
35+
36+
/* Returns the code object of the frame (strong reference).
37+
* Does not raise an exception. */
38+
PyAPI_FUNC(PyCodeObject *) PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame);
39+
40+
/* Returns a byte ofsset into the last executed instruction.
41+
* Does not raise an exception. */
42+
PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame);
43+
44+
/* Returns the currently executing line number, or -1 if there is no line number.
45+
* Does not raise an exception. */
46+
PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame);

Include/internal/pycore_frame.h

-2
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,6 @@ _PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_l
265265
return new_frame;
266266
}
267267

268-
int _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame);
269-
270268
static inline
271269
PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
272270
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Add unstable C-API functions to get the code object, lasti and line number from
2+
the internal ``_PyInterpreterFrame`` in the limited API. The functions are:
3+
4+
* ``PyCodeObject * PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)``
5+
* ``int PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)``
6+
* ``int PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame)``

Modules/_tracemalloc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "pycore_runtime.h" // _Py_ID()
88
#include "pycore_traceback.h"
99
#include <pycore_frame.h>
10+
#include "frameobject.h" // _PyInterpreterFrame_GetLine
1011

1112
#include <stdlib.h> // malloc()
1213

@@ -257,7 +258,7 @@ static void
257258
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
258259
{
259260
frame->filename = &_Py_STR(anon_unknown);
260-
int lineno = _PyInterpreterFrame_GetLine(pyframe);
261+
int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
261262
if (lineno < 0) {
262263
lineno = 0;
263264
}

Objects/frameobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ PyFrame_GetLineNumber(PyFrameObject *f)
3838
return f->f_lineno;
3939
}
4040
else {
41-
return _PyInterpreterFrame_GetLine(f->f_frame);
41+
return PyUnstable_InterpreterFrame_GetLine(f->f_frame);
4242
}
4343
}
4444

Objects/genobject.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "pycore_pystate.h" // _PyThreadState_GET()
1313
#include "structmember.h" // PyMemberDef
1414
#include "opcode.h" // SEND
15+
#include "frameobject.h" // _PyInterpreterFrame_GetLine
1516
#include "pystats.h"
1617

1718
static PyObject *gen_close(PyGenObject *, PyObject *);
@@ -1322,7 +1323,7 @@ compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame)
13221323
frame = current_frame;
13231324
for (int i = 0; i < frame_count; ++i) {
13241325
PyCodeObject *code = frame->f_code;
1325-
int line = _PyInterpreterFrame_GetLine(frame);
1326+
int line = PyUnstable_InterpreterFrame_GetLine(frame);
13261327
PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line,
13271328
code->co_name);
13281329
if (!frameinfo) {

Python/ceval.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "pycore_dict.h"
2828
#include "dictobject.h"
2929
#include "pycore_frame.h"
30+
#include "frameobject.h" // _PyInterpreterFrame_GetLine
3031
#include "opcode.h"
3132
#include "pydtrace.h"
3233
#include "setobject.h"
@@ -785,7 +786,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
785786
_PyErr_Format(tstate, PyExc_SystemError,
786787
"%U:%d: unknown opcode %d",
787788
frame->f_code->co_filename,
788-
_PyInterpreterFrame_GetLine(frame),
789+
PyUnstable_InterpreterFrame_GetLine(frame),
789790
opcode);
790791
goto error;
791792

Python/frame.c

+17-1
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,24 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
144144
Py_DECREF(frame->f_funcobj);
145145
}
146146

147+
/* Unstable API functions */
148+
149+
PyCodeObject *
150+
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
151+
{
152+
PyCodeObject *code = frame->f_code;
153+
Py_INCREF(code);
154+
return code;
155+
}
156+
157+
int
158+
PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)
159+
{
160+
return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
161+
}
162+
147163
int
148-
_PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame)
164+
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
149165
{
150166
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
151167
return PyCode_Addr2Line(frame->f_code, addr);

Python/traceback.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
11801180
PUTS(fd, "???");
11811181
}
11821182

1183-
int lineno = _PyInterpreterFrame_GetLine(frame);
1183+
int lineno = PyUnstable_InterpreterFrame_GetLine(frame);
11841184
PUTS(fd, ", line ");
11851185
if (lineno >= 0) {
11861186
_Py_DumpDecimal(fd, (size_t)lineno);

0 commit comments

Comments
 (0)