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
22 changes: 13 additions & 9 deletions cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

import rich.box
from rich.console import Group
from rich.highlighter import ReprHighlighter
from rich.rule import Rule
from rich.style import Style, StyleType
from rich.table import (
Expand Down Expand Up @@ -1365,18 +1366,21 @@ def pexcept(
console.print()
return

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

highlighter = ReprHighlighter()
if exception_str:
highlighter = ReprHighlighter()

final_msg = Text.assemble(
("EXCEPTION of type ", Cmd2Style.ERROR),
(f"{type(exception).__name__}", Cmd2Style.EXCEPTION_TYPE),
(" occurred with message: ", Cmd2Style.ERROR),
highlighter(str(exception)),
)
final_msg = Text.assemble(
(f"{type(exception).__name__}: ", "traceback.exc_type"),
highlighter(exception_str),
)
else:
final_msg = Text(f"{type(exception).__name__}", style="traceback.exc_type")

# If not in debug mode and the 'debug' setting is available,
# inform the user how to enable full tracebacks.
if not self.debug and 'debug' in self.settables:
help_msg = Text.assemble(
"\n\n",
Expand Down
34 changes: 16 additions & 18 deletions tests/test_cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,8 +895,8 @@ def test_base_debug(base_app) -> None:

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

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

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

# Since debug is unsettable, the user will not be given the option to enable a full traceback
assert err == ['Invalid syntax: No closing quotation']
assert err == ["ValueError: Please use 'set editor' to specify your text editing program of", 'choice.']


def test_blank_exception(mocker, base_app):
mocker.patch("cmd2.Cmd.do_help", side_effect=Exception)
out, err = run_cmd(base_app, 'help')

# When an exception has no message, the first error line is just its type.
assert err[0] == "Exception"


def test_remove_settable_keyerror(base_app) -> None:
Expand Down Expand Up @@ -2668,8 +2677,7 @@ def test_pexcept_style(base_app, capsys) -> None:

base_app.pexcept(msg)
out, err = capsys.readouterr()
expected = su.stylize("EXCEPTION of type ", style=Cmd2Style.ERROR)
expected += su.stylize("Exception", style=Cmd2Style.EXCEPTION_TYPE)
expected = su.stylize("Exception: ", style="traceback.exc_type")
assert err.startswith(expected)


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

base_app.pexcept(msg)
out, err = capsys.readouterr()
assert err.startswith("EXCEPTION of type Exception occurred with message: testing...")


@with_ansi_style(ru.AllowStyle.NEVER)
def test_pexcept_not_exception(base_app, capsys) -> None:
# Pass in a msg that is not an Exception object
msg = False

base_app.pexcept(msg)
out, err = capsys.readouterr()
assert err.startswith("EXCEPTION of type bool occurred with message: False")
assert err.startswith("Exception: testing...")


@pytest.mark.parametrize('chop', [True, False])
Expand Down
Loading