Merged revisions 80004 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r80004 | r.david.murray | 2010-04-12 12:35:19 -0400 (Mon, 12 Apr 2010) | 13 lines

  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.
........
This commit is contained in:
R. David Murray 2010-04-12 16:58:02 +00:00
parent af9c3cfd44
commit b2416e54b1
5 changed files with 51 additions and 21 deletions

View File

@ -140,8 +140,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 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*, times. Any or all of these may be specified using strings for *fromfile*,
*tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally *tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally
expressed in the format returned by :func:`time.ctime`. If not specified, the expressed in the ISO 8601 format. If not specified, the
strings default to blanks. strings default to blanks.
>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n'] >>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
@ -272,8 +272,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 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*, times. Any or all of these may be specified using strings for *fromfile*,
*tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally *tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally
expressed in the format returned by :func:`time.ctime`. If not specified, the expressed in the ISO 8601 format. If not specified, the
strings default to blanks. strings default to blanks.

View File

@ -1160,18 +1160,18 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
The unidiff format normally has a header for filenames and modification The unidiff format normally has a header for filenames and modification
times. Any or all of these may be specified using strings for times. Any or all of these may be specified using strings for
'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. The modification 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
times are normally expressed in the format returned by time.ctime(). The modification times are normally expressed in the ISO 8601 format.
Example: Example:
>>> for line in unified_diff('one two three four'.split(), >>> for line in unified_diff('one two three four'.split(),
... 'zero one tree four'.split(), 'Original', 'Current', ... '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=''): ... lineterm=''):
... print(line) ... print(line) # doctest: +NORMALIZE_WHITESPACE
--- Original Sat Jan 26 23:30:50 1991 --- Original 2005-01-26 23:30:50
+++ Current Fri Jun 06 10:20:52 2003 +++ Current 2010-04-02 10:20:52
@@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
+zero +zero
one one
@ -1184,8 +1184,10 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
started = False started = False
for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
if not started: if not started:
yield '--- %s %s%s' % (fromfile, fromfiledate, lineterm) fromdate = '\t%s' % fromfiledate if fromfiledate else ''
yield '+++ %s %s%s' % (tofile, tofiledate, lineterm) todate = '\t%s' % tofiledate if tofiledate else ''
yield '--- %s%s%s' % (fromfile, fromdate, lineterm)
yield '+++ %s%s%s' % (tofile, todate, lineterm)
started = True started = True
i1, i2, j1, j2 = group[0][1], group[-1][2], group[0][3], group[-1][4] 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) yield "@@ -%d,%d +%d,%d @@%s" % (i1+1, i2-i1, j1+1, j2-j1, lineterm)
@ -1223,17 +1225,16 @@ def context_diff(a, b, fromfile='', tofile='',
The context diff format normally has a header for filenames and The context diff format normally has a header for filenames and
modification times. Any or all of these may be specified using modification times. Any or all of these may be specified using
strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
The modification times are normally expressed in the format returned The modification times are normally expressed in the ISO 8601 format.
by time.ctime(). If not specified, the strings default to blanks. If not specified, the strings default to blanks.
Example: Example:
>>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(1), >>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(1),
... 'zero\none\ntree\nfour\n'.splitlines(1), 'Original', 'Current', ... 'zero\none\ntree\nfour\n'.splitlines(1), 'Original', 'Current')),
... 'Sat Jan 26 23:30:50 1991', 'Fri Jun 06 10:22:46 2003')),
... end="") ... end="")
*** Original Sat Jan 26 23:30:50 1991 *** Original
--- Current Fri Jun 06 10:22:46 2003 --- Current
*************** ***************
*** 1,4 **** *** 1,4 ****
one one
@ -1251,8 +1252,10 @@ def context_diff(a, b, fromfile='', tofile='',
prefixmap = {'insert':'+ ', 'delete':'- ', 'replace':'! ', 'equal':' '} prefixmap = {'insert':'+ ', 'delete':'- ', 'replace':'! ', 'equal':' '}
for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
if not started: if not started:
yield '*** %s %s%s' % (fromfile, fromfiledate, lineterm) fromdate = '\t%s' % fromfiledate if fromfiledate else ''
yield '--- %s %s%s' % (tofile, tofiledate, lineterm) todate = '\t%s' % tofiledate if tofiledate else ''
yield '*** %s%s%s' % (fromfile, fromdate, lineterm)
yield '--- %s%s%s' % (tofile, todate, lineterm)
started = True started = True
yield '***************%s' % (lineterm,) yield '***************%s' % (lineterm,)

View File

@ -159,10 +159,32 @@ class TestSFpatches(unittest.TestCase):
difflib.SequenceMatcher(None, old, new).get_opcodes() 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(): def test_main():
difflib.HtmlDiff._default_prefix = 0 difflib.HtmlDiff._default_prefix = 0
Doctests = doctest.DocTestSuite(difflib) Doctests = doctest.DocTestSuite(difflib)
run_unittest(TestSFpatches, TestSFbugs, Doctests) run_unittest(TestSFpatches, TestSFbugs, TestOutputFormat, Doctests)
if __name__ == '__main__': if __name__ == '__main__':
test_main() test_main()

View File

@ -755,6 +755,7 @@ Christian Tanzer
Steven Taschuk Steven Taschuk
Monty Taylor Monty Taylor
Amy Taylor Amy Taylor
Anatoly Techtonik
Tobias Thelen Tobias Thelen
James Thomas James Thomas
Robin Thomas Robin Thomas

View File

@ -312,6 +312,10 @@ C-API
Library 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 - Issue #7472: Fixed typo in email.encoders module; messages using ISO-2022
character sets will now consistently use a Content-Transfer-Encoding of character sets will now consistently use a Content-Transfer-Encoding of
7bit rather than sometimes being marked as 8bit. 7bit rather than sometimes being marked as 8bit.