From aba9796c5e92413f9fb5863da41a789d2bb225b8 Mon Sep 17 00:00:00 2001
From: Georg Brandl <georg@python.org>
Date: Fri, 26 Nov 2010 08:37:46 +0000
Subject: Merged revisions 85450-85455,85460-85465 via svnmerge from
 svn+ssh://svn.python.org/python/branches/py3k

........
  r85450 | georg.brandl | 2010-10-14 08:35:53 +0200 (Do, 14 Okt 2010) | 1 line

  #7642: update to os.system() docs.
........
  r85451 | georg.brandl | 2010-10-14 08:41:42 +0200 (Do, 14 Okt 2010) | 1 line

  #3865: add note about benchmarking with profilers, and move licensing stuff to bottom of document.
........
  r85452 | georg.brandl | 2010-10-14 08:43:22 +0200 (Do, 14 Okt 2010) | 1 line

  #10046: small correction to atexit docs.
........
  r85453 | georg.brandl | 2010-10-14 08:46:08 +0200 (Do, 14 Okt 2010) | 1 line

  #6825: small correction to split() docs.
........
  r85454 | georg.brandl | 2010-10-14 08:48:47 +0200 (Do, 14 Okt 2010) | 1 line

  Mention 2to3.
........
  r85455 | georg.brandl | 2010-10-14 08:59:45 +0200 (Do, 14 Okt 2010) | 1 line

  #1710703: write zipfile structures also in the case of closing a new, but empty, archive.
........
  r85460 | georg.brandl | 2010-10-14 09:24:28 +0200 (Do, 14 Okt 2010) | 1 line

  #9964: fix running test_import under -O or -OO.
........
  r85461 | georg.brandl | 2010-10-14 09:29:08 +0200 (Do, 14 Okt 2010) | 1 line

  #9964: fix lib2to3 fixer fix_operator when running under -OO.
........
  r85462 | georg.brandl | 2010-10-14 09:32:52 +0200 (Do, 14 Okt 2010) | 1 line

  #9964: fix running test_xml_etree under -OO.
........
  r85463 | georg.brandl | 2010-10-14 09:34:56 +0200 (Do, 14 Okt 2010) | 1 line

  Better check for "any optimize option given".
........
  r85464 | georg.brandl | 2010-10-14 09:42:27 +0200 (Do, 14 Okt 2010) | 1 line

  #9964: fix running test_compileall under -O and -OO.
........
  r85465 | georg.brandl | 2010-10-14 10:08:56 +0200 (Do, 14 Okt 2010) | 1 line

  #9964: fix running test_cmd_line_script under -O and -OO.
........
---
 Doc/library/atexit.rst   |  4 +--
 Doc/library/os.path.rst  | 16 ++++-----
 Doc/library/os.rst       | 34 +++++++++---------
 Doc/library/profile.rst  | 94 ++++++++++++++++++++++++------------------------
 Doc/library/zipfile.rst  |  4 +++
 Lib/test/test_zipfile.py | 25 +++++++++++++
 Lib/zipfile.py           | 27 +++++++++++---
 Misc/NEWS                |  4 +++
 Tools/README             |  7 ++--
 9 files changed, 133 insertions(+), 82 deletions(-)

diff --git a/Doc/library/atexit.rst b/Doc/library/atexit.rst
index db90218..104c730 100644
--- a/Doc/library/atexit.rst
+++ b/Doc/library/atexit.rst
@@ -12,8 +12,8 @@ functions.  Functions thus registered are automatically executed upon normal
 interpreter termination.
 
 Note: the functions registered via this module are not called when the program
-is killed by a signal, when a Python fatal internal error is detected, or when
-:func:`os._exit` is called.
+is killed by a signal not handled by Python, when a Python fatal internal error
+is detected, or when :func:`os._exit` is called.
 
 
 .. function:: register(func, *args, **kargs)
diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst
index 3e60e9e..fdc45b9 100644
--- a/Doc/library/os.path.rst
+++ b/Doc/library/os.path.rst
@@ -258,14 +258,14 @@ applications should use string objects to access all files.
 
 .. function:: split(path)
 
-   Split the pathname *path* into a pair, ``(head, tail)`` where *tail* is the last
-   pathname component and *head* is everything leading up to that.  The *tail* part
-   will never contain a slash; if *path* ends in a slash, *tail* will be empty.  If
-   there is no slash in *path*, *head* will be empty.  If *path* is empty, both
-   *head* and *tail* are empty.  Trailing slashes are stripped from *head* unless
-   it is the root (one or more slashes only).  In nearly all cases, ``join(head,
-   tail)`` equals *path* (the only exception being when there were multiple slashes
-   separating *head* from *tail*).
+   Split the pathname *path* into a pair, ``(head, tail)`` where *tail* is the
+   last pathname component and *head* is everything leading up to that.  The
+   *tail* part will never contain a slash; if *path* ends in a slash, *tail*
+   will be empty.  If there is no slash in *path*, *head* will be empty.  If
+   *path* is empty, both *head* and *tail* are empty.  Trailing slashes are
+   stripped from *head* unless it is the root (one or more slashes only).  In
+   all cases, ``join(head, tail)`` returns a path to the same location as *path*
+   (but the strings may differ).
 
 
 .. function:: splitdrive(path)
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index 9680d7a..371a902 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -1760,25 +1760,25 @@ written in Python, such as a mail server's external command delivery program.
 
    Execute the command (a string) in a subshell.  This is implemented by calling
    the Standard C function :cfunc:`system`, and has the same limitations.
-   Changes to :data:`sys.stdin`, etc. are not reflected in the environment of the
-   executed command.
+   Changes to :data:`sys.stdin`, etc. are not reflected in the environment of
+   the executed command. If *command* generates any output, it will be sent to
+   the interpreter standard output stream.
 
    On Unix, the return value is the exit status of the process encoded in the
-   format specified for :func:`wait`.  Note that POSIX does not specify the meaning
-   of the return value of the C :cfunc:`system` function, so the return value of
-   the Python function is system-dependent.
-
-   On Windows, the return value is that returned by the system shell after running
-   *command*, given by the Windows environment variable :envvar:`COMSPEC`: on
-   :program:`command.com` systems (Windows 95, 98 and ME) this is always ``0``; on
-   :program:`cmd.exe` systems (Windows NT, 2000 and XP) this is the exit status of
-   the command run; on systems using a non-native shell, consult your shell
-   documentation.
-
-   The :mod:`subprocess` module provides more powerful facilities for spawning new
-   processes and retrieving their results; using that module is preferable to using
-   this function.  Use the :mod:`subprocess` module.  Check especially the
-   :ref:`subprocess-replacements` section.
+   format specified for :func:`wait`.  Note that POSIX does not specify the
+   meaning of the return value of the C :cfunc:`system` function, so the return
+   value of the Python function is system-dependent.
+
+   On Windows, the return value is that returned by the system shell after
+   running *command*.  The shell is given by the Windows environment variable
+   :envvar:`COMSPEC`: it is usually :program:`cmd.exe`, which returns the exit
+   status of the command run; on systems using a non-native shell, consult your
+   shell documentation.
+
+   The :mod:`subprocess` module provides more powerful facilities for spawning
+   new processes and retrieving their results; using that module is preferable
+   to using this function.  See the :ref:`subprocess-replacements` section in
+   the :mod:`subprocess` documentation for some helpful recipes.
 
    Availability: Unix, Windows.
 
diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst
index e66ceaf..c5e5dd5 100644
--- a/Doc/library/profile.rst
+++ b/Doc/library/profile.rst
@@ -10,29 +10,6 @@ The Python Profilers
 .. module:: profile
    :synopsis: Python source profiler.
 
-.. index:: single: InfoSeek Corporation
-
-Copyright © 1994, by InfoSeek Corporation, all rights reserved.
-
-Written by James Roskind. [#]_
-
-Permission to use, copy, modify, and distribute this Python software and its
-associated documentation for any purpose (subject to the restriction in the
-following sentence) without fee is hereby granted, provided that the above
-copyright notice appears in all copies, and that both that copyright notice and
-this permission notice appear in supporting documentation, and that the name of
-InfoSeek not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission.  This permission is
-explicitly restricted to the copying and modification of the software to remain
-in Python, compiled Python, or other languages (such as C) wherein the modified
-or derived code is exclusively imported into a Python module.
-
-INFOSEEK CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
-SHALL INFOSEEK CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 .. _profiler-introduction:
 
@@ -43,33 +20,38 @@ Introduction to the profilers
    single: deterministic profiling
    single: profiling, deterministic
 
-A :dfn:`profiler` is a program that describes the run time performance
-of a program, providing a variety of statistics.  This documentation
-describes the profiler functionality provided in the modules
-:mod:`cProfile`, :mod:`profile` and :mod:`pstats`.  This profiler
-provides :dfn:`deterministic profiling` of Python programs.  It also
-provides a series of report generation tools to allow users to rapidly
-examine the results of a profile operation.
+A :dfn:`profiler` is a program that describes the run time performance of a
+program, providing a variety of statistics.  This documentation describes the
+profiler functionality provided in the modules :mod:`cProfile`, :mod:`profile`
+and :mod:`pstats`.  This profiler provides :dfn:`deterministic profiling` of
+Python programs.  It also provides a series of report generation tools to allow
+users to rapidly examine the results of a profile operation.
 
 The Python standard library provides two different profilers:
 
-#. :mod:`cProfile` is recommended for most users; it's a C extension
-   with reasonable overhead
-   that makes it suitable for profiling long-running programs.
-   Based on :mod:`lsprof`,
-   contributed by Brett Rosen and Ted Czotter.
+1. :mod:`cProfile` is recommended for most users; it's a C extension with
+   reasonable overhead that makes it suitable for profiling long-running
+   programs.  Based on :mod:`lsprof`, contributed by Brett Rosen and Ted
+   Czotter.
 
-#. :mod:`profile`, a pure Python module whose interface is imitated by
-   :mod:`cProfile`.  Adds significant overhead to profiled programs.
-   If you're trying to extend
-   the profiler in some way, the task might be easier with this module.
-   Copyright © 1994, by InfoSeek Corporation.
+2. :mod:`profile`, a pure Python module whose interface is imitated by
+   :mod:`cProfile`.  Adds significant overhead to profiled programs.  If you're
+   trying to extend the profiler in some way, the task might be easier with this
+   module.  Copyright © 1994, by InfoSeek Corporation.
 
 The :mod:`profile` and :mod:`cProfile` modules export the same interface, so
 they are mostly interchangeable; :mod:`cProfile` has a much lower overhead but
-is newer and might not be available on all systems.
-:mod:`cProfile` is really a compatibility layer on top of the internal
-:mod:`_lsprof` module.
+is newer and might not be available on all systems.  :mod:`cProfile` is really a
+compatibility layer on top of the internal :mod:`_lsprof` module.
+
+.. note::
+
+   The profiler modules are designed to provide an execution profile for a given
+   program, not for benchmarking purposes (for that, there is :mod:`timeit` for
+   resonably accurate results).  This particularly applies to benchmarking
+   Python code against C code: the profilers introduce overhead for Python code,
+   but not for C-level functions, and so the C code would seem faster than any
+   Python one.
 
 
 .. _profile-instant:
@@ -608,8 +590,26 @@ The resulting profiler will then call :func:`your_time_func`.
    best results with a custom timer, it might be necessary to hard-code it in the C
    source of the internal :mod:`_lsprof` module.
 
-.. rubric:: Footnotes
 
-.. [#] Updated and converted to LaTeX by Guido van Rossum. Further updated by Armin
-   Rigo to integrate the documentation for the new :mod:`cProfile` module of Python
-   2.5.
+Copyright and License Notices
+=============================
+
+Copyright © 1994, by InfoSeek Corporation, all rights reserved.
+
+Permission to use, copy, modify, and distribute this Python software and its
+associated documentation for any purpose (subject to the restriction in the
+following sentence) without fee is hereby granted, provided that the above
+copyright notice appears in all copies, and that both that copyright notice and
+this permission notice appear in supporting documentation, and that the name of
+InfoSeek not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission.  This permission is
+explicitly restricted to the copying and modification of the software to remain
+in Python, compiled Python, or other languages (such as C) wherein the modified
+or derived code is exclusively imported into a Python module.
+
+INFOSEEK CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
+SHALL INFOSEEK CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst
index 3ab78ab..5a168c0 100644
--- a/Doc/library/zipfile.rst
+++ b/Doc/library/zipfile.rst
@@ -120,6 +120,10 @@ ZipFile Objects
    because the default :program:`zip` and :program:`unzip` commands on Unix (the
    InfoZIP utilities) don't support these extensions.
 
+   If the file is created with mode ``'a'`` or ``'w'`` and then
+   :meth:`close`\ d without adding any files to the archive, the appropriate
+   ZIP structures for an empty archive will be written to the file.
+
 
 .. method:: ZipFile.close()
 
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index e32d2d0..26bc47b 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -902,6 +902,31 @@ class OtherTests(unittest.TestCase):
         def test_read_return_size_deflated(self):
             self.check_read_return_size(zipfile.ZIP_DEFLATED)
 
+    def test_empty_zipfile(self):
+        # Check that creating a file in 'w' or 'a' mode and closing without
+        # adding any files to the archives creates a valid empty ZIP file
+        zipf = zipfile.ZipFile(TESTFN, mode="w")
+        zipf.close()
+        try:
+            zipf = zipfile.ZipFile(TESTFN, mode="r")
+        except zipfile.BadZipFile:
+            self.fail("Unable to create empty ZIP file in 'w' mode")
+
+        zipf = zipfile.ZipFile(TESTFN, mode="a")
+        zipf.close()
+        try:
+            zipf = zipfile.ZipFile(TESTFN, mode="r")
+        except:
+            self.fail("Unable to create empty ZIP file in 'a' mode")
+
+    def test_open_empty_file(self):
+        # Issue 1710703: Check that opening a file with less than 22 bytes
+        # raises a BadZipfile exception (rather than the previously unhelpful
+        # IOError)
+        f = open(TESTFN, 'w')
+        f.close()
+        self.assertRaises(zipfile.BadZipfile, zipfile.ZipFile, TESTFN, 'r')
+
     def tearDown(self):
         support.unlink(TESTFN)
         support.unlink(TESTFN2)
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 3d2d57b..c376ee4 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -158,7 +158,13 @@ def _EndRecData64(fpin, offset, endrec):
     """
     Read the ZIP64 end-of-archive records and use that to update endrec
     """
-    fpin.seek(offset - sizeEndCentDir64Locator, 2)
+    try:
+        fpin.seek(offset - sizeEndCentDir64Locator, 2)
+    except IOError:
+        # If the seek fails, the file is not large enough to contain a ZIP64
+        # end-of-archive record, so just return the end record we were given.
+        return endrec
+
     data = fpin.read(sizeEndCentDir64Locator)
     sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data)
     if sig != stringEndArchive64Locator:
@@ -723,14 +729,22 @@ class ZipFile:
         if key == 'r':
             self._GetContents()
         elif key == 'w':
-            pass
+            # set the modified flag so central directory gets written
+            # even if no files are added to the archive
+            self._didModify = True
         elif key == 'a':
-            try:                        # See if file is a zip file
+            try:
+                # See if file is a zip file
                 self._RealGetContents()
                 # seek to start of directory and overwrite
                 self.fp.seek(self.start_dir, 0)
-            except BadZipfile:          # file is not a zip file, just append
+            except BadZipfile:
+                # file is not a zip file, just append
                 self.fp.seek(0, 2)
+
+                # set the modified flag so central directory gets written
+                # even if no files are added to the archive
+                self._didModify = True
         else:
             if not self._filePassed:
                 self.fp.close()
@@ -751,7 +765,10 @@ class ZipFile:
     def _RealGetContents(self):
         """Read in the table of contents for the ZIP file."""
         fp = self.fp
-        endrec = _EndRecData(fp)
+        try:
+            endrec = _EndRecData(fp)
+        except IOError:
+            raise BadZipfile("File is not a zip file")
         if not endrec:
             raise BadZipfile("File is not a zip file")
         if self.debug > 1:
diff --git a/Misc/NEWS b/Misc/NEWS
index e305fc3..b77b789 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,10 @@ Library
 
 - Issue #10459: Update CJK character names to Unicode 5.1.
 
+- Issue #1710703: Write structures for an empty ZIP archive when a ZipFile is
+  created in modes 'a' or 'w' and then closed without adding any files. Raise
+  BadZipfile (rather than IOError) when opening small non-ZIP files.
+
 - Issue #4493: urllib.request adds '/' in front of path components which does not
   start with '/. Common behavior exhibited by browsers and other clients.
 
diff --git a/Tools/README b/Tools/README
index db6e370..a70e087 100644
--- a/Tools/README
+++ b/Tools/README
@@ -26,9 +26,10 @@ modulator	Interactively generate boiler plate for an extension
 
 pynche		A Tkinter-based color editor.
 
-scripts		A number of useful single-file programs, e.g. tabnanny.py
-		(by Tim Peters), which checks for inconsistent mixing
-		of tabs and spaces.
+scripts         A number of useful single-file programs, e.g. tabnanny.py
+                by Tim Peters, which checks for inconsistent mixing of
+                tabs and spaces, and 2to3, which converts Python 2 code
+                to Python 3 code.
 
 unicode		Tools used to generate unicode database files for
 		Python 2.0 (by Fredrik Lundh).
-- 
cgit v0.12