Skip to content

Commit e1c638d

Browse files
asottiletim-one
authored andcommitted
Fix difflib ? hint in diff output when dealing with tabs (#15201)
1 parent 092911d commit e1c638d

File tree

3 files changed

+20
-23
lines changed

3 files changed

+20
-23
lines changed

Lib/difflib.py

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -733,20 +733,15 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6):
733733
# Strip scores for the best n matches
734734
return [x for score, x in result]
735735

736-
def _count_leading(line, ch):
737-
"""
738-
Return number of `ch` characters at the start of `line`.
739736

740-
Example:
737+
def _keep_original_ws(s, tag_s):
738+
"""Replace whitespace with the original whitespace characters in `s`"""
739+
return ''.join(
740+
c if tag_c == " " and c.isspace() else tag_c
741+
for c, tag_c in zip(s, tag_s)
742+
)
741743

742-
>>> _count_leading(' abc', ' ')
743-
3
744-
"""
745744

746-
i, n = 0, len(line)
747-
while i < n and line[i] == ch:
748-
i += 1
749-
return i
750745

751746
class Differ:
752747
r"""
@@ -1033,7 +1028,7 @@ def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
10331028

10341029
def _qformat(self, aline, bline, atags, btags):
10351030
r"""
1036-
Format "?" output and deal with leading tabs.
1031+
Format "?" output and deal with tabs.
10371032
10381033
Example:
10391034
@@ -1047,22 +1042,16 @@ def _qformat(self, aline, bline, atags, btags):
10471042
'+ \tabcdefGhijkl\n'
10481043
'? \t ^ ^ ^\n'
10491044
"""
1050-
1051-
# Can hurt, but will probably help most of the time.
1052-
common = min(_count_leading(aline, "\t"),
1053-
_count_leading(bline, "\t"))
1054-
common = min(common, _count_leading(atags[:common], " "))
1055-
common = min(common, _count_leading(btags[:common], " "))
1056-
atags = atags[common:].rstrip()
1057-
btags = btags[common:].rstrip()
1045+
atags = _keep_original_ws(aline, atags).rstrip()
1046+
btags = _keep_original_ws(bline, btags).rstrip()
10581047

10591048
yield "- " + aline
10601049
if atags:
1061-
yield "? %s%s\n" % ("\t" * common, atags)
1050+
yield f"? {atags}\n"
10621051

10631052
yield "+ " + bline
10641053
if btags:
1065-
yield "? %s%s\n" % ("\t" * common, btags)
1054+
yield f"? {btags}\n"
10661055

10671056
# With respect to junk, an earlier version of ndiff simply refused to
10681057
# *start* a match with a junk element. The result was cases like this:

Lib/test/test_difflib.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,16 @@ def test_added_tab_hint(self):
8989
# Check fix for bug #1488943
9090
diff = list(difflib.Differ().compare(["\tI am a buggy"],["\t\tI am a bug"]))
9191
self.assertEqual("- \tI am a buggy", diff[0])
92-
self.assertEqual("? --\n", diff[1])
92+
self.assertEqual("? \t --\n", diff[1])
9393
self.assertEqual("+ \t\tI am a bug", diff[2])
9494
self.assertEqual("? +\n", diff[3])
9595

96+
def test_hint_indented_properly_with_tabs(self):
97+
diff = list(difflib.Differ().compare(["\t \t \t^"], ["\t \t \t^\n"]))
98+
self.assertEqual("- \t \t \t^", diff[0])
99+
self.assertEqual("+ \t \t \t^\n", diff[1])
100+
self.assertEqual("? \t \t \t +\n", diff[2])
101+
96102
def test_mdiff_catch_stop_iteration(self):
97103
# Issue #33224
98104
self.assertEqual(
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :mod:`difflib` ``?`` hint in diff output when dealing with tabs. Patch
2+
by Anthony Sottile.

0 commit comments

Comments
 (0)