diff options
author | Raymond Hettinger <python@rcn.com> | 2011-04-11 19:40:58 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2011-04-11 19:40:58 (GMT) |
commit | 49353d0e8f1faf526e7bc90d7422b3e050ad74bb (patch) | |
tree | 26fa6e21911b6125ac81ebbf11850a02d6148a72 /Lib | |
parent | fdb2df49bd9739dfbec7d6fda7870e31d0c46f91 (diff) | |
download | cpython-49353d0e8f1faf526e7bc90d7422b3e050ad74bb.zip cpython-49353d0e8f1faf526e7bc90d7422b3e050ad74bb.tar.gz cpython-49353d0e8f1faf526e7bc90d7422b3e050ad74bb.tar.bz2 |
Issue #11747: Fix range formatting in context and unified diffs.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/difflib.py | 34 | ||||
-rw-r--r-- | Lib/test/test_difflib.py | 16 |
2 files changed, 39 insertions, 11 deletions
diff --git a/Lib/difflib.py b/Lib/difflib.py index 86d928f..c5005a1 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1144,6 +1144,17 @@ def IS_CHARACTER_JUNK(ch, ws=" \t"): return ch in ws +def _format_range(start, stop): + 'Convert range to the "ed" format' + # Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning = start + 1 # lines start numbering with one + length = stop - start + if length == 1: + return '{}'.format(beginning) + if not length: + beginning -= 1 # empty ranges begin at line just before the range + return '{},{}'.format(beginning, length) + def unified_diff(a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=3, lineterm='\n'): r""" @@ -1193,9 +1204,12 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='', todate = '\t{}'.format(tofiledate) if tofiledate else '' yield '--- {}{}{}'.format(fromfile, fromdate, lineterm) yield '+++ {}{}{}'.format(tofile, todate, lineterm) + first, last = group[0], group[-1] - i1, i2, j1, j2 = first[1], last[2], first[3], last[4] - yield '@@ -{},{} +{},{} @@{}'.format(i1+1, i2-i1, j1+1, j2-j1, lineterm) + file1_range = _format_range(first[1], last[2]) + file2_range = _format_range(first[3], last[4]) + yield '@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm) + for tag, i1, i2, j1, j2 in group: if tag == 'equal': for line in a[i1:i2]: @@ -1264,22 +1278,20 @@ def context_diff(a, b, fromfile='', tofile='', yield '--- {}{}{}'.format(tofile, todate, lineterm) first, last = group[0], group[-1] - yield '***************{}'.format(lineterm) + yield '***************' + lineterm + + file1_range = _format_range(first[1], last[2]) + yield '*** {} ****{}'.format(file1_range, lineterm) - if last[2] - first[1] > 1: - yield '*** {},{} ****{}'.format(first[1]+1, last[2], lineterm) - else: - yield '*** {} ****{}'.format(last[2], lineterm) if any(tag in {'replace', 'delete'} for tag, _, _, _, _ in group): for tag, i1, i2, _, _ in group: if tag != 'insert': for line in a[i1:i2]: yield prefix[tag] + line - if last[4] - first[3] > 1: - yield '--- {},{} ----{}'.format(first[3]+1, last[4], lineterm) - else: - yield '--- {} ----{}'.format(last[4], lineterm) + file2_range = _format_range(first[3], last[4]) + yield '--- {} ----{}'.format(file2_range, lineterm) + if any(tag in {'replace', 'insert'} for tag, _, _, _, _ in group): for tag, _, _, j1, j2 in group: if tag != 'delete': diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py index a263ee6..b08be53 100644 --- a/Lib/test/test_difflib.py +++ b/Lib/test/test_difflib.py @@ -236,6 +236,22 @@ class TestOutputFormat(unittest.TestCase): cd = difflib.context_diff(*args, lineterm='') self.assertEqual(list(cd)[0:2], ["*** Original", "--- Current"]) + def test_range_format(self): + # Per the diff spec at http://www.unix.org/single_unix_specification/ + spec = '''\ + Each <range> field shall be of the form: + %1d", <beginning line number> if the range contains exactly one line, + and: + "%1d,%1d", <beginning line number>, <number of lines> otherwise. + If a range is empty, its beginning line number shall be the number of + the line just before the range, or 0 if the empty range starts the file. + ''' + fmt = difflib._format_range + self.assertEqual(fmt(3,3), '3,0') + self.assertEqual(fmt(3,4), '4') + self.assertEqual(fmt(3,5), '4,2') + self.assertEqual(fmt(3,6), '4,3') + self.assertEqual(fmt(0,0), '0,0') def test_main(): difflib.HtmlDiff._default_prefix = 0 |