Was looking at assertion diff output and noticed the trailing skip optimization wasn't kicking in when the compared strings differed at the start. Traced it to _diff_text in compare_text.py line 62:
if len(left) == len(right):
for i in range(len(left)):
if left[-i] != right[-i]:
break
if i > 42:
i -= 10 # Provide some context
yield (
f"Skipping {i} identical trailing "
"characters in diff, use -v to show"
)
left = left[:-i]
right = right[:-i]
-0 == 0 in Python, so left[-0] is actually left[0] — the first character, not the last. When the first chars differ, the loop breaks at i=0, i > 42 is False, and the trailing identical characters never get skipped. Dozens of them, just sitting there in the diff output.
Reproducer:
from _pytest.assertion.compare_text import _diff_text
from _pytest.assertion.highlight import dummy_highlighter
# Case 1: first char same — skip works
result = list(_diff_text("a" + "x" + "z" * 50, "a" + "y" + "z" * 50, dummy_highlighter, 0))
# → contains "Skipping 41 identical trailing characters in diff, use -v to show"
# Case 2: first char differs — skip silently fails
result = list(_diff_text("x" + "z" * 50, "y" + "z" * 50, dummy_highlighter, 0))
# → no "Skipping" message, full 50-char diff output
Fix: loop from i=1 instead of i=0:
for i in range(1, len(left) + 1):
if left[-i] != right[-i]:
break
The existing test test_text_skipping_trailing doesn't catch this because both test strings start with 'a', so the accidental left[-0] comparison happens to pass and the loop continues to the actual trailing characters.
This code has been around since 2013 (originally in assertion/util.py, moved to compare_text.py in #14520).
Was looking at assertion diff output and noticed the trailing skip optimization wasn't kicking in when the compared strings differed at the start. Traced it to
_diff_textincompare_text.pyline 62:-0 == 0in Python, soleft[-0]is actuallyleft[0]— the first character, not the last. When the first chars differ, the loop breaks ati=0,i > 42is False, and the trailing identical characters never get skipped. Dozens of them, just sitting there in the diff output.Reproducer:
Fix: loop from
i=1instead ofi=0:The existing test
test_text_skipping_trailingdoesn't catch this because both test strings start with'a', so the accidentalleft[-0]comparison happens to pass and the loop continues to the actual trailing characters.This code has been around since 2013 (originally in
assertion/util.py, moved tocompare_text.pyin #14520).