1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
"""Tests for the message formatter helpers in :mod:`edify.errors.formatting`."""
from unittest import mock
from edify.errors.context import CallerContext
from edify.errors.formatting import (
FixInsertion,
Problem,
compose_annotated_message,
format_error,
format_fix_block,
format_help_header,
format_note_line,
format_pointer_block,
format_problem,
format_problem_header,
)
def _context(source_line: str = " x = do_the_thing(1, 2, 3)", colno: int = 9) -> CallerContext:
return CallerContext(
filename="/tmp/user_code.py",
lineno=42,
colno=colno,
end_colno=colno + 15,
source_line=source_line,
)
def test_format_error_with_only_summary_returns_bare_header():
assert format_error("boom") == "error: boom"
def test_format_error_with_summary_and_blocks_joins_them_with_blank_line():
output = format_error("boom", "first block", "second block")
assert output == "error: boom\n\nfirst block\n\nsecond block"
def test_format_error_skips_empty_blocks():
output = format_error("boom", "", "only real block", "")
assert output == "error: boom\n\nonly real block"
def test_format_pointer_block_draws_caret_at_caller_column():
context = _context()
block = format_pointer_block(context, "here")
lines = block.splitlines()
assert lines[0] == " --> /tmp/user_code.py:42:9"
assert "^^^^^^^^^^^^^^^ here" in block
def test_format_pointer_block_has_at_least_one_caret_when_span_is_empty():
context = CallerContext(
filename="/tmp/x.py",
lineno=1,
colno=5,
end_colno=5,
source_line="abcde",
)
block = format_pointer_block(context, "point")
assert "^ point" in block
def test_format_note_line_prepends_the_note_prefix():
assert format_note_line("something is off") == " = note: something is off"
def test_format_problem_header_prepends_problem_prefix():
assert format_problem_header("stuff") == "problem: stuff"
def test_format_help_header_prepends_help_prefix():
assert format_help_header("do X") == "help: do X"
def test_format_fix_block_inserts_text_at_the_target_column():
context = _context(source_line="value = compute()", colno=1)
insertion = FixInsertion(column=9, text="new_")
block = format_fix_block(context, insertion)
assert "value = new_compute()" in block
assert "++++" in block
def test_format_problem_composes_header_pointer_help_and_fix():
problem_context = _context(source_line="pattern = build()", colno=11)
fix_context = _context(source_line="pattern = build()", colno=11)
fix_insertion = FixInsertion(column=11, text=".digit()")
problem = Problem(
description="missing operand",
problem_context=problem_context,
problem_hint="no operand added",
help_summary="add .digit() before .build()",
fix_context=fix_context,
fix_insertion=fix_insertion,
)
output = format_problem(problem)
assert "problem: missing operand" in output
assert "no operand added" in output
assert "help: add .digit() before .build()" in output
assert "++++++++" in output
def test_compose_annotated_message_when_caller_context_is_available():
output = compose_annotated_message(
summary="bad thing happened",
trigger_hint="right here",
note="because reasons",
help_line="help: do X",
)
assert output.startswith("error: bad thing happened")
assert "-->" in output
assert "= note: because reasons" in output
assert output.rstrip().endswith("help: do X")
def test_compose_annotated_message_falls_back_when_caller_context_is_none():
with mock.patch("edify.errors.formatting.capture_caller_context", return_value=None):
output = compose_annotated_message(
summary="bad thing happened",
trigger_hint="here",
note="because reasons",
help_line="help: do X",
)
assert output.startswith("error: bad thing happened")
assert "-->" not in output
assert "= note: because reasons" in output
assert output.rstrip().endswith("help: do X")
|