@@ -111,6 +111,26 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
111
111
return ret ;
112
112
}
113
113
114
+ static int
115
+ tb_get_lineno (PyTracebackObject * tb ) {
116
+ PyFrameObject * frame = tb -> tb_frame ;
117
+ assert (frame != NULL );
118
+ return PyCode_Addr2Line (PyFrame_GetCode (frame ), tb -> tb_lasti );
119
+ }
120
+
121
+ static PyObject *
122
+ tb_lineno_get (PyTracebackObject * self , void * Py_UNUSED (_ ))
123
+ {
124
+ int lineno = self -> tb_lineno ;
125
+ if (lineno == -1 ) {
126
+ lineno = tb_get_lineno (self );
127
+ if (lineno < 0 ) {
128
+ Py_RETURN_NONE ;
129
+ }
130
+ }
131
+ return PyLong_FromLong (lineno );
132
+ }
133
+
114
134
static int
115
135
tb_next_set (PyTracebackObject * self , PyObject * new_next , void * Py_UNUSED (_ ))
116
136
{
@@ -157,12 +177,12 @@ static PyMethodDef tb_methods[] = {
157
177
static PyMemberDef tb_memberlist [] = {
158
178
{"tb_frame" , T_OBJECT , OFF (tb_frame ), READONLY |PY_AUDIT_READ },
159
179
{"tb_lasti" , T_INT , OFF (tb_lasti ), READONLY },
160
- {"tb_lineno" , T_INT , OFF (tb_lineno ), READONLY },
161
180
{NULL } /* Sentinel */
162
181
};
163
182
164
183
static PyGetSetDef tb_getsetters [] = {
165
184
{"tb_next" , (getter )tb_next_get , (setter )tb_next_set , NULL , NULL },
185
+ {"tb_lineno" , (getter )tb_lineno_get , NULL , NULL , NULL },
166
186
{NULL } /* Sentinel */
167
187
};
168
188
@@ -241,8 +261,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
241
261
assert (tb_next == NULL || PyTraceBack_Check (tb_next ));
242
262
assert (frame != NULL );
243
263
int addr = _PyInterpreterFrame_LASTI (frame -> f_frame ) * sizeof (_Py_CODEUNIT );
244
- return tb_create_raw ((PyTracebackObject * )tb_next , frame , addr ,
245
- PyFrame_GetLineNumber (frame ));
264
+ return tb_create_raw ((PyTracebackObject * )tb_next , frame , addr , -1 );
246
265
}
247
266
248
267
@@ -990,23 +1009,27 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,
990
1009
}
991
1010
while (tb != NULL ) {
992
1011
code = PyFrame_GetCode (tb -> tb_frame );
1012
+ int tb_lineno = tb -> tb_lineno ;
1013
+ if (tb_lineno == -1 ) {
1014
+ tb_lineno = tb_get_lineno (tb );
1015
+ }
993
1016
if (last_file == NULL ||
994
1017
code -> co_filename != last_file ||
995
- last_line == -1 || tb -> tb_lineno != last_line ||
1018
+ last_line == -1 || tb_lineno != last_line ||
996
1019
last_name == NULL || code -> co_name != last_name ) {
997
1020
if (cnt > TB_RECURSIVE_CUTOFF ) {
998
1021
if (tb_print_line_repeated (f , cnt ) < 0 ) {
999
1022
goto error ;
1000
1023
}
1001
1024
}
1002
1025
last_file = code -> co_filename ;
1003
- last_line = tb -> tb_lineno ;
1026
+ last_line = tb_lineno ;
1004
1027
last_name = code -> co_name ;
1005
1028
cnt = 0 ;
1006
1029
}
1007
1030
cnt ++ ;
1008
1031
if (cnt <= TB_RECURSIVE_CUTOFF ) {
1009
- if (tb_displayline (tb , f , code -> co_filename , tb -> tb_lineno ,
1032
+ if (tb_displayline (tb , f , code -> co_filename , tb_lineno ,
1010
1033
tb -> tb_frame , code -> co_name , indent , margin ) < 0 ) {
1011
1034
goto error ;
1012
1035
}
0 commit comments