summaryrefslogtreecommitdiff
path: root/Lib/difflib.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/difflib.py')
-rw-r--r--Lib/difflib.py37
1 files changed, 21 insertions, 16 deletions
diff --git a/Lib/difflib.py b/Lib/difflib.py
index 9be6ca7242..b43dc970e2 100644
--- a/Lib/difflib.py
+++ b/Lib/difflib.py
@@ -30,9 +30,13 @@ Class HtmlDiff:
__all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher',
'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff',
- 'unified_diff', 'HtmlDiff']
+ 'unified_diff', 'HtmlDiff', 'Match']
import heapq
+from collections import namedtuple as _namedtuple
+from functools import reduce
+
+Match = _namedtuple('Match', 'a b size')
def _calculate_ratio(matches, length):
if length:
@@ -199,7 +203,7 @@ class SequenceMatcher:
# DON'T USE! Only __chain_b uses this. Use isbjunk.
# isbjunk
# for x in b, isbjunk(x) == isjunk(x) but much faster;
- # it's really the has_key method of a hidden dict.
+ # it's really the __contains__ method of a hidden dict.
# DOES NOT WORK for x in a!
# isbpopular
# for x in b, isbpopular(x) is true iff b is reasonably long
@@ -341,8 +345,8 @@ class SequenceMatcher:
# lot of junk in the sequence, the number of *unique* junk
# elements is probably small. So the memory burden of keeping
# this dict alive is likely trivial compared to the size of b2j.
- self.isbjunk = junkdict.has_key
- self.isbpopular = populardict.has_key
+ self.isbjunk = junkdict.__contains__
+ self.isbpopular = populardict.__contains__
def find_longest_match(self, alo, ahi, blo, bhi):
"""Find longest matching block in a[alo:ahi] and b[blo:bhi].
@@ -363,7 +367,7 @@ class SequenceMatcher:
>>> s = SequenceMatcher(None, " abcd", "abcd abcd")
>>> s.find_longest_match(0, 5, 0, 9)
- (0, 4, 5)
+ Match(a=0, b=4, size=5)
If isjunk is defined, first the longest matching block is
determined as above, but with the additional restriction that no
@@ -379,13 +383,13 @@ class SequenceMatcher:
>>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd")
>>> s.find_longest_match(0, 5, 0, 9)
- (1, 0, 4)
+ Match(a=1, b=0, size=4)
If no blocks match, return (alo, blo, 0).
>>> s = SequenceMatcher(None, "ab", "c")
>>> s.find_longest_match(0, 2, 0, 1)
- (0, 0, 0)
+ Match(a=0, b=0, size=0)
"""
# CAUTION: stripping common prefix or suffix would be incorrect.
@@ -452,7 +456,7 @@ class SequenceMatcher:
a[besti+bestsize] == b[bestj+bestsize]:
bestsize = bestsize + 1
- return besti, bestj, bestsize
+ return Match(besti, bestj, bestsize)
def get_matching_blocks(self):
"""Return list of triples describing matching subsequences.
@@ -470,7 +474,7 @@ class SequenceMatcher:
>>> s = SequenceMatcher(None, "abxcd", "abcd")
>>> s.get_matching_blocks()
- [(0, 0, 2), (3, 2, 2), (5, 4, 0)]
+ [Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)]
"""
if self.matching_blocks is not None:
@@ -523,7 +527,7 @@ class SequenceMatcher:
non_adjacent.append( (la, lb, 0) )
self.matching_blocks = non_adjacent
- return self.matching_blocks
+ return map(Match._make, self.matching_blocks)
def get_opcodes(self):
"""Return list of 5-tuples describing how to turn a into b.
@@ -674,7 +678,7 @@ class SequenceMatcher:
# avail[x] is the number of times x appears in 'b' less the
# number of times we've seen it in 'a' so far ... kinda
avail = {}
- availhas, matches = avail.has_key, 0
+ availhas, matches = avail.__contains__, 0
for elt in self.a:
if availhas(elt):
numb = avail[elt]
@@ -1057,20 +1061,21 @@ class Differ:
Example:
>>> d = Differ()
- >>> results = d._qformat('\tabcDefghiJkl\n', '\t\tabcdefGhijkl\n',
- ... ' ^ ^ ^ ', '+ ^ ^ ^ ')
+ >>> results = d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n',
+ ... ' ^ ^ ^ ', ' ^ ^ ^ ')
>>> for line in results: print repr(line)
...
'- \tabcDefghiJkl\n'
'? \t ^ ^ ^\n'
- '+ \t\tabcdefGhijkl\n'
- '? \t ^ ^ ^\n'
+ '+ \tabcdefGhijkl\n'
+ '? \t ^ ^ ^\n'
"""
# Can hurt, but will probably help most of the time.
common = min(_count_leading(aline, "\t"),
_count_leading(bline, "\t"))
common = min(common, _count_leading(atags[:common], " "))
+ common = min(common, _count_leading(btags[:common], " "))
atags = atags[common:].rstrip()
btags = btags[common:].rstrip()
@@ -1325,7 +1330,7 @@ def _mdiff(fromlines, tolines, context=None, linejunk=None,
(from line tuple, to line tuple, boolean flag)
from/to line tuple -- (line num, line text)
- line num -- integer or None (to indicate a context seperation)
+ line num -- integer or None (to indicate a context separation)
line text -- original line text with following markers inserted:
'\0+' -- marks start of added text
'\0-' -- marks start of deleted text