summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/reflection.rst5
-rw-r--r--Include/code.h3
-rw-r--r--Include/frameobject.h10
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/frameobject.c26
-rw-r--r--Python/_warnings.c2
-rw-r--r--Python/ceval.c2
-rw-r--r--Python/traceback.c3
8 files changed, 35 insertions, 19 deletions
diff --git a/Doc/c-api/reflection.rst b/Doc/c-api/reflection.rst
index 822c593..3996c1f 100644
--- a/Doc/c-api/reflection.rst
+++ b/Doc/c-api/reflection.rst
@@ -29,6 +29,11 @@ Reflection
currently executing.
+.. cfunction:: int PyFrame_GetLineNumber(PyFrameObject *frame)
+
+ Return the line number that *frame* is currently executing.
+
+
.. cfunction:: int PyEval_GetRestricted()
If there is a current frame and it is executing in restricted mode, return true,
diff --git a/Include/code.h b/Include/code.h
index 0167ad4..cbf00d8 100644
--- a/Include/code.h
+++ b/Include/code.h
@@ -75,6 +75,9 @@ PyAPI_FUNC(PyCodeObject *) PyCode_New(
PyAPI_FUNC(PyCodeObject *)
PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno);
+/* Return the line number associated with the specified bytecode index
+ in this code object. If you just need the line number of a frame,
+ use PyFrame_GetLineNumber() instead. */
PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
/* for internal use only */
diff --git a/Include/frameobject.h b/Include/frameobject.h
index 297b66d..17e7679 100644
--- a/Include/frameobject.h
+++ b/Include/frameobject.h
@@ -38,8 +38,11 @@ typedef struct _frame {
PyThreadState *f_tstate;
int f_lasti; /* Last instruction if called */
- /* As of 2.3 f_lineno is only valid when tracing is active (i.e. when
- f_trace is set) -- at other times use PyCode_Addr2Line instead. */
+ /* Call PyFrame_GetLineNumber() instead of reading this field
+ directly. As of 2.3 f_lineno is only valid when tracing is
+ active (i.e. when f_trace is set). At other times we use
+ PyCode_Addr2Line to calculate the line from the current
+ bytecode index. */
int f_lineno; /* Current line number */
int f_iblock; /* index in f_blockstack */
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
@@ -77,6 +80,9 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
+/* Return the line of code the frame is currently executing. */
+PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
+
#ifdef __cplusplus
}
#endif
diff --git a/Misc/NEWS b/Misc/NEWS
index ba721e7..fa362fd 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -927,6 +927,9 @@ Build
C-API
-----
+- Issue #5954: Add a PyFrame_GetLineNumber() function to replace most uses of
+ PyCode_Addr2Line().
+
- Issue #5959: Add a PyCode_NewEmpty() function to create a new empty code
object at a specified file, function, and line number.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 4ac1ab0..7a9d40d 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -60,17 +60,19 @@ frame_getlocals(PyFrameObject *f, void *closure)
return f->f_locals;
}
-static PyObject *
-frame_getlineno(PyFrameObject *f, void *closure)
+int
+PyFrame_GetLineNumber(PyFrameObject *f)
{
- int lineno;
-
if (f->f_trace)
- lineno = f->f_lineno;
+ return f->f_lineno;
else
- lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
+ return PyCode_Addr2Line(f->f_code, f->f_lasti);
+}
- return PyInt_FromLong(lineno);
+static PyObject *
+frame_getlineno(PyFrameObject *f, void *closure)
+{
+ return PyInt_FromLong(PyFrame_GetLineNumber(f));
}
/* Setter for f_lineno - you can set f_lineno from within a trace function in
@@ -351,16 +353,14 @@ frame_gettrace(PyFrameObject *f, void *closure)
static int
frame_settrace(PyFrameObject *f, PyObject* v, void *closure)
{
- /* We rely on f_lineno being accurate when f_trace is set. */
+ PyObject* old_value;
- PyObject* old_value = f->f_trace;
+ /* We rely on f_lineno being accurate when f_trace is set. */
+ f->f_lineno = PyFrame_GetLineNumber(f);
+ old_value = f->f_trace;
Py_XINCREF(v);
f->f_trace = v;
-
- if (v != NULL)
- f->f_lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
-
Py_XDECREF(old_value);
return 0;
diff --git a/Python/_warnings.c b/Python/_warnings.c
index 1a7c2d5..219cfc6 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -454,7 +454,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
}
else {
globals = f->f_globals;
- *lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
+ *lineno = PyFrame_GetLineNumber(f);
}
*module = NULL;
diff --git a/Python/ceval.c b/Python/ceval.c
index 88b9d0e..474a885 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2698,7 +2698,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
default:
fprintf(stderr,
"XXX lineno: %d, opcode: %d\n",
- PyCode_Addr2Line(f->f_code, f->f_lasti),
+ PyFrame_GetLineNumber(f),
opcode);
PyErr_SetString(PyExc_SystemError, "unknown opcode");
why = WHY_EXCEPTION;
diff --git a/Python/traceback.c b/Python/traceback.c
index c2d7e77..1c26ba2 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -96,8 +96,7 @@ newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
Py_XINCREF(frame);
tb->tb_frame = frame;
tb->tb_lasti = frame->f_lasti;
- tb->tb_lineno = PyCode_Addr2Line(frame->f_code,
- frame->f_lasti);
+ tb->tb_lineno = PyFrame_GetLineNumber(frame);
PyObject_GC_Track(tb);
}
return tb;