|
1 | 1 | import io |
| 2 | +import re |
2 | 3 | import sys |
3 | 4 |
|
4 | 5 | import pytest |
|
21 | 22 | def test_handler(): |
22 | 23 | console = Console(file=io.StringIO(), width=100, color_system=None) |
23 | 24 | expected_old_handler = sys.excepthook |
| 25 | + |
| 26 | + def level1(): |
| 27 | + level2() |
| 28 | + |
| 29 | + def level2(): |
| 30 | + return 1 / 0 |
| 31 | + |
24 | 32 | try: |
25 | 33 | old_handler = install(console=console) |
26 | 34 | try: |
27 | | - 1 / 0 |
| 35 | + level1() |
28 | 36 | except Exception: |
29 | 37 | exc_type, exc_value, traceback = sys.exc_info() |
30 | 38 | sys.excepthook(exc_type, exc_value, traceback) |
31 | 39 | rendered_exception = console.file.getvalue() |
32 | 40 | print(repr(rendered_exception)) |
33 | 41 | assert "Traceback" in rendered_exception |
34 | 42 | assert "ZeroDivisionError" in rendered_exception |
| 43 | + |
| 44 | + frame_blank_line_possible_preambles = ( |
| 45 | + # Start of the stack rendering: |
| 46 | + "╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮", |
| 47 | + # Each subsequent frame (starting with the file name) should then be preceded with a blank line: |
| 48 | + "│" + (" " * 98) + "│", |
| 49 | + ) |
| 50 | + for frame_start in re.finditer( |
| 51 | + "^│ .+rich/tests/test_traceback\.py:", |
| 52 | + rendered_exception, |
| 53 | + flags=re.MULTILINE, |
| 54 | + ): |
| 55 | + frame_start_index = frame_start.start() |
| 56 | + for preamble in frame_blank_line_possible_preambles: |
| 57 | + preamble_start, preamble_end = ( |
| 58 | + frame_start_index - len(preamble) - 1, |
| 59 | + frame_start_index - 1, |
| 60 | + ) |
| 61 | + if rendered_exception[preamble_start:preamble_end] == preamble: |
| 62 | + break |
| 63 | + else: |
| 64 | + pytest.fail( |
| 65 | + f"Frame {frame_start[0]} doesn't have the expected preamble" |
| 66 | + ) |
35 | 67 | finally: |
36 | 68 | sys.excepthook = old_handler |
37 | 69 | assert old_handler == expected_old_handler |
|
0 commit comments