Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions Doc/c-api/reflection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Reflection

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

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


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

Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.9.rst
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,9 @@ Optimizations
Build and C API Changes
=======================

* Add :c:func:`PyFrame_GetLineNumber` to the limited C API.
(Contributed by Victor Stinner in :issue:`40421`.)

* New :c:func:`PyThreadState_GetInterpreter` and
:c:func:`PyInterpreterState_Get` functions to get the interpreter.
New :c:func:`PyThreadState_GetFrame` function to get the current frame of a
Expand Down
1 change: 1 addition & 0 deletions Include/Python.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
#include "classobject.h"
#include "fileobject.h"
#include "pycapsule.h"
#include "pyframe.h"
#include "traceback.h"
#include "sliceobject.h"
#include "cellobject.h"
Expand Down
8 changes: 3 additions & 5 deletions Include/ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyEval_CallFunction(
Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyEval_CallMethod(
PyObject *obj, const char *name, const char *format, ...);

struct _frame; /* Avoid including frameobject.h */

PyAPI_FUNC(PyObject *) PyEval_GetBuiltins(void);
PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void);
PyAPI_FUNC(PyObject *) PyEval_GetLocals(void);
PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void);
PyAPI_FUNC(PyFrameObject *) PyEval_GetFrame(void);

PyAPI_FUNC(int) Py_AddPendingCall(int (*func)(void *), void *arg);
PyAPI_FUNC(int) Py_MakePendingCalls(void);
Expand Down Expand Up @@ -80,8 +78,8 @@ PyAPI_FUNC(void) Py_LeaveRecursiveCall(void);
PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *);
PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *);

PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *);
PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc);
PyAPI_FUNC(PyObject *) PyEval_EvalFrame(PyFrameObject *);
PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(PyFrameObject *f, int exc);

/* Interface for threads.

Expand Down
2 changes: 1 addition & 1 deletion Include/cpython/ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *);
flag was set, else return 0. */
PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);

PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _frame *f, int exc);
PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int exc);

PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds);
PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void);
Expand Down
7 changes: 2 additions & 5 deletions Include/cpython/frameobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ typedef struct {
int b_level; /* value stack level to pop to */
} PyTryBlock;

typedef struct _frame {
struct _frame {
PyObject_VAR_HEAD
struct _frame *f_back; /* previous frame, or NULL */
PyCodeObject *f_code; /* code segment */
Expand Down Expand Up @@ -44,7 +44,7 @@ typedef struct _frame {
char f_executing; /* whether the frame is still executing */
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
} PyFrameObject;
};


/* Standard object interface */
Expand Down Expand Up @@ -79,9 +79,6 @@ PyAPI_FUNC(int) PyFrame_ClearFreeList(void);

PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out);

/* Return the line of code the frame is currently executing. */
PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);

#ifdef __cplusplus
}
#endif
6 changes: 3 additions & 3 deletions Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ PyAPI_FUNC(PyObject *) _PyInterpreterState_GetMainModule(PyInterpreterState *);
/* State unique per thread */

/* Py_tracefunc return -1 when raising an exception, or 0 for success. */
typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *);
typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *);

/* The following values are used for 'what' for tracefunc functions
*
Expand Down Expand Up @@ -56,7 +56,7 @@ struct _ts {
PyInterpreterState *interp;

/* Borrowed reference to the current frame (it can be NULL) */
struct _frame *frame;
PyFrameObject *frame;
int recursion_depth;
char overflowed; /* The stack has overflowed. Allow 50 more calls
to handle the runtime error. */
Expand Down Expand Up @@ -184,7 +184,7 @@ PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void);

/* Frame evaluation API */

typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, struct _frame *, int);
typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, PyFrameObject *, int);

PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc(
PyInterpreterState *interp);
Expand Down
2 changes: 1 addition & 1 deletion Include/cpython/traceback.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern "C" {
typedef struct _traceback {
PyObject_HEAD
struct _traceback *tb_next;
struct _frame *tb_frame;
PyFrameObject *tb_frame;
int tb_lasti;
int tb_lineno;
} PyTracebackObject;
Expand Down
4 changes: 1 addition & 3 deletions Include/frameobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
extern "C" {
#endif

/* There are currently no frame related APIs in the stable ABI
* (they're all in the full CPython-specific API)
*/
#include "pyframe.h"

#ifndef Py_LIMITED_API
# define Py_CPYTHON_FRAMEOBJECT_H
Expand Down
12 changes: 5 additions & 7 deletions Include/genobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ extern "C" {

#include "pystate.h" /* _PyErr_StackItem */

struct _frame; /* Avoid including frameobject.h */

/* _PyGenObject_HEAD defines the initial segment of generator
and coroutine objects. */
#define _PyGenObject_HEAD(prefix) \
PyObject_HEAD \
/* Note: gi_frame can be NULL if the generator is "finished" */ \
struct _frame *prefix##_frame; \
PyFrameObject *prefix##_frame; \
/* True if generator is being executed. */ \
char prefix##_running; \
/* The code object backing the generator */ \
Expand All @@ -40,8 +38,8 @@ PyAPI_DATA(PyTypeObject) PyGen_Type;
#define PyGen_Check(op) PyObject_TypeCheck(op, &PyGen_Type)
#define PyGen_CheckExact(op) Py_IS_TYPE(op, &PyGen_Type)

PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *);
PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(struct _frame *,
PyAPI_FUNC(PyObject *) PyGen_New(PyFrameObject *);
PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(PyFrameObject *,
PyObject *name, PyObject *qualname);
PyAPI_FUNC(int) _PyGen_SetStopIterationValue(PyObject *);
PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **);
Expand All @@ -60,7 +58,7 @@ PyAPI_DATA(PyTypeObject) _PyCoroWrapper_Type;

#define PyCoro_CheckExact(op) Py_IS_TYPE(op, &PyCoro_Type)
PyObject *_PyCoro_GetAwaitableIter(PyObject *o);
PyAPI_FUNC(PyObject *) PyCoro_New(struct _frame *,
PyAPI_FUNC(PyObject *) PyCoro_New(PyFrameObject *,
PyObject *name, PyObject *qualname);

/* Asynchronous Generators */
Expand All @@ -86,7 +84,7 @@ PyAPI_DATA(PyTypeObject) _PyAsyncGenASend_Type;
PyAPI_DATA(PyTypeObject) _PyAsyncGenWrappedValue_Type;
PyAPI_DATA(PyTypeObject) _PyAsyncGenAThrow_Type;

PyAPI_FUNC(PyObject *) PyAsyncGen_New(struct _frame *,
PyAPI_FUNC(PyObject *) PyAsyncGen_New(PyFrameObject *,
PyObject *name, PyObject *qualname);

#define PyAsyncGen_CheckExact(op) Py_IS_TYPE(op, &PyAsyncGen_Type)
Expand Down
3 changes: 1 addition & 2 deletions Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ extern "C" {
/* Forward declarations */
struct pyruntimestate;
struct _ceval_runtime_state;
struct _frame;

#include "pycore_interp.h" /* PyInterpreterState.eval_frame */

Expand All @@ -36,7 +35,7 @@ PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(
void _PyEval_Fini(void);

static inline PyObject*
_PyEval_EvalFrame(PyThreadState *tstate, struct _frame *f, int throwflag)
_PyEval_EvalFrame(PyThreadState *tstate, PyFrameObject *f, int throwflag)
{
return tstate->interp->eval_frame(tstate, f, throwflag);
}
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_traceback.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ PyAPI_FUNC(void) _Py_DumpHexadecimal(

PyAPI_FUNC(PyObject*) _PyTraceBack_FromFrame(
PyObject *tb_next,
struct _frame *frame);
PyFrameObject *frame);

#ifdef __cplusplus
}
Expand Down
20 changes: 20 additions & 0 deletions Include/pyframe.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* Limited C API of PyFrame API
*
* Include "frameobject.h" to get the PyFrameObject structure.
*/

#ifndef Py_PYFRAME_H
#define Py_PYFRAME_H
#ifdef __cplusplus
extern "C" {
#endif

typedef struct _frame PyFrameObject;

/* Return the line of code the frame is currently executing. */
PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);

#ifdef __cplusplus
}
#endif
#endif /* !Py_PYFRAME_H */
3 changes: 1 addition & 2 deletions Include/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ removed (with effort). */

/* Forward declarations for PyFrameObject, PyThreadState
and PyInterpreterState */
struct _frame;
struct _ts;
struct _is;

Expand Down Expand Up @@ -88,7 +87,7 @@ PyAPI_FUNC(int) PyThreadState_SetAsyncExc(unsigned long, PyObject *);
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000
/* New in 3.9 */
PyAPI_FUNC(PyInterpreterState*) PyThreadState_GetInterpreter(PyThreadState *tstate);
PyAPI_FUNC(struct _frame*) PyThreadState_GetFrame(PyThreadState *tstate);
PyAPI_FUNC(PyFrameObject*) PyThreadState_GetFrame(PyThreadState *tstate);
PyAPI_FUNC(uint64_t) PyThreadState_GetID(PyThreadState *tstate);
#endif

Expand Down
4 changes: 1 addition & 3 deletions Include/traceback.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
extern "C" {
#endif

struct _frame;

/* Traceback interface */

PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *);
PyAPI_FUNC(int) PyTraceBack_Here(PyFrameObject *);
PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *);

/* Reveal traceback type so we can typecheck traceback objects */
Expand Down
1 change: 1 addition & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/pydtrace.h \
$(srcdir)/Include/pyerrors.h \
$(srcdir)/Include/pyfpe.h \
$(srcdir)/Include/pyframe.h \
$(srcdir)/Include/pyhash.h \
$(srcdir)/Include/pylifecycle.h \
$(srcdir)/Include/pymacconfig.h \
Expand Down
7 changes: 5 additions & 2 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ frame_getlocals(PyFrameObject *f, void *closure)
int
PyFrame_GetLineNumber(PyFrameObject *f)
{
if (f->f_trace)
assert(f != NULL);
if (f->f_trace) {
return f->f_lineno;
else
}
else {
return PyCode_Addr2Line(f->f_code, f->f_lasti);
}
}

static PyObject *
Expand Down
15 changes: 8 additions & 7 deletions PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\Include\Python-ast.h" />
<ClInclude Include="..\Include\Python.h" />
<ClInclude Include="..\Include\abstract.h" />
<ClInclude Include="..\Include\asdl.h" />
<ClInclude Include="..\Include\ast.h" />
Expand Down Expand Up @@ -165,8 +167,8 @@
<ClInclude Include="..\Include\internal\pycore_abstract.h" />
<ClInclude Include="..\Include\internal\pycore_accu.h" />
<ClInclude Include="..\Include\internal\pycore_atomic.h" />
<ClInclude Include="..\Include\internal\pycore_byteswap.h" />
<ClInclude Include="..\Include\internal\pycore_bytes_methods.h" />
<ClInclude Include="..\Include\internal\pycore_byteswap.h" />
<ClInclude Include="..\Include\internal\pycore_call.h" />
<ClInclude Include="..\Include\internal\pycore_ceval.h" />
<ClInclude Include="..\Include\internal\pycore_code.h" />
Expand Down Expand Up @@ -214,7 +216,6 @@
<ClInclude Include="..\Include\parsetok.h" />
<ClInclude Include="..\Include\patchlevel.h" />
<ClInclude Include="..\Include\picklebufobject.h" />
<ClInclude Include="..\Include\pyhash.h" />
<ClInclude Include="..\Include\py_curses.h" />
<ClInclude Include="..\Include\pyarena.h" />
<ClInclude Include="..\Include\pycapsule.h" />
Expand All @@ -223,20 +224,20 @@
<ClInclude Include="..\Include\pyerrors.h" />
<ClInclude Include="..\Include\pyexpat.h" />
<ClInclude Include="..\Include\pyfpe.h" />
<ClInclude Include="..\Include\pyframe.h" />
<ClInclude Include="..\Include\pyhash.h" />
<ClInclude Include="..\Include\pylifecycle.h" />
<ClInclude Include="..\Include\pymath.h" />
<ClInclude Include="..\Include\pytime.h" />
<ClInclude Include="..\Include\pymacro.h" />
<ClInclude Include="..\Include\pymath.h" />
<ClInclude Include="..\Include\pymem.h" />
<ClInclude Include="..\Include\pyport.h" />
<ClInclude Include="..\Include\pystate.h" />
<ClInclude Include="..\Include\pystrcmp.h" />
<ClInclude Include="..\Include\pystrtod.h" />
<ClInclude Include="..\Include\pystrhex.h" />
<ClInclude Include="..\Include\Python-ast.h" />
<ClInclude Include="..\Include\Python.h" />
<ClInclude Include="..\Include\pystrtod.h" />
<ClInclude Include="..\Include\pythonrun.h" />
<ClInclude Include="..\Include\pythread.h" />
<ClInclude Include="..\Include\pytime.h" />
<ClInclude Include="..\Include\rangeobject.h" />
<ClInclude Include="..\Include\setobject.h" />
<ClInclude Include="..\Include\sliceobject.h" />
Expand Down
3 changes: 3 additions & 0 deletions PCbuild/pythoncore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@
<ClInclude Include="..\Include\internal\pycore_pyerrors.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_pyframe.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_pyhash.h">
<Filter>Include</Filter>
</ClInclude>
Expand Down