2020-04-02 15:59:44 +00:00
|
|
|
import io
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
from rich.console import Console
|
|
|
|
from rich.traceback import install, Traceback
|
|
|
|
|
2020-08-10 16:01:27 +00:00
|
|
|
# from .render import render
|
2020-04-02 15:59:44 +00:00
|
|
|
|
|
|
|
try:
|
2020-07-16 16:24:16 +00:00
|
|
|
from ._exception_render import expected
|
2020-04-02 15:59:44 +00:00
|
|
|
except ImportError:
|
|
|
|
expected = None
|
|
|
|
|
|
|
|
|
|
|
|
CAPTURED_EXCEPTION = 'Traceback (most recent call last):\n╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\n│ File "/Users/willmcgugan/projects/rich/tests/test_traceback.py", line 26, in test_handler │\n│ 23 try: │\n│ 24 old_handler = install(console=console, line_numbers=False) │\n│ 25 try: │\n│ ❱ 26 1 / 0 │\n│ 27 except Exception: │\n│ 28 exc_type, exc_value, traceback = sys.exc_info() │\n│ 29 sys.excepthook(exc_type, exc_value, traceback) │\n╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\nZeroDivisionError: division by zero\n'
|
|
|
|
|
|
|
|
|
|
|
|
def test_handler():
|
|
|
|
console = Console(file=io.StringIO(), width=100, color_system=None)
|
|
|
|
expected_old_handler = sys.excepthook
|
|
|
|
try:
|
2020-09-26 14:56:27 +00:00
|
|
|
old_handler = install(console=console)
|
2020-04-02 15:59:44 +00:00
|
|
|
try:
|
|
|
|
1 / 0
|
|
|
|
except Exception:
|
|
|
|
exc_type, exc_value, traceback = sys.exc_info()
|
|
|
|
sys.excepthook(exc_type, exc_value, traceback)
|
|
|
|
rendered_exception = console.file.getvalue()
|
|
|
|
print(repr(rendered_exception))
|
2020-04-08 06:27:01 +00:00
|
|
|
assert "Traceback" in rendered_exception
|
|
|
|
assert "ZeroDivisionError" in rendered_exception
|
2020-04-02 15:59:44 +00:00
|
|
|
finally:
|
|
|
|
sys.excepthook = old_handler
|
|
|
|
assert old_handler == expected_old_handler
|
|
|
|
|
|
|
|
|
|
|
|
def text_exception_render():
|
|
|
|
exc_render = render(get_exception())
|
|
|
|
assert exc_render == expected
|
|
|
|
|
|
|
|
|
|
|
|
def test_capture():
|
|
|
|
try:
|
|
|
|
1 / 0
|
|
|
|
except Exception:
|
|
|
|
tb = Traceback()
|
|
|
|
assert tb.trace.stacks[0].exc_type == "ZeroDivisionError"
|
|
|
|
|
|
|
|
|
|
|
|
def test_no_exception():
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
tb = Traceback()
|
|
|
|
|
|
|
|
|
|
|
|
def get_exception() -> Traceback:
|
|
|
|
def bar(a):
|
|
|
|
print(1 / a)
|
|
|
|
|
|
|
|
def foo(a):
|
|
|
|
bar(a)
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
foo(0)
|
|
|
|
except:
|
|
|
|
foobarbaz
|
|
|
|
except:
|
|
|
|
tb = Traceback()
|
|
|
|
return tb
|
|
|
|
|
|
|
|
|
2020-04-27 15:22:39 +00:00
|
|
|
def test_print_exception():
|
|
|
|
console = Console(width=100, file=io.StringIO())
|
|
|
|
try:
|
|
|
|
1 / 0
|
|
|
|
except Exception:
|
|
|
|
console.print_exception()
|
|
|
|
exception_text = console.file.getvalue()
|
|
|
|
assert "ZeroDivisionError" in exception_text
|
|
|
|
|
|
|
|
|
2020-08-10 15:33:45 +00:00
|
|
|
def test_syntax_error():
|
|
|
|
console = Console(width=100, file=io.StringIO())
|
|
|
|
try:
|
|
|
|
# raises SyntaxError: unexpected EOF while parsing
|
|
|
|
eval("(2 + 2")
|
|
|
|
except Exception:
|
|
|
|
console.print_exception()
|
|
|
|
exception_text = console.file.getvalue()
|
|
|
|
assert "SyntaxError" in exception_text
|
|
|
|
|
|
|
|
|
2020-08-10 16:01:27 +00:00
|
|
|
def test_nested_exception():
|
|
|
|
console = Console(width=100, file=io.StringIO())
|
2020-11-29 22:15:11 +00:00
|
|
|
value_error_message = "ValueError because of ZeroDivisionError"
|
2020-08-10 16:01:27 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
1 / 0
|
|
|
|
except ZeroDivisionError:
|
|
|
|
raise ValueError(value_error_message)
|
|
|
|
except Exception:
|
|
|
|
console.print_exception()
|
|
|
|
exception_text = console.file.getvalue()
|
|
|
|
|
|
|
|
text_should_contain = [
|
|
|
|
value_error_message,
|
|
|
|
"ZeroDivisionError",
|
|
|
|
"ValueError",
|
|
|
|
"During handling of the above exception",
|
|
|
|
]
|
|
|
|
|
2020-11-29 22:15:11 +00:00
|
|
|
for msg in text_should_contain:
|
|
|
|
assert msg in exception_text
|
|
|
|
|
|
|
|
# ZeroDivisionError should come before ValueError
|
|
|
|
assert exception_text.find("ZeroDivisionError") < exception_text.find("ValueError")
|
|
|
|
|
|
|
|
|
|
|
|
def test_caused_exception():
|
|
|
|
console = Console(width=100, file=io.StringIO())
|
|
|
|
value_error_message = "ValueError caused by ZeroDivisionError"
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
1 / 0
|
|
|
|
except ZeroDivisionError as e:
|
|
|
|
raise ValueError(value_error_message) from e
|
|
|
|
except Exception:
|
|
|
|
console.print_exception()
|
|
|
|
exception_text = console.file.getvalue()
|
|
|
|
|
|
|
|
text_should_contain = [
|
|
|
|
value_error_message,
|
|
|
|
"ZeroDivisionError",
|
|
|
|
"ValueError",
|
|
|
|
"The above exception was the direct cause",
|
|
|
|
]
|
|
|
|
|
|
|
|
for msg in text_should_contain:
|
|
|
|
assert msg in exception_text
|
2020-08-10 16:01:27 +00:00
|
|
|
|
|
|
|
# ZeroDivisionError should come before ValueError
|
|
|
|
assert exception_text.find("ZeroDivisionError") < exception_text.find("ValueError")
|
|
|
|
|
|
|
|
|
2020-08-10 16:31:28 +00:00
|
|
|
def test_filename_with_bracket():
|
|
|
|
console = Console(width=100, file=io.StringIO())
|
|
|
|
try:
|
|
|
|
exec(compile("1/0", filename="<string>", mode="exec"))
|
|
|
|
except Exception:
|
|
|
|
console.print_exception()
|
|
|
|
exception_text = console.file.getvalue()
|
2020-09-26 14:56:27 +00:00
|
|
|
assert "<string>" in exception_text
|
2020-08-10 16:31:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_filename_not_a_file():
|
|
|
|
console = Console(width=100, file=io.StringIO())
|
|
|
|
try:
|
|
|
|
exec(compile("1/0", filename="string", mode="exec"))
|
|
|
|
except Exception:
|
|
|
|
console.print_exception()
|
|
|
|
exception_text = console.file.getvalue()
|
2020-09-26 14:56:27 +00:00
|
|
|
assert "string" in exception_text
|
2020-08-10 16:31:28 +00:00
|
|
|
|
|
|
|
|
2020-04-27 15:22:39 +00:00
|
|
|
if __name__ == "__main__": # pragma: no cover
|
2020-04-02 15:59:44 +00:00
|
|
|
|
|
|
|
expected = render(get_exception())
|
|
|
|
|
|
|
|
with open("_exception_render.py", "wt") as fh:
|
|
|
|
exc_render = render(get_exception())
|
|
|
|
print(exc_render)
|
|
|
|
fh.write(f"expected={exc_render!r}")
|