Skip to content

Commit 052fb4f

Browse files
committed
Fix bug in Pytest 5.4.x that was altering order of output lines.
Under pytest 5.4.x, failure reporting behavior considers all lines without a fail_marker prefix ("E") as a line of source code. These "source_lines" are grouped together regardless of their original position. Doing this can scramble the output when lines without a fail_marker appear after lines with a fail_marker. Normally, this causes no problems but when datatest removes fail_markers for "data differences", the output can be displayed out-of-order. The source of this behavior was introduced in pytest-dev/pytest@4209ad6 when addressing pytest-dev/pytest#6658. You can see the diff on GitHub: pytest-dev/pytest@4209ad6?branch=4209ad6fcacb679d953f3dd6be96f330139006f0&diff=split#diff-ac2099a172465905236568f8c175328fb75ebc1b80ce39f4799e61373d355418R1042 In later versions of Pytest, all lines after the first fail_marker are considered part of the error and the order of these lines is not altered--THIS IS THE DESIRED BEHAVIOR. See Pytest 6.1.1 source on GitHub: https://github.com/pytest-dev/pytest/blob/0ad20b533ffc52ced7bb1a03fba664615e90c093/src/_pytest/_code/code.py#L1059
1 parent 2a4779b commit 052fb4f

File tree

1 file changed

+50
-2
lines changed

1 file changed

+50
-2
lines changed

pytest_datatest.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
import itertools
3333
import re
34-
from _pytest._code.code import ReprEntry
34+
from _pytest._code.code import ReprEntry as _ReprEntry
3535
from _pytest._code.code import FormattedExcinfo
3636
from _pytest._code.code import ExceptionChainRepr
3737
from _pytest._code.code import ExceptionRepr
@@ -40,14 +40,17 @@
4040
from _pytest.assertion.truncate import DEFAULT_MAX_CHARS
4141
from _pytest.assertion.truncate import USAGE_MSG
4242
from pytest import hookimpl
43+
from pytest import __version__ as _pytest_version
4344
from datatest import ValidationError
4445

46+
47+
PYTEST54 = _pytest_version[:3] == '5.4'
48+
4549
if __name__ == 'pytest_datatest':
4650
from datatest._pytest_plugin import version_info as _bundled_version_info
4751
else:
4852
_bundled_version_info = (0, 0, 0)
4953

50-
5154
version = '0.1.4.dev0'
5255
version_info = (0, 1, 4)
5356

@@ -146,6 +149,47 @@ def _formatted_lines_generator(lines, fail_index):
146149
yield line
147150

148151

152+
if PYTEST54:
153+
class ReprEntry(_ReprEntry):
154+
"""Custom ReprEntry--USE ONLY WITH PYTEST 5.4.X VERSIONS."""
155+
def __init__(self, reprentry):
156+
self.lines = reprentry.lines
157+
self.reprfuncargs = reprentry.reprfuncargs
158+
self.reprlocals = reprentry.reprlocals
159+
self.reprfileloc = reprentry.reprfileloc
160+
self.style = reprentry.style
161+
162+
def _write_entry_lines(self, tw):
163+
"""This method is adapted from Pytest version 6.1.1."""
164+
165+
if not self.lines:
166+
return
167+
168+
fail_marker = "{} ".format(FormattedExcinfo.fail_marker)
169+
indent_size = len(fail_marker)
170+
indents = []
171+
source_lines = []
172+
failure_lines = []
173+
for index, line in enumerate(self.lines):
174+
is_failure_line = line.startswith(fail_marker)
175+
if is_failure_line:
176+
# from this point on all lines are considered part of the failure
177+
failure_lines.extend(self.lines[index:])
178+
break
179+
else:
180+
if self.style == "value":
181+
source_lines.append(line)
182+
else:
183+
indents.append(line[:indent_size])
184+
source_lines.append(line[indent_size:])
185+
186+
tw._write_source(source_lines, indents)
187+
188+
# failure lines are always completely red and bold
189+
for line in failure_lines:
190+
tw.line(line, bold=True, red=True)
191+
192+
149193
def _format_reprtraceback(reprtraceback):
150194
for reprentry in reprtraceback.reprentries:
151195
try:
@@ -163,6 +207,10 @@ def _format_reprtraceback(reprtraceback):
163207
lines = _formatted_lines_generator(lines, position)
164208
reprentry['lines'] = list(lines)
165209

210+
if PYTEST54:
211+
reprtraceback.reprentries = \
212+
[ReprEntry(entry) for entry in reprtraceback.reprentries]
213+
166214

167215
def pytest_runtest_logreport(report):
168216
"""Hook to format the ReprEntry lines for ValidationErrors"""

0 commit comments

Comments
 (0)