@@ -107,6 +107,26 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
107
107
return Py_NewRef (ret );
108
108
}
109
109
110
+ static int
111
+ tb_get_lineno (PyTracebackObject * tb ) {
112
+ PyFrameObject * frame = tb -> tb_frame ;
113
+ assert (frame != NULL );
114
+ return PyCode_Addr2Line (PyFrame_GetCode (frame ), tb -> tb_lasti );
115
+ }
116
+
117
+ static PyObject *
118
+ tb_lineno_get (PyTracebackObject * self , void * Py_UNUSED (_ ))
119
+ {
120
+ int lineno = self -> tb_lineno ;
121
+ if (lineno == -1 ) {
122
+ lineno = tb_get_lineno (self );
123
+ if (lineno < 0 ) {
124
+ Py_RETURN_NONE ;
125
+ }
126
+ }
127
+ return PyLong_FromLong (lineno );
128
+ }
129
+
110
130
static int
111
131
tb_next_set (PyTracebackObject * self , PyObject * new_next , void * Py_UNUSED (_ ))
112
132
{
@@ -150,12 +170,12 @@ static PyMethodDef tb_methods[] = {
150
170
static PyMemberDef tb_memberlist [] = {
151
171
{"tb_frame" , T_OBJECT , OFF (tb_frame ), READONLY |PY_AUDIT_READ },
152
172
{"tb_lasti" , T_INT , OFF (tb_lasti ), READONLY },
153
- {"tb_lineno" , T_INT , OFF (tb_lineno ), READONLY },
154
173
{NULL } /* Sentinel */
155
174
};
156
175
157
176
static PyGetSetDef tb_getsetters [] = {
158
177
{"tb_next" , (getter )tb_next_get , (setter )tb_next_set , NULL , NULL },
178
+ {"tb_lineno" , (getter )tb_lineno_get , NULL , NULL , NULL },
159
179
{NULL } /* Sentinel */
160
180
};
161
181
@@ -234,8 +254,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
234
254
assert (tb_next == NULL || PyTraceBack_Check (tb_next ));
235
255
assert (frame != NULL );
236
256
int addr = _PyInterpreterFrame_LASTI (frame -> f_frame ) * sizeof (_Py_CODEUNIT );
237
- return tb_create_raw ((PyTracebackObject * )tb_next , frame , addr ,
238
- PyFrame_GetLineNumber (frame ));
257
+ return tb_create_raw ((PyTracebackObject * )tb_next , frame , addr , -1 );
239
258
}
240
259
241
260
@@ -983,34 +1002,30 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,
983
1002
}
984
1003
while (tb != NULL ) {
985
1004
code = PyFrame_GetCode (tb -> tb_frame );
1005
+ int tb_lineno = tb -> tb_lineno ;
1006
+ if (tb_lineno == -1 ) {
1007
+ tb_lineno = tb_get_lineno (tb );
1008
+ }
986
1009
if (last_file == NULL ||
987
1010
code -> co_filename != last_file ||
988
- last_line == -1 || tb -> tb_lineno != last_line ||
1011
+ last_line == -1 || tb_lineno != last_line ||
989
1012
last_name == NULL || code -> co_name != last_name ) {
990
1013
if (cnt > TB_RECURSIVE_CUTOFF ) {
991
1014
if (tb_print_line_repeated (f , cnt ) < 0 ) {
992
1015
goto error ;
993
1016
}
994
1017
}
995
1018
last_file = code -> co_filename ;
996
- last_line = tb -> tb_lineno ;
1019
+ last_line = tb_lineno ;
997
1020
last_name = code -> co_name ;
998
1021
cnt = 0 ;
999
1022
}
1000
1023
cnt ++ ;
1001
1024
if (cnt <= TB_RECURSIVE_CUTOFF ) {
1002
- if (tb_displayline (tb , f , code -> co_filename , tb -> tb_lineno ,
1025
+ if (tb_displayline (tb , f , code -> co_filename , tb_lineno ,
1003
1026
tb -> tb_frame , code -> co_name , indent , margin ) < 0 ) {
1004
- goto error ;
1005
1027
}
1006
1028
1007
- if (PyErr_CheckSignals () < 0 ) {
1008
- goto error ;
1009
- }
1010
- }
1011
- Py_CLEAR (code );
1012
- tb = tb -> tb_next ;
1013
- }
1014
1029
if (cnt > TB_RECURSIVE_CUTOFF ) {
1015
1030
if (tb_print_line_repeated (f , cnt ) < 0 ) {
1016
1031
goto error ;
0 commit comments