Skip to content

Commit 56a7b6c

Browse files
committed
new approach to the columns heuristic
1 parent 7801d4a commit 56a7b6c

File tree

2 files changed

+55
-20
lines changed

2 files changed

+55
-20
lines changed

pytest_icdiff.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
# pylint: disable=inconsistent-return-statements
2+
import py
23
from pprintpp import pformat
34
import icdiff
45

6+
COLS = py.io.TerminalWriter().fullwidth # pylint: disable=no-member
7+
MARGIN_L = 9
8+
GUTTER = 2
9+
MARGINS = MARGIN_L + GUTTER + 1
10+
11+
512

613
def pytest_assertrepr_compare(config, op, left, right):
714
if op != '==':
@@ -13,26 +20,23 @@ def pytest_assertrepr_compare(config, op, left, right):
1320
except TypeError:
1421
pass
1522

16-
terminal_writer = config.get_terminal_writer()
17-
cols = terminal_writer.fullwidth - 12
18-
19-
wide_left = pformat(left, indent=2, width=cols / 2).splitlines()
20-
wide_right = pformat(right, indent=2, width=cols / 2).splitlines()
21-
if len(wide_left) < 3 or len(wide_right) < 3:
22-
shortest_left = pformat(left, indent=2, width=1).splitlines()
23-
shortest_right = pformat(right, indent=2, width=1).splitlines()
24-
longest_line_length = max(len(l) for l in shortest_left + shortest_right)
25-
else:
26-
longest_line_length = max(len(l) for l in wide_left + wide_right)
27-
cols = int(min(longest_line_length, cols))
23+
half_cols = COLS / 2 - MARGINS
2824

29-
pretty_left = pformat(left, indent=2, width=cols / 2).splitlines()
30-
pretty_right = pformat(right, indent=2, width=cols / 2).splitlines()
25+
pretty_left = pformat(left, indent=2, width=half_cols).splitlines()
26+
pretty_right = pformat(right, indent=2, width=half_cols).splitlines()
27+
diff_cols = COLS - MARGINS
3128

29+
if len(pretty_left) < 3 or len(pretty_right) < 3:
30+
# avoid small diffs far apart by smooshing them up to the left
31+
pretty_left = pformat(left, indent=2, width=1).splitlines()
32+
pretty_right = pformat(right, indent=2, width=1).splitlines()
33+
diff_cols = max(len(l) + 1 for l in pretty_left + pretty_right) * 2
34+
if (diff_cols + MARGINS) > COLS:
35+
diff_cols = COLS - MARGINS
3236

33-
differ = icdiff.ConsoleDiff(cols=cols + 12, tabsize=2)
37+
differ = icdiff.ConsoleDiff(cols=diff_cols, tabsize=2)
3438

35-
if not terminal_writer.hasmarkup:
39+
if not config.get_terminal_writer().hasmarkup:
3640
# colorization is disabled in Pytest - either due to the terminal not
3741
# supporting it or the user disabling it. We should obey, but there is
3842
# no option in icdiff to disable it, so we replace its colorization
@@ -44,4 +48,4 @@ def pytest_assertrepr_compare(config, op, left, right):
4448

4549
icdiff_lines = list(differ.make_table(pretty_left, pretty_right))
4650

47-
return ['equals failed'] + [color_off + l for l in icdiff_lines]
51+
return [f'equals failed'] + [color_off + l for l in icdiff_lines]

tests/test_pytest_icdiff.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_one():
2424
assert {one!r} == {two!r}
2525
"""
2626
)
27-
output = testdir.runpytest().stdout.str()
27+
output = testdir.runpytest('-vv').stdout.str()
2828
print(repr(output))
2929
two_left = "'the number two'"
3030
two_right = "'the number three'"
@@ -173,7 +173,7 @@ def test_one():
173173
assert {one!r} == {two!r}
174174
"""
175175
)
176-
output = testdir.runpytest().stdout.str()
176+
output = testdir.runpytest('-vv').stdout.str()
177177
print(repr(output))
178178
assert re.search(r"1: '1',\s+$", output, flags=re.MULTILINE)
179179

@@ -218,4 +218,35 @@ def test_one():
218218
if "hell" in l
219219
and "assert" not in l
220220
)
221-
assert comparison_line.count('hell') < 13
221+
assert comparison_line.count('hell') < 15
222+
223+
224+
def test_columns_are_calculated_outside_hook(testdir):
225+
"""
226+
ok for some reason if you get the TerminalWriter width
227+
inside of the hook it just always returns 80.
228+
but (bear with me here) if you monkeypatch.setenv(COLUMNS)
229+
then it _does_ affect the width inside the hook
230+
(which is where we don't want to measure it)
231+
but it does _not_ affect the one outside the hook
232+
(which is the one we want to use).
233+
"""
234+
left = "hello " * 10
235+
right = "hella " * 10
236+
testdir.makepyfile(
237+
f"""
238+
def test_one():
239+
assert {left!r} == {right!r}
240+
"""
241+
)
242+
testdir.monkeypatch.setenv('COLUMNS', '50')
243+
# testdir._method = 'subprocess'
244+
output = testdir.runpytest(
245+
'-vv', '--color=yes',
246+
).stdout.str()
247+
comparison_line = next(
248+
l for l in output.splitlines()
249+
if 'hell' in l and "assert" not in l
250+
)
251+
assert comparison_line.count('hell') > 5
252+

0 commit comments

Comments
 (0)