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
1 change: 1 addition & 0 deletions news/508.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix `__suppress_context__` not being respected in exception rendering
4 changes: 3 additions & 1 deletion src/cleo/ui/exception_trace/inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ def __init__(self, exception: BaseException) -> None:
self._frames: FrameCollection | None = None
self._outer_frames = None
self._inner_frames = None
self._previous_exception = exception.__context__
self._previous_exception = (
None if exception.__suppress_context__ else exception.__context__
)

@property
def exception(self) -> BaseException:
Expand Down
6 changes: 6 additions & 0 deletions tests/fixtures/exceptions/raiser_with_suppressed_context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

def raiser_with_suppressed_context() -> None:
try:
raise ValueError("This error should be suppressed.")
except ValueError:
raise RuntimeError("This error should be displayed.") from None
42 changes: 36 additions & 6 deletions tests/ui/test_exception_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from cleo.ui.exception_trace.component import ExceptionTrace
from tests.fixtures.exceptions import nested1
from tests.fixtures.exceptions import nested2
from tests.fixtures.exceptions import raiser_with_suppressed_context
from tests.fixtures.exceptions import recursion
from tests.fixtures.exceptions import simple

Expand Down Expand Up @@ -50,7 +51,7 @@ def test_render_debug_better_error_message() -> None:

trace.render(io)

lineno = 47
lineno = 48
expected = f"""
Stack trace:

Expand Down Expand Up @@ -84,7 +85,7 @@ def test_render_debug_better_error_message_recursion_error() -> None:
except RecursionError as e:
trace = ExceptionTrace(e)

lineno = 83
lineno = 84
trace.render(io)

expected = rf"""^
Expand Down Expand Up @@ -131,7 +132,7 @@ def test_render_very_verbose_better_error_message() -> None:
expected = f"""
Stack trace:

1 {trace._get_relative_file_path(__file__)}:125 in \
1 {trace._get_relative_file_path(__file__)}:126 in \
test_render_very_verbose_better_error_message
simple.simple_exception()

Expand Down Expand Up @@ -183,7 +184,7 @@ def test_render_can_ignore_given_files() -> None:
trace.ignore_files_in(rf"^{re.escape(nested1.__file__)}$")
trace.render(io)

lineno = 180
lineno = 181
expected = f"""
Stack trace:

Expand Down Expand Up @@ -221,7 +222,7 @@ def test_render_shows_ignored_files_if_in_debug_mode() -> None:
trace.ignore_files_in(rf"^{re.escape(nested1.__file__)}$")

trace.render(io)
lineno = 218
lineno = 219
expected = f"""
Stack trace:

Expand Down Expand Up @@ -344,7 +345,7 @@ def test_simple_render_aborts_if_no_message() -> None:
trace = ExceptionTrace(e.value)

trace.render(io, simple=True)
lineno = 342
lineno = 343

expected = f"""
AssertionError
Expand All @@ -364,3 +365,32 @@ def test_simple_render_aborts_if_no_message() -> None:
{lineno + 4}│ trace.render(io, simple=True)
"""
assert expected == io.fetch_output()


def test_render_with_suppressed_context() -> None:
io = BufferedIO()
lineno = 6

# Arrange: Trigger and catch the exception
with pytest.raises(RuntimeError) as excinfo:
raiser_with_suppressed_context.raiser_with_suppressed_context()

trace = ExceptionTrace(excinfo.value)

trace.render(io)

expected = f"""\

RuntimeError

This error should be displayed.

at {trace._get_relative_file_path(raiser_with_suppressed_context.__file__)}:{lineno} in raiser_with_suppressed_context
{lineno - 4}│ def raiser_with_suppressed_context() -> None:
{lineno - 3}│ try:
{lineno - 2}│ raise ValueError("This error should be suppressed.")
{lineno - 1}│ except ValueError:
→ {lineno + 0}│ raise RuntimeError("This error should be displayed.") from None
{lineno + 1}│
"""
assert expected == io.fetch_output()
Loading