pytest.fail: fix ANSI escape codes for colored output (#12959)

- 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 https://github.com/pytest-dev/pytest/pull/12959#discussion_r1842574618

Closes #12849
This commit is contained in:
Leonardus Chen 2024-11-25 19:25:50 +07:00 committed by GitHub
parent 3b230e06db
commit 76e0444770
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 32 additions and 7 deletions

View File

@ -247,6 +247,7 @@ Kristoffer Nordström
Kyle Altendorf
Lawrence Mitchell
Lee Kamentsky
Leonardus Chen
Lev Maximov
Levon Saldamli
Lewis Cowles

View File

@ -0,0 +1 @@
ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False`.

View File

@ -1221,6 +1221,15 @@ class ReprEntry(TerminalRepr):
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"
@ -1236,11 +1245,8 @@ class ReprEntry(TerminalRepr):
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)

View File

@ -1194,6 +1194,23 @@ raise ValueError()
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",
[

View File

@ -119,8 +119,8 @@ def tw_mock():
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