]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #7585: use tab between components in unified and context diff headers.
authorR. David Murray <rdmurray@bitdance.com>
Mon, 12 Apr 2010 16:35:19 +0000 (16:35 +0000)
committerR. David Murray <rdmurray@bitdance.com>
Mon, 12 Apr 2010 16:35:19 +0000 (16:35 +0000)
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.

Doc/library/difflib.rst
Lib/difflib.py
Lib/test/test_difflib.py
Misc/ACKS
Misc/NEWS

index d749e14582953d0e33eccab5e4c42dcc21edec0a..8556e1d3759bd1a5938b360188757ee42c2fe9aa 100644 (file)
@@ -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']
index b43dc970e254fa855737d4ea2c3ff0a77ebab10c..3cc5f6b7918e7aa5d4239e102de3f67b5646f36c 100644 (file)
@@ -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,)
index 93f5c742e95d3be590d95f7e8e19756f5f9c3a23..1b828bb65a06ee669accb0c4bd4bccea5d54d700 100644 (file)
@@ -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()
index b0e89ca8eb5e0664f0516f21793e4a8cfa92d5cb..2a031e7153bb96a87a612956deb9f077dcb61b07 100644 (file)
--- 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
index c95076eaed6f7e839c8798bf06f8698a2aff10d3..d2b907eda5e9ae9b15c85affe07649ee90b57125 100644 (file)
--- 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.