Commit 9bd2aa46 authored by Neal Norwitz's avatar Neal Norwitz

Fix SF bug #763023, difflib.py: ratio() zero division not caught

Backport candidate
parent 5b1aa2fb
...@@ -29,6 +29,11 @@ __all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher', ...@@ -29,6 +29,11 @@ __all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher',
'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff', 'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff',
'unified_diff'] 'unified_diff']
def _calculate_ratio(matches, length):
if length:
return 2.0 * matches / length
return 1.0
class SequenceMatcher: class SequenceMatcher:
""" """
...@@ -611,7 +616,7 @@ class SequenceMatcher: ...@@ -611,7 +616,7 @@ class SequenceMatcher:
matches = reduce(lambda sum, triple: sum + triple[-1], matches = reduce(lambda sum, triple: sum + triple[-1],
self.get_matching_blocks(), 0) self.get_matching_blocks(), 0)
return 2.0 * matches / (len(self.a) + len(self.b)) return _calculate_ratio(matches, len(self.a) + len(self.b))
def quick_ratio(self): def quick_ratio(self):
"""Return an upper bound on ratio() relatively quickly. """Return an upper bound on ratio() relatively quickly.
...@@ -640,7 +645,7 @@ class SequenceMatcher: ...@@ -640,7 +645,7 @@ class SequenceMatcher:
avail[elt] = numb - 1 avail[elt] = numb - 1
if numb > 0: if numb > 0:
matches = matches + 1 matches = matches + 1
return 2.0 * matches / (len(self.a) + len(self.b)) return _calculate_ratio(matches, len(self.a) + len(self.b))
def real_quick_ratio(self): def real_quick_ratio(self):
"""Return an upper bound on ratio() very quickly. """Return an upper bound on ratio() very quickly.
...@@ -652,7 +657,7 @@ class SequenceMatcher: ...@@ -652,7 +657,7 @@ class SequenceMatcher:
la, lb = len(self.a), len(self.b) la, lb = len(self.a), len(self.b)
# can't have more matches than the number of elements in the # can't have more matches than the number of elements in the
# shorter sequence # shorter sequence
return 2.0 * min(la, lb) / (la + lb) return _calculate_ratio(min(la, lb), la + lb)
def get_close_matches(word, possibilities, n=3, cutoff=0.6): def get_close_matches(word, possibilities, n=3, cutoff=0.6):
"""Use SequenceMatcher to return list of the best "good enough" matches. """Use SequenceMatcher to return list of the best "good enough" matches.
......
import difflib import difflib
from test import test_support from test import test_support
import unittest
class TestSFbugs(unittest.TestCase):
def test_ratio_for_null_seqn(self):
# Check clearing of SF bug 763023
s = difflib.SequenceMatcher(None, [], [])
self.assertEqual(s.ratio(), 1)
self.assertEqual(s.quick_ratio(), 1)
self.assertEqual(s.real_quick_ratio(), 1)
test_support.run_unittest(TestSFbugs)
test_support.run_doctest(difflib) test_support.run_doctest(difflib)
...@@ -24,6 +24,9 @@ Extension modules ...@@ -24,6 +24,9 @@ Extension modules
Library Library
------- -------
- SF bug 763023: fix uncaught ZeroDivisionError in difflib ratio methods
when there are no lines.
Tools/Demos Tools/Demos
----------- -----------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment