Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 72417) +++ Python/ceval.c (working copy) @@ -2698,7 +2698,7 @@ 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; Index: Python/traceback.c =================================================================== --- Python/traceback.c (revision 72417) +++ Python/traceback.c (working copy) @@ -96,8 +96,7 @@ 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; Index: Python/_warnings.c =================================================================== --- Python/_warnings.c (revision 72417) +++ Python/_warnings.c (working copy) @@ -454,7 +454,7 @@ } else { globals = f->f_globals; - *lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + *lineno = PyFrame_GetLineNumber(f); } *module = NULL; Index: Include/code.h =================================================================== --- Include/code.h (revision 72417) +++ Include/code.h (working copy) @@ -70,6 +70,10 @@ int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *); /* same as struct above */ + +/* 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 */ Index: Include/frameobject.h =================================================================== --- Include/frameobject.h (revision 72417) +++ Include/frameobject.h (working copy) @@ -38,8 +38,11 @@ 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(int) PyFrame_ClearFreeList(void); +/* Return the line of code the frame is currently executing. */ +PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *); + #ifdef __cplusplus } #endif Index: Objects/frameobject.c =================================================================== --- Objects/frameobject.c (revision 72417) +++ Objects/frameobject.c (working copy) @@ -60,17 +60,19 @@ 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 @@ static int frame_settrace(PyFrameObject *f, PyObject* v, void *closure) { + PyObject* old_value; + /* We rely on f_lineno being accurate when f_trace is set. */ + f->f_lineno = PyFrame_GetLineNumber(f); - PyObject* old_value = f->f_trace; - + 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;