cpython: 334c01aa7f93 (original) (raw)

Mercurial > cpython

changeset 93711:334c01aa7f93

Issue #14099: ZipFile.open() no longer reopen the underlying file. Objects returned by ZipFile.open() can now operate independently of the ZipFile even if the ZipFile was created by passing in a file-like object as the first argument to the constructor. [#14099]

Serhiy Storchaka storchaka@gmail.com
date Wed, 03 Dec 2014 09:14:36 +0200
parents fd80195b920f(current diff)e5bb3044402b(diff)
children 7509a0607c40
files Lib/test/test_zipfile.py Lib/zipfile.py Misc/NEWS
diffstat 4 files changed, 166 insertions(+), 73 deletions(-)[+] [-] Doc/library/zipfile.rst 10 Lib/test/test_zipfile.py 121 Lib/zipfile.py 103 Misc/NEWS 5

line wrap: on

line diff

--- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -219,14 +219,8 @@ ZipFile Objects .. note::

.. note::

--- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -1,3 +1,4 @@ +import contextlib import io import os import sys @@ -25,6 +26,9 @@ SMALL_TEST_DATA = [('_ziptest1', '1q2w3e ('ziptest2dir/ziptest3dir/_ziptest3', 'azsxdcfvgb'), ('ziptest2dir/ziptest3dir/ziptest4dir/_ziptest3', '6y7u8i9o0p')] +def getrandbytes(size):

+ def get_files(test): yield TESTFN2 with TemporaryFile() as f: @@ -289,7 +293,7 @@ class AbstractTestsWithSourceFile: # than requested. for test_size in (1, 4095, 4096, 4097, 16384): file_size = test_size + 1

@@ -1666,46 +1670,111 @@ class LzmaTestsWithRandomBinaryFiles(Abs @requires_zlib class TestsWithMultipleOpens(unittest.TestCase):

+

def test_same_file(self): # Verify that (when the ZipFile is in control of creating file objects) # multiple open() calls can be made without interfering with each other.

def test_different_file(self): # Verify that (when the ZipFile is in control of creating file objects) # multiple open() calls can be made without interfering with each other.

def test_interleaved(self): # Verify that (when the ZipFile is in control of creating file objects) # multiple open() calls can be made without interfering with each other.

+

+

+

+

def tearDown(self): unlink(TESTFN2)

--- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -646,6 +646,25 @@ def _get_decompressor(compress_type): raise NotImplementedError("compression type %d" % (compress_type,)) +class _SharedFile:

+

+

+ + class ZipExtFile(io.BufferedIOBase): """File-like object for reading an archive member. Is returned by ZipFile.open(). @@ -945,7 +964,7 @@ class ZipFile: self.NameToInfo = {} # Find file info given name self.filelist = [] # List of ZipInfo instances for archive self.compression = compression # Method of compression

@@ -954,28 +973,33 @@ class ZipFile: # No, it's a filename self._filePassed = 0 self.filename = file

try:

@@ -988,13 +1012,13 @@ class ZipFile: # set the modified flag so central directory gets written # even if no files are added to the archive self._didModify = True

def enter(self): @@ -1181,23 +1205,17 @@ class ZipFile: raise RuntimeError( "Attempt to read ZIP archive that was already closed")

- # Skip the file header: fheader = zef_file.read(sizeFileHeader) if len(fheader) != sizeFileHeader: @@ -1256,11 +1274,9 @@ class ZipFile: if h[11] != check_byte: raise RuntimeError("Bad password for file", name)

def extract(self, member, path=None, pwd=None): @@ -1394,6 +1410,7 @@ class ZipFile: zinfo.file_size = st.st_size zinfo.flag_bits = 0x00

@@ -1410,6 +1427,7 @@ class ZipFile: self.filelist.append(zinfo) self.NameToInfo[zinfo.filename] = zinfo self.fp.write(zinfo.FileHeader(False))

cmpr = _get_compressor(zinfo.compress_type) @@ -1448,10 +1466,10 @@ class ZipFile: raise RuntimeError('Compressed size larger than uncompressed size') # Seek backwards and write file header (which will now include # correct CRC and file sizes)

@@ -1480,6 +1498,7 @@ class ZipFile: "Attempt to write to ZIP archive that was already closed") zinfo.file_size = len(data) # Uncompressed size

@@ -1508,6 +1527,7 @@ class ZipFile: self.fp.write(struct.pack(fmt, zinfo.CRC, zinfo.compress_size, zinfo.file_size)) self.fp.flush()

@@ -1523,7 +1543,7 @@ class ZipFile: try: if self.mode in ("w", "a") and self._didModify: # write ending records

@@ -1589,8 +1609,8 @@ class ZipFile: pos2 = self.fp.tell() # Write end-of-zip-archive record centDirCount = len(self.filelist)

@@ -1626,8 +1646,13 @@ class ZipFile: finally: fp = self.fp self.fp = None

+

class PyZipFile(ZipFile):

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -194,6 +194,11 @@ Core and Builtins Library ------- +- Issue #14099: ZipFile.open() no longer reopen the underlying file. Objects