summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorR. David Murray <rdmurray@bitdance.com>2010-04-12 16:35:19 (GMT)
committerR. David Murray <rdmurray@bitdance.com>2010-04-12 16:35:19 (GMT)
commit1a14d3d169a34293f416abe4a41e4141c4e07965 (patch)
tree66c9de2d714533b17be4f16c7326da7771242c0d
parent9aca91d7d73121a73cdf5d742a8b6cae30989f50 (diff)
downloadcpython-1a14d3d169a34293f416abe4a41e4141c4e07965.zip
cpython-1a14d3d169a34293f416abe4a41e4141c4e07965.tar.gz
cpython-1a14d3d169a34293f416abe4a41e4141c4e07965.tar.bz2
Issue #7585: use tab between components in unified and context diff headers.
Instead of spaces between the filename and date (or whatever the string is that follows the filename, if any) use tabs. This is what the unix 'diff' command does, for example, and difflib was intended to follow the 'standard' way of doing diffs. This improves compatibility with patch tools. The docs and examples are also changed to recommended that the date format used be the ISO 8601 format, which is what modern diff tools emit by default. Patch by Anatoly Techtonik.
-rw-r--r--Doc/library/difflib.rst8
-rw-r--r--Lib/difflib.py35
-rw-r--r--Lib/test/test_difflib.py24
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS4
5 files changed, 51 insertions, 21 deletions
diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst
index d749e14..8556e1d 100644
--- a/Doc/library/difflib.rst
+++ b/Doc/library/difflib.rst
@@ -146,8 +146,8 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module.
The context diff format normally has a header for filenames and modification
times. Any or all of these may be specified using strings for *fromfile*,
- *tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally
- expressed in the format returned by :func:`time.ctime`. If not specified, the
+ *tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally
+ expressed in the ISO 8601 format. If not specified, the
strings default to blanks.
>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
@@ -281,8 +281,8 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module.
The context diff format normally has a header for filenames and modification
times. Any or all of these may be specified using strings for *fromfile*,
- *tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally
- expressed in the format returned by :func:`time.ctime`. If not specified, the
+ *tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally
+ expressed in the ISO 8601 format. If not specified, the
strings default to blanks.
>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
diff --git a/Lib/difflib.py b/Lib/difflib.py
index b43dc97..3cc5f6b 100644
--- a/Lib/difflib.py
+++ b/Lib/difflib.py
@@ -1161,18 +1161,18 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
The unidiff format normally has a header for filenames and modification
times. Any or all of these may be specified using strings for
- 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. The modification
- times are normally expressed in the format returned by time.ctime().
+ 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
+ The modification times are normally expressed in the ISO 8601 format.
Example:
>>> for line in unified_diff('one two three four'.split(),
... 'zero one tree four'.split(), 'Original', 'Current',
- ... 'Sat Jan 26 23:30:50 1991', 'Fri Jun 06 10:20:52 2003',
+ ... '2005-01-26 23:30:50', '2010-04-02 10:20:52',
... lineterm=''):
- ... print line
- --- Original Sat Jan 26 23:30:50 1991
- +++ Current Fri Jun 06 10:20:52 2003
+ ... print line # doctest: +NORMALIZE_WHITESPACE
+ --- Original 2005-01-26 23:30:50
+ +++ Current 2010-04-02 10:20:52
@@ -1,4 +1,4 @@
+zero
one
@@ -1185,8 +1185,10 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
started = False
for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
if not started:
- yield '--- %s %s%s' % (fromfile, fromfiledate, lineterm)
- yield '+++ %s %s%s' % (tofile, tofiledate, lineterm)
+ fromdate = '\t%s' % fromfiledate if fromfiledate else ''
+ todate = '\t%s' % tofiledate if tofiledate else ''
+ yield '--- %s%s%s' % (fromfile, fromdate, lineterm)
+ yield '+++ %s%s%s' % (tofile, todate, lineterm)
started = True
i1, i2, j1, j2 = group[0][1], group[-1][2], group[0][3], group[-1][4]
yield "@@ -%d,%d +%d,%d @@%s" % (i1+1, i2-i1, j1+1, j2-j1, lineterm)
@@ -1224,16 +1226,15 @@ def context_diff(a, b, fromfile='', tofile='',
The context diff format normally has a header for filenames and
modification times. Any or all of these may be specified using
strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
- The modification times are normally expressed in the format returned
- by time.ctime(). If not specified, the strings default to blanks.
+ The modification times are normally expressed in the ISO 8601 format.
+ If not specified, the strings default to blanks.
Example:
>>> print ''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(1),
- ... 'zero\none\ntree\nfour\n'.splitlines(1), 'Original', 'Current',
- ... 'Sat Jan 26 23:30:50 1991', 'Fri Jun 06 10:22:46 2003')),
- *** Original Sat Jan 26 23:30:50 1991
- --- Current Fri Jun 06 10:22:46 2003
+ ... 'zero\none\ntree\nfour\n'.splitlines(1), 'Original', 'Current')),
+ *** Original
+ --- Current
***************
*** 1,4 ****
one
@@ -1251,8 +1252,10 @@ def context_diff(a, b, fromfile='', tofile='',
prefixmap = {'insert':'+ ', 'delete':'- ', 'replace':'! ', 'equal':' '}
for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
if not started:
- yield '*** %s %s%s' % (fromfile, fromfiledate, lineterm)
- yield '--- %s %s%s' % (tofile, tofiledate, lineterm)
+ fromdate = '\t%s' % fromfiledate if fromfiledate else ''
+ todate = '\t%s' % tofiledate if tofiledate else ''
+ yield '*** %s%s%s' % (fromfile, fromdate, lineterm)
+ yield '--- %s%s%s' % (tofile, todate, lineterm)
started = True
yield '***************%s' % (lineterm,)
diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py
index 93f5c74..1b828bb 100644
--- a/Lib/test/test_difflib.py
+++ b/Lib/test/test_difflib.py
@@ -159,10 +159,32 @@ class TestSFpatches(unittest.TestCase):
difflib.SequenceMatcher(None, old, new).get_opcodes()
+class TestOutputFormat(unittest.TestCase):
+ def test_tab_delimiter(self):
+ args = ['one', 'two', 'Original', 'Current',
+ '2005-01-26 23:30:50', '2010-04-02 10:20:52']
+ ud = difflib.unified_diff(*args, lineterm='')
+ self.assertEqual(list(ud)[0:2], [
+ "--- Original\t2005-01-26 23:30:50",
+ "+++ Current\t2010-04-02 10:20:52"])
+ cd = difflib.context_diff(*args, lineterm='')
+ self.assertEqual(list(cd)[0:2], [
+ "*** Original\t2005-01-26 23:30:50",
+ "--- Current\t2010-04-02 10:20:52"])
+
+ def test_no_trailing_tab_on_empty_filedate(self):
+ args = ['one', 'two', 'Original', 'Current']
+ ud = difflib.unified_diff(*args, lineterm='')
+ self.assertEqual(list(ud)[0:2], ["--- Original", "+++ Current"])
+
+ cd = difflib.context_diff(*args, lineterm='')
+ self.assertEqual(list(cd)[0:2], ["*** Original", "--- Current"])
+
+
def test_main():
difflib.HtmlDiff._default_prefix = 0
Doctests = doctest.DocTestSuite(difflib)
- run_unittest(TestSFpatches, TestSFbugs, Doctests)
+ run_unittest(TestSFpatches, TestSFbugs, TestOutputFormat, Doctests)
if __name__ == '__main__':
test_main()
diff --git a/Misc/ACKS b/Misc/ACKS
index b0e89ca..2a031e7 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -747,6 +747,7 @@ Christian Tanzer
Steven Taschuk
Monty Taylor
Amy Taylor
+Anatoly Techtonik
Tobias Thelen
James Thomas
Robin Thomas
diff --git a/Misc/NEWS b/Misc/NEWS
index c95076e..d2b907e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -15,6 +15,10 @@ Core and Builtins
Library
-------
+- Issue #7585: difflib context and unified diffs now place a tab between
+ filename and date, conforming to the 'standards' they were originally
+ designed to follow. This improves compatibility with patch tools.
+
- Issue #7472: Fixed typo in email.encoders module; messages using ISO-2022
character sets will now consistently use a Content-Transfer-Encoding of
7bit rather than sometimes being marked as 8bit.