Skip to content

Commit 5c420e3

Browse files
committed
Formatting an exception like Rich does after a traceback.
1 parent 96465a8 commit 5c420e3

File tree

2 files changed

+29
-27
lines changed

2 files changed

+29
-27
lines changed

cmd2/cmd2.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565

6666
import rich.box
6767
from rich.console import Group
68+
from rich.highlighter import ReprHighlighter
6869
from rich.rule import Rule
6970
from rich.style import Style, StyleType
7071
from rich.table import (
@@ -1365,18 +1366,21 @@ def pexcept(
13651366
console.print()
13661367
return
13671368

1368-
# Otherwise highlight and print the exception.
1369-
from rich.highlighter import ReprHighlighter
1369+
# Print the exception in the same style Rich uses after a traceback.
1370+
exception_str = str(exception)
13701371

1371-
highlighter = ReprHighlighter()
1372+
if exception_str:
1373+
highlighter = ReprHighlighter()
13721374

1373-
final_msg = Text.assemble(
1374-
("EXCEPTION of type ", Cmd2Style.ERROR),
1375-
(f"{type(exception).__name__}", Cmd2Style.EXCEPTION_TYPE),
1376-
(" occurred with message: ", Cmd2Style.ERROR),
1377-
highlighter(str(exception)),
1378-
)
1375+
final_msg = Text.assemble(
1376+
(f"{type(exception).__name__}: ", "traceback.exc_type"),
1377+
highlighter(exception_str),
1378+
)
1379+
else:
1380+
final_msg = Text(f"{type(exception).__name__}", style="traceback.exc_type")
13791381

1382+
# If not in debug mode and the 'debug' setting is available,
1383+
# inform the user how to enable full tracebacks.
13801384
if not self.debug and 'debug' in self.settables:
13811385
help_msg = Text.assemble(
13821386
"\n\n",

tests/test_cmd2.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -895,8 +895,8 @@ def test_base_debug(base_app) -> None:
895895

896896
# Make sure we get an exception, but cmd2 handles it
897897
out, err = run_cmd(base_app, 'edit')
898-
assert "EXCEPTION of type" in err[0]
899-
assert "Please use 'set editor'" in err[0]
898+
assert "ValueError: Please use 'set editor'" in err[0]
899+
assert "To enable full traceback" in err[3]
900900

901901
# Set debug true
902902
out, err = run_cmd(base_app, 'set debug True')
@@ -918,11 +918,20 @@ def test_debug_not_settable(base_app) -> None:
918918
base_app.debug = False
919919
base_app.remove_settable('debug')
920920

921-
# Cause an exception
922-
out, err = run_cmd(base_app, 'bad "quote')
921+
# Cause an exception by setting editor to None and running edit
922+
base_app.editor = None
923+
out, err = run_cmd(base_app, 'edit')
923924

924925
# Since debug is unsettable, the user will not be given the option to enable a full traceback
925-
assert err == ['Invalid syntax: No closing quotation']
926+
assert err == ["ValueError: Please use 'set editor' to specify your text editing program of", 'choice.']
927+
928+
929+
def test_blank_exception(mocker, base_app):
930+
mocker.patch("cmd2.Cmd.do_help", side_effect=Exception)
931+
out, err = run_cmd(base_app, 'help')
932+
933+
# When an exception has no message, the first error line is just its type.
934+
assert err[0] == "Exception"
926935

927936

928937
def test_remove_settable_keyerror(base_app) -> None:
@@ -2668,8 +2677,7 @@ def test_pexcept_style(base_app, capsys) -> None:
26682677

26692678
base_app.pexcept(msg)
26702679
out, err = capsys.readouterr()
2671-
expected = su.stylize("EXCEPTION of type ", style=Cmd2Style.ERROR)
2672-
expected += su.stylize("Exception", style=Cmd2Style.EXCEPTION_TYPE)
2680+
expected = su.stylize("Exception: ", style="traceback.exc_type")
26732681
assert err.startswith(expected)
26742682

26752683

@@ -2679,17 +2687,7 @@ def test_pexcept_no_style(base_app, capsys) -> None:
26792687

26802688
base_app.pexcept(msg)
26812689
out, err = capsys.readouterr()
2682-
assert err.startswith("EXCEPTION of type Exception occurred with message: testing...")
2683-
2684-
2685-
@with_ansi_style(ru.AllowStyle.NEVER)
2686-
def test_pexcept_not_exception(base_app, capsys) -> None:
2687-
# Pass in a msg that is not an Exception object
2688-
msg = False
2689-
2690-
base_app.pexcept(msg)
2691-
out, err = capsys.readouterr()
2692-
assert err.startswith("EXCEPTION of type bool occurred with message: False")
2690+
assert err.startswith("Exception: testing...")
26932691

26942692

26952693
@pytest.mark.parametrize('chop', [True, False])

0 commit comments

Comments
 (0)