@@ -109,6 +109,26 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
109
109
return Py_NewRef (ret );
110
110
}
111
111
112
+ static int
113
+ tb_get_lineno (PyTracebackObject * tb ) {
114
+ _PyInterpreterFrame * frame = tb -> tb_frame -> f_frame ;
115
+ assert (frame != NULL );
116
+ return PyCode_Addr2Line (_PyFrame_GetCode (frame ), tb -> tb_lasti );
117
+ }
118
+
119
+ static PyObject *
120
+ tb_lineno_get (PyTracebackObject * self , void * Py_UNUSED (_ ))
121
+ {
122
+ int lineno = self -> tb_lineno ;
123
+ if (lineno == -1 ) {
124
+ lineno = tb_get_lineno (self );
125
+ if (lineno < 0 ) {
126
+ Py_RETURN_NONE ;
127
+ }
128
+ }
129
+ return PyLong_FromLong (lineno );
130
+ }
131
+
112
132
static int
113
133
tb_next_set (PyTracebackObject * self , PyObject * new_next , void * Py_UNUSED (_ ))
114
134
{
@@ -152,12 +172,12 @@ static PyMethodDef tb_methods[] = {
152
172
static PyMemberDef tb_memberlist [] = {
153
173
{"tb_frame" , _Py_T_OBJECT , OFF (tb_frame ), Py_READONLY |Py_AUDIT_READ },
154
174
{"tb_lasti" , Py_T_INT , OFF (tb_lasti ), Py_READONLY },
155
- {"tb_lineno" , Py_T_INT , OFF (tb_lineno ), Py_READONLY },
156
175
{NULL } /* Sentinel */
157
176
};
158
177
159
178
static PyGetSetDef tb_getsetters [] = {
160
179
{"tb_next" , (getter )tb_next_get , (setter )tb_next_set , NULL , NULL },
180
+ {"tb_lineno" , (getter )tb_lineno_get , NULL , NULL , NULL },
161
181
{NULL } /* Sentinel */
162
182
};
163
183
@@ -236,8 +256,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
236
256
assert (tb_next == NULL || PyTraceBack_Check (tb_next ));
237
257
assert (frame != NULL );
238
258
int addr = _PyInterpreterFrame_LASTI (frame -> f_frame ) * sizeof (_Py_CODEUNIT );
239
- return tb_create_raw ((PyTracebackObject * )tb_next , frame , addr ,
240
- PyFrame_GetLineNumber (frame ));
259
+ return tb_create_raw ((PyTracebackObject * )tb_next , frame , addr , -1 );
241
260
}
242
261
243
262
@@ -681,23 +700,27 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
681
700
}
682
701
while (tb != NULL ) {
683
702
code = PyFrame_GetCode (tb -> tb_frame );
703
+ int tb_lineno = tb -> tb_lineno ;
704
+ if (tb_lineno == -1 ) {
705
+ tb_lineno = tb_get_lineno (tb );
706
+ }
684
707
if (last_file == NULL ||
685
708
code -> co_filename != last_file ||
686
- last_line == -1 || tb -> tb_lineno != last_line ||
709
+ last_line == -1 || tb_lineno != last_line ||
687
710
last_name == NULL || code -> co_name != last_name ) {
688
711
if (cnt > TB_RECURSIVE_CUTOFF ) {
689
712
if (tb_print_line_repeated (f , cnt ) < 0 ) {
690
713
goto error ;
691
714
}
692
715
}
693
716
last_file = code -> co_filename ;
694
- last_line = tb -> tb_lineno ;
717
+ last_line = tb_lineno ;
695
718
last_name = code -> co_name ;
696
719
cnt = 0 ;
697
720
}
698
721
cnt ++ ;
699
722
if (cnt <= TB_RECURSIVE_CUTOFF ) {
700
- if (tb_displayline (tb , f , code -> co_filename , tb -> tb_lineno ,
723
+ if (tb_displayline (tb , f , code -> co_filename , tb_lineno ,
701
724
tb -> tb_frame , code -> co_name ) < 0 ) {
702
725
goto error ;
703
726
}
0 commit comments