Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions IPython/core/tests/test_ultratb.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ class Python3ChainedExceptionsTest(unittest.TestCase):
raise ValueError("Yikes") from None
"""

SYS_EXIT_WITH_CONTEXT_CODE = """
try:
1/0
except Exception as e:
raise SystemExit(1)
"""

def test_direct_cause_error(self):
with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
Expand All @@ -306,6 +313,11 @@ def test_exception_during_handling_error(self):
with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)

def test_sysexit_while_handling_error(self):
with tt.AssertPrints(["SystemExit", "to see the full traceback"]):
with tt.AssertNotPrints(["another exception"], suppress=False):
ip.run_cell(self.SYS_EXIT_WITH_CONTEXT_CODE)

def test_suppress_exception_chaining(self):
with tt.AssertNotPrints("ZeroDivisionError"), \
tt.AssertPrints("ValueError", suppress=False):
Expand Down
43 changes: 23 additions & 20 deletions IPython/core/ultratb.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,28 +552,31 @@ def structured_traceback(
lines = ''.join(self._format_exception_only(etype, evalue))
out_list.append(lines)

exception = self.get_parts_of_chained_exception(evalue)
# Find chained exceptions if we have a traceback (not for exception-only mode)
if etb is not None:
exception = self.get_parts_of_chained_exception(evalue)

if exception and (id(exception[1]) not in chained_exc_ids):
chained_exception_message = (
self.prepare_chained_exception_message(evalue.__cause__)[0]
if evalue is not None
else ""
)
etype, evalue, etb = exception
# Trace exception to avoid infinite 'cause' loop
chained_exc_ids.add(id(exception[1]))
chained_exceptions_tb_offset = 0
out_list = (
self.structured_traceback(
etype,
evalue,
(etb, chained_exc_ids), # type: ignore
chained_exceptions_tb_offset,
context,
if exception and (id(exception[1]) not in chained_exc_ids):
chained_exception_message = (
self.prepare_chained_exception_message(evalue.__cause__)[0]
if evalue is not None
else ""
)
etype, evalue, etb = exception
# Trace exception to avoid infinite 'cause' loop
chained_exc_ids.add(id(exception[1]))
chained_exceptions_tb_offset = 0
out_list = (
self.structured_traceback(
etype,
evalue,
(etb, chained_exc_ids), # type: ignore
chained_exceptions_tb_offset,
context,
)
+ chained_exception_message
+ out_list
)
+ chained_exception_message
+ out_list)

return out_list

Expand Down