Index: Lib/difflib.py =================================================================== --- Lib/difflib.py (revision 79884) +++ Lib/difflib.py (working copy) @@ -1161,18 +1161,18 @@ 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 @@ 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 @@ 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 @@ 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: Lib/test/test_difflib.py =================================================================== --- Lib/test/test_difflib.py (revision 79884) +++ Lib/test/test_difflib.py (working copy) @@ -159,10 +159,32 @@ 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: Doc/library/difflib.rst =================================================================== --- Doc/library/difflib.rst (revision 79884) +++ Doc/library/difflib.rst (working copy) @@ -146,8 +146,8 @@ 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 @@ 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']