summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2011-04-11 19:40:58 (GMT)
committerRaymond Hettinger <python@rcn.com>2011-04-11 19:40:58 (GMT)
commit49353d0e8f1faf526e7bc90d7422b3e050ad74bb (patch)
tree26fa6e21911b6125ac81ebbf11850a02d6148a72 /Lib
parentfdb2df49bd9739dfbec7d6fda7870e31d0c46f91 (diff)
downloadcpython-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.py34
-rw-r--r--Lib/test/test_difflib.py16
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