Skip to content

Commit

Permalink
pytest.fail: fix ANSI escape codes for colored output (#12959)
Browse files Browse the repository at this point in the history
- When `ReprEntry.style == "value"` (happens when calling `pytest.fail(..., pytrace=False)`, the message should not be printed to terminal using `TerminalWriter._write_source` because then it'll try to highlight the message as source code
- The message should be printed to terminal directly using `TerminalWriter.line` or `TerminalWriter.write`, I went with the later for testing purposes #12959 (comment)

Closes #12849
  • Loading branch information
leonarduschen authored Nov 25, 2024
1 parent 3b230e0 commit 76e0444
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 7 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ Kristoffer Nordström
Kyle Altendorf
Lawrence Mitchell
Lee Kamentsky
Leonardus Chen
Lev Maximov
Levon Saldamli
Lewis Cowles
Expand Down
1 change: 1 addition & 0 deletions changelog/12849.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False`.
16 changes: 11 additions & 5 deletions src/_pytest/_code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,15 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None:
if not self.lines:
return

if self.style == "value":
# Using tw.write instead of tw.line for testing purposes due to TWMock implementation;
# lines written with TWMock.line and TWMock._write_source cannot be distinguished
# from each other, whereas lines written with TWMock.write are marked with TWMock.WRITE
for line in self.lines:
tw.write(line)
tw.write("\n")
return

# separate indents and source lines that are not failures: we want to
# highlight the code but not the indentation, which may contain markers
# such as "> assert 0"
Expand All @@ -1236,11 +1245,8 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None:
failure_lines.extend(self.lines[index:])
break
else:
if self.style == "value":
source_lines.append(line)
else:
indents.append(line[:indent_size])
source_lines.append(line[indent_size:])
indents.append(line[:indent_size])
source_lines.append(line[indent_size:])

tw._write_source(source_lines, indents)

Expand Down
17 changes: 17 additions & 0 deletions testing/code/test_excinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,23 @@ def f():
line = tw_mock.lines[-1]
assert line == ":3: ValueError"

def test_toterminal_value(self, importasmod, tw_mock):
mod = importasmod(
"""
def g(x):
raise ValueError(x)
def f():
g('some_value')
"""
)
excinfo = pytest.raises(ValueError, mod.f)
excinfo.traceback = excinfo.traceback.filter(excinfo)
repr = excinfo.getrepr(style="value")
repr.toterminal(tw_mock)

assert tw_mock.get_write_msg(0) == "some_value"
assert tw_mock.get_write_msg(1) == "\n"

@pytest.mark.parametrize(
"reproptions",
[
Expand Down
4 changes: 2 additions & 2 deletions testing/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ def markup(self, text, **kw):
return text

def get_write_msg(self, idx):
flag, msg = self.lines[idx]
assert flag == TWMock.WRITE
assert self.lines[idx][0] == TWMock.WRITE
msg = self.lines[idx][1]
return msg

fullwidth = 80
Expand Down

0 comments on commit 76e0444

Please sign in to comment.