summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/difflib.py30
-rw-r--r--Lib/test/test_difflib.py29
2 files changed, 52 insertions, 7 deletions
diff --git a/Lib/difflib.py b/Lib/difflib.py
index c5005a104d..e6cc6ee442 100644
--- a/Lib/difflib.py
+++ b/Lib/difflib.py
@@ -1144,7 +1144,11 @@ def IS_CHARACTER_JUNK(ch, ws=" \t"):
return ch in ws
-def _format_range(start, stop):
+########################################################################
+### Unified Diff
+########################################################################
+
+def _format_range_unified(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
@@ -1206,8 +1210,8 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
yield '+++ {}{}{}'.format(tofile, todate, lineterm)
first, last = group[0], group[-1]
- file1_range = _format_range(first[1], last[2])
- file2_range = _format_range(first[3], last[4])
+ file1_range = _format_range_unified(first[1], last[2])
+ file2_range = _format_range_unified(first[3], last[4])
yield '@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm)
for tag, i1, i2, j1, j2 in group:
@@ -1222,6 +1226,22 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
for line in b[j1:j2]:
yield '+' + line
+
+########################################################################
+### Context Diff
+########################################################################
+
+def _format_range_context(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 not length:
+ beginning -= 1 # empty ranges begin at line just before the range
+ if length <= 1:
+ return '{}'.format(beginning)
+ return '{},{}'.format(beginning, beginning + length - 1)
+
# See http://www.unix.org/single_unix_specification/
def context_diff(a, b, fromfile='', tofile='',
fromfiledate='', tofiledate='', n=3, lineterm='\n'):
@@ -1280,7 +1300,7 @@ def context_diff(a, b, fromfile='', tofile='',
first, last = group[0], group[-1]
yield '***************' + lineterm
- file1_range = _format_range(first[1], last[2])
+ file1_range = _format_range_context(first[1], last[2])
yield '*** {} ****{}'.format(file1_range, lineterm)
if any(tag in {'replace', 'delete'} for tag, _, _, _, _ in group):
@@ -1289,7 +1309,7 @@ def context_diff(a, b, fromfile='', tofile='',
for line in a[i1:i2]:
yield prefix[tag] + line
- file2_range = _format_range(first[3], last[4])
+ file2_range = _format_range_context(first[3], last[4])
yield '--- {} ----{}'.format(file2_range, lineterm)
if any(tag in {'replace', 'insert'} for tag, _, _, _, _ in group):
diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py
index b08be53dd9..325449aa55 100644
--- a/Lib/test/test_difflib.py
+++ b/Lib/test/test_difflib.py
@@ -236,7 +236,7 @@ class TestOutputFormat(unittest.TestCase):
cd = difflib.context_diff(*args, lineterm='')
self.assertEqual(list(cd)[0:2], ["*** Original", "--- Current"])
- def test_range_format(self):
+ def test_range_format_unified(self):
# Per the diff spec at http://www.unix.org/single_unix_specification/
spec = '''\
Each <range> field shall be of the form:
@@ -246,13 +246,38 @@ class TestOutputFormat(unittest.TestCase):
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
+ fmt = difflib._format_range_unified
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_range_format_context(self):
+ # Per the diff spec at http://www.unix.org/single_unix_specification/
+ spec = '''\
+ The range of lines in file1 shall be written in the following format
+ if the range contains two or more lines:
+ "*** %d,%d ****\n", <beginning line number>, <ending line number>
+ and the following format otherwise:
+ "*** %d ****\n", <ending line number>
+ The ending line number of an empty range shall be the number of the preceding line,
+ or 0 if the range is at the start of the file.
+
+ Next, the range of lines in file2 shall be written in the following format
+ if the range contains two or more lines:
+ "--- %d,%d ----\n", <beginning line number>, <ending line number>
+ and the following format otherwise:
+ "--- %d ----\n", <ending line number>
+ '''
+ fmt = difflib._format_range_context
+ self.assertEqual(fmt(3,3), '3')
+ self.assertEqual(fmt(3,4), '4')
+ self.assertEqual(fmt(3,5), '4,5')
+ self.assertEqual(fmt(3,6), '4,6')
+ self.assertEqual(fmt(0,0), '0')
+
+
def test_main():
difflib.HtmlDiff._default_prefix = 0
Doctests = doctest.DocTestSuite(difflib)