Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Doc/library/difflib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ The :class:`SequenceMatcher` class has this constructor:
is not changed.


.. method:: find_longest_match(alo, ahi, blo, bhi)
.. method:: find_longest_match(alo=0, ahi=None, blo=0, bhi=None)

Find longest matching block in ``a[alo:ahi]`` and ``b[blo:bhi]``.

Expand Down Expand Up @@ -458,6 +458,9 @@ The :class:`SequenceMatcher` class has this constructor:

This method returns a :term:`named tuple` ``Match(a, b, size)``.

.. versionchanged:: 3.9
Added default arguments.


.. method:: get_matching_blocks()

Expand Down
8 changes: 6 additions & 2 deletions Lib/difflib.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class SequenceMatcher:
set_seq2(b)
Set the second sequence to be compared.

find_longest_match(alo, ahi, blo, bhi)
find_longest_match(alo=0, ahi=None, blo=0, bhi=None)
Find longest matching block in a[alo:ahi] and b[blo:bhi].

get_matching_blocks()
Expand Down Expand Up @@ -334,9 +334,11 @@ def __chain_b(self):
for elt in popular: # ditto; as fast for 1% deletion
del b2j[elt]

def find_longest_match(self, alo, ahi, blo, bhi):
def find_longest_match(self, alo=0, ahi=None, blo=0, bhi=None):
"""Find longest matching block in a[alo:ahi] and b[blo:bhi].

By default it will find the longest match in the entirety of a and b.

If isjunk is not defined:

Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
Expand Down Expand Up @@ -391,6 +393,8 @@ def find_longest_match(self, alo, ahi, blo, bhi):
# the unique 'b's and then matching the first two 'a's.

a, b, b2j, isbjunk = self.a, self.b, self.b2j, self.bjunk.__contains__
ahi = len(a) if ahi is None else ahi
bhi = len(b) if bhi is None else bhi
Comment thread
lrjball marked this conversation as resolved.
Outdated
besti, bestj, bestsize = alo, blo, 0
# find longest junk-free match
# during an iteration of the loop, j2len[j] = length of longest
Expand Down
48 changes: 47 additions & 1 deletion Lib/test/test_difflib.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,12 +501,58 @@ def test_is_character_junk_false(self):
for char in ['a', '#', '\n', '\f', '\r', '\v']:
self.assertFalse(difflib.IS_CHARACTER_JUNK(char), repr(char))

class TestFindLongest(unittest.TestCase):
def longer_match_exists(self, a, b, n):
return any(b_part in a for b_part in
[b[i:i + n + 1] for i in range(0, len(b) - n - 1)])

def test_default_args(self):
a = 'foo bar'
b = 'foo baz bar'
sm = difflib.SequenceMatcher(a=a, b=b)
match = sm.find_longest_match()
self.assertEqual(match.a, 0)
self.assertEqual(match.b, 0)
self.assertEqual(match.size, 6)
Comment thread
tim-one marked this conversation as resolved.
self.assertEqual(a[match.a: match.a + match.size],
b[match.b: match.b + match.size])
self.assertFalse(self.longer_match_exists(a, b, match.size))

match = sm.find_longest_match(alo=2, blo=4)
self.assertEqual(match.a, 3)
self.assertEqual(match.b, 7)
self.assertEqual(match.size, 4)
self.assertEqual(a[match.a: match.a + match.size],
b[match.b: match.b + match.size])
self.assertFalse(self.longer_match_exists(a[2:], b[4:], match.size))

match = sm.find_longest_match(bhi=5, blo=1)
self.assertEqual(match.a, 1)
self.assertEqual(match.b, 1)
self.assertEqual(match.size, 4)
self.assertEqual(a[match.a: match.a + match.size],
b[match.b: match.b + match.size])
self.assertFalse(self.longer_match_exists(a, b[1:5], match.size))

def test_longest_match_with_popular_chars(self):
a = 'dabcd'
b = 'd'*100 + 'abc' + 'd'*100 # length over 200 so popular used
sm = difflib.SequenceMatcher(a=a, b=b)
match = sm.find_longest_match(0, len(a), 0, len(b))
self.assertEqual(match.a, 0)
self.assertEqual(match.b, 99)
self.assertEqual(match.size, 5)
self.assertEqual(a[match.a: match.a + match.size],
b[match.b: match.b + match.size])
self.assertFalse(self.longer_match_exists(a, b, match.size))


def test_main():
difflib.HtmlDiff._default_prefix = 0
Doctests = doctest.DocTestSuite(difflib)
run_unittest(
TestWithAscii, TestAutojunk, TestSFpatches, TestSFbugs,
TestOutputFormat, TestBytes, TestJunkAPIs, Doctests)
TestOutputFormat, TestBytes, TestJunkAPIs, TestFindLongest, Doctests)

if __name__ == '__main__':
test_main()
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Dwayne Bailey
Stig Bakken
Aleksandr Balezin
Greg Ball
Lewis Ball
Luigi Ballabio
Thomas Ballinger
Jeff Balogh
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added default arguments to :meth:`difflib.SequenceMatcher.find_longest_match()`.