Skip to content

Commit 1f25c33

Browse files
authored
gh-156505: Speed up difflib.HtmlDiff for lopsided replacements (GH-156506)
1 parent 3b56438 commit 1f25c33

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

Lib/difflib.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
'unified_diff', 'diff_bytes', 'HtmlDiff', 'Match']
3232

3333
from heapq import nlargest as _nlargest
34-
from collections import namedtuple as _namedtuple
34+
from collections import deque as _deque, namedtuple as _namedtuple
3535
from types import GenericAlias
3636
lazy from _colorize import can_colorize, get_theme
3737

@@ -1571,7 +1571,7 @@ def _line_pair_iterator():
15711571
is defined) does not need to be of module scope.
15721572
"""
15731573
line_iterator = _line_iterator()
1574-
fromlines,tolines=[],[]
1574+
fromlines, tolines = _deque(), _deque()
15751575
while True:
15761576
# Collecting lines of text until we have a from/to pair
15771577
while (len(fromlines)==0 or len(tolines)==0):
@@ -1584,8 +1584,8 @@ def _line_pair_iterator():
15841584
if to_line is not None:
15851585
tolines.append((to_line,found_diff))
15861586
# Once we have a pair, remove them from the collection and yield it
1587-
from_line, fromDiff = fromlines.pop(0)
1588-
to_line, to_diff = tolines.pop(0)
1587+
from_line, fromDiff = fromlines.popleft()
1588+
to_line, to_diff = tolines.popleft()
15891589
yield (from_line,to_line,fromDiff or to_diff)
15901590

15911591
# Handle case where user does not want context differencing, just yield

Lib/test/test_difflib.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,26 @@ def test_mdiff_catch_stop_iteration(self):
200200
[((1, '\x00-2\x01'), (1, '\x00+3\x01'), True)],
201201
)
202202

203+
def test_mdiff_lopsided_replace(self):
204+
self.assertEqual(
205+
list(difflib._mdiff(["a\n"] * 4, ["b\n"])),
206+
[
207+
((1, '\x00-a\n\x01'), (1, '\x00+b\n\x01'), True),
208+
((2, '\x00-a\n\x01'), ('', '\n'), True),
209+
((3, '\x00-a\n\x01'), ('', '\n'), True),
210+
((4, '\x00-a\n\x01'), ('', '\n'), True),
211+
],
212+
)
213+
self.assertEqual(
214+
list(difflib._mdiff(["a\n"], ["b\n"] * 4)),
215+
[
216+
((1, '\x00-a\n\x01'), (1, '\x00+b\n\x01'), True),
217+
(('', '\n'), (2, '\x00+b\n\x01'), True),
218+
(('', '\n'), (3, '\x00+b\n\x01'), True),
219+
(('', '\n'), (4, '\x00+b\n\x01'), True),
220+
],
221+
)
222+
203223

204224
patch914575_from1 = """
205225
1. Beautiful is beTTer than ugly.

0 commit comments

Comments
 (0)