Skip to content

Commit cd90034

Browse files
committed
gh-126935: added handler frame to output of traceback of a chained exception
1 parent d6b3e78 commit cd90034

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

Lib/traceback.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -397,18 +397,32 @@ def walk_tb(tb):
397397
tb = tb.tb_next
398398

399399

400-
def _walk_tb_with_full_positions(tb):
400+
def _get_tb_position(tb):
401+
positions = _get_code_position(tb.tb_frame.f_code, tb.tb_lasti)
402+
# Yield tb_lineno when co_positions does not have a line number to
403+
# maintain behavior with walk_tb.
404+
if positions[0] is None:
405+
return tb.tb_frame, (tb.tb_lineno, ) + positions[1:]
406+
return tb.tb_frame, positions
407+
408+
409+
def _walk_tb_with_full_positions(tb, _seen=None):
401410
# Internal version of walk_tb that yields full code positions including
402411
# end line and column information.
412+
handler_tb = None
403413
while tb is not None:
404-
positions = _get_code_position(tb.tb_frame.f_code, tb.tb_lasti)
405-
# Yield tb_lineno when co_positions does not have a line number to
406-
# maintain behavior with walk_tb.
407-
if positions[0] is None:
408-
yield tb.tb_frame, (tb.tb_lineno, ) + positions[1:]
409-
else:
410-
yield tb.tb_frame, positions
414+
yield _get_tb_position(tb)
415+
if tb.tb_lineno != tb.tb_frame.f_lineno and _seen:
416+
for exc in reversed(_seen.values()):
417+
if (handler_tb := exc.__traceback__) is not tb:
418+
while handler_tb.tb_lineno != tb.tb_frame.f_lineno:
419+
if not (handler_tb := handler_tb.tb_next):
420+
break
421+
else:
422+
break
411423
tb = tb.tb_next
424+
if handler_tb:
425+
yield _get_tb_position(handler_tb)
412426

413427

414428
def _get_code_position(code, instruction_index):
@@ -1035,14 +1049,14 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
10351049
# Handle loops in __cause__ or __context__.
10361050
is_recursive_call = _seen is not None
10371051
if _seen is None:
1038-
_seen = set()
1039-
_seen.add(id(exc_value))
1052+
_seen = {}
1053+
_seen[id(exc_value)] = exc_value
10401054

10411055
self.max_group_width = max_group_width
10421056
self.max_group_depth = max_group_depth
10431057

10441058
self.stack = StackSummary._extract_from_extended_frame_gen(
1045-
_walk_tb_with_full_positions(exc_traceback),
1059+
_walk_tb_with_full_positions(exc_traceback, _seen),
10461060
limit=limit, lookup_lines=lookup_lines,
10471061
capture_locals=capture_locals)
10481062

0 commit comments

Comments
 (0)