@@ -111,6 +111,26 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
111111 return ret ;
112112}
113113
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+
114134static int
115135tb_next_set (PyTracebackObject * self , PyObject * new_next , void * Py_UNUSED (_ ))
116136{
@@ -157,12 +177,12 @@ static PyMethodDef tb_methods[] = {
157177static PyMemberDef tb_memberlist [] = {
158178 {"tb_frame" , T_OBJECT , OFF (tb_frame ), READONLY |PY_AUDIT_READ },
159179 {"tb_lasti" , T_INT , OFF (tb_lasti ), READONLY },
160- {"tb_lineno" , T_INT , OFF (tb_lineno ), READONLY },
161180 {NULL } /* Sentinel */
162181};
163182
164183static PyGetSetDef tb_getsetters [] = {
165184 {"tb_next" , (getter )tb_next_get , (setter )tb_next_set , NULL , NULL },
185+ {"tb_lineno" , (getter )tb_lineno_get , NULL , NULL , NULL },
166186 {NULL } /* Sentinel */
167187};
168188
@@ -241,8 +261,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
241261 assert (tb_next == NULL || PyTraceBack_Check (tb_next ));
242262 assert (frame != NULL );
243263 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 );
246265}
247266
248267
@@ -990,23 +1009,27 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,
9901009 }
9911010 while (tb != NULL ) {
9921011 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+ }
9931016 if (last_file == NULL ||
9941017 code -> co_filename != last_file ||
995- last_line == -1 || tb -> tb_lineno != last_line ||
1018+ last_line == -1 || tb_lineno != last_line ||
9961019 last_name == NULL || code -> co_name != last_name ) {
9971020 if (cnt > TB_RECURSIVE_CUTOFF ) {
9981021 if (tb_print_line_repeated (f , cnt ) < 0 ) {
9991022 goto error ;
10001023 }
10011024 }
10021025 last_file = code -> co_filename ;
1003- last_line = tb -> tb_lineno ;
1026+ last_line = tb_lineno ;
10041027 last_name = code -> co_name ;
10051028 cnt = 0 ;
10061029 }
10071030 cnt ++ ;
10081031 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 ,
10101033 tb -> tb_frame , code -> co_name , indent , margin ) < 0 ) {
10111034 goto error ;
10121035 }
0 commit comments