From aba9796c5e92413f9fb5863da41a789d2bb225b8 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 26 Nov 2010 08:37:46 +0000 Subject: [PATCH] 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 | 30 ++++++------- 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, 131 insertions(+), 80 deletions(-) diff --git a/Doc/library/atexit.rst b/Doc/library/atexit.rst index db902187fb7..104c73027d2 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 3e60e9e7712..fdc45b93918 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 9680d7a3596..371a902fdc5 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. + 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. + 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. Use the :mod:`subprocess` module. Check especially the - :ref:`subprocess-replacements` section. + 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 e66ceafdd29..c5e5dd5a6a2 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 3ab78ab321c..5a168c0f39b 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 e32d2d02962..26bc47b056c 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 3d2d57b2058..c376ee47ee4 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 e305fc341e4..b77b789d74b 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 db6e3705a4f..a70e087a58f 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).