Patch #1775025: allow opening zipfile members via ZipInfo instances.
Patch by Graham Horler.
This commit is contained in:
parent
4dd019fde3
commit
112aa50329
|
@ -155,11 +155,11 @@ ZipFile Objects
|
|||
.. method:: ZipFile.open(name[, mode[, pwd]])
|
||||
|
||||
Extract a member from the archive as a file-like object (ZipExtFile). *name* is
|
||||
the name of the file in the archive. The *mode* parameter, if included, must be
|
||||
one of the following: ``'r'`` (the default), ``'U'``, or ``'rU'``. Choosing
|
||||
``'U'`` or ``'rU'`` will enable universal newline support in the read-only
|
||||
object. *pwd* is the password used for encrypted files. Calling :meth:`open`
|
||||
on a closed ZipFile will raise a :exc:`RuntimeError`.
|
||||
the name of the file in the archive, or a :class:`ZipInfo` object. The *mode*
|
||||
parameter, if included, must be one of the following: ``'r'`` (the default),
|
||||
``'U'``, or ``'rU'``. Choosing ``'U'`` or ``'rU'`` will enable universal newline
|
||||
support in the read-only object. *pwd* is the password used for encrypted files.
|
||||
Calling :meth:`open` on a closed ZipFile will raise a :exc:`RuntimeError`.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -178,16 +178,22 @@ ZipFile Objects
|
|||
create a new file object that will be held by the ZipExtFile, allowing it to
|
||||
operate independently of the ZipFile.
|
||||
|
||||
.. note::
|
||||
|
||||
The :meth:`open`, :meth:`read` and :meth:`extract` methods can take a filename
|
||||
or a :class:`ZipInfo` object. You will appreciate this when trying to read a
|
||||
ZIP file that contains members with duplicate names.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
|
||||
.. method:: ZipFile.extract(member[, path[, pwd]])
|
||||
|
||||
Extract a member from the archive to the current working directory, using its
|
||||
full name. Its file information is extracted as accurately as possible.
|
||||
*path* specifies a different directory to extract to. *member* can be a
|
||||
filename or a :class:`ZipInfo` object. *pwd* is the password used for
|
||||
encrypted files.
|
||||
Extract a member from the archive to the current working directory; *member*
|
||||
must be its full name or a :class:`ZipInfo` object). Its file information is
|
||||
extracted as accurately as possible. *path* specifies a different directory
|
||||
to extract to. *member* can be a filename or a :class:`ZipInfo` object.
|
||||
*pwd* is the password used for encrypted files.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
|
@ -216,13 +222,14 @@ ZipFile Objects
|
|||
|
||||
.. method:: ZipFile.read(name[, pwd])
|
||||
|
||||
Return the bytes of the file in the archive. The archive must be open for read
|
||||
or append. *pwd* is the password used for encrypted files and, if specified, it
|
||||
will override the default password set with :meth:`setpassword`. Calling
|
||||
Return the bytes of the file *name* in the archive. *name* is the name of the
|
||||
file in the archive, or a :class:`ZipInfo` object. The archive must be open for
|
||||
read or append. *pwd* is the password used for encrypted files and, if specified,
|
||||
it will override the default password set with :meth:`setpassword`. Calling
|
||||
:meth:`read` on a closed ZipFile will raise a :exc:`RuntimeError`.
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
*pwd* was added.
|
||||
*pwd* was added, and *name* can now be a :class:`ZipInfo` object.
|
||||
|
||||
|
||||
.. method:: ZipFile.testzip()
|
||||
|
|
|
@ -132,6 +132,25 @@ class TestsWithSourceFile(unittest.TestCase):
|
|||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
self.zipOpenTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def testOpenViaZipInfo(self):
|
||||
# Create the ZIP archive
|
||||
zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
|
||||
zipfp.writestr("name", "foo")
|
||||
zipfp.writestr("name", "bar")
|
||||
zipfp.close()
|
||||
|
||||
zipfp = zipfile.ZipFile(TESTFN2, "r")
|
||||
infos = zipfp.infolist()
|
||||
data = ""
|
||||
for info in infos:
|
||||
data += zipfp.open(info).read()
|
||||
self.assert_(data == "foobar" or data == "barfoo")
|
||||
data = ""
|
||||
for info in infos:
|
||||
data += zipfp.read(info)
|
||||
self.assert_(data == "foobar" or data == "barfoo")
|
||||
zipfp.close()
|
||||
|
||||
def zipRandomOpenTest(self, f, compression):
|
||||
self.makeTestArchive(f, compression)
|
||||
|
||||
|
|
|
@ -776,10 +776,13 @@ class ZipFile:
|
|||
else:
|
||||
zef_file = open(self.filename, 'rb')
|
||||
|
||||
# Get info object for name
|
||||
zinfo = self.getinfo(name)
|
||||
|
||||
filepos = zef_file.tell()
|
||||
# Make sure we have an info object
|
||||
if isinstance(name, ZipInfo):
|
||||
# 'name' is already an info object
|
||||
zinfo = name
|
||||
else:
|
||||
# Get info object for name
|
||||
zinfo = self.getinfo(name)
|
||||
|
||||
zef_file.seek(zinfo.header_offset, 0)
|
||||
|
||||
|
@ -884,7 +887,7 @@ class ZipFile:
|
|||
if upperdirs and not os.path.exists(upperdirs):
|
||||
os.makedirs(upperdirs)
|
||||
|
||||
source = self.open(member.filename, pwd=pwd)
|
||||
source = self.open(member, pwd=pwd)
|
||||
target = file(targetpath, "wb")
|
||||
shutil.copyfileobj(source, target)
|
||||
source.close()
|
||||
|
|
|
@ -52,6 +52,10 @@ Extension Modules
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #1775025: You can now specify zipfile members to open(),
|
||||
read() or extract() via a ZipInfo instance. This allows handling
|
||||
duplicate filenames in zipfiles.
|
||||
|
||||
- Issue #961805: Fix Text.edit_modified() in Tkinter.
|
||||
|
||||
- Issue #1793: Function ctypes.util.find_msvcrt() added that returns
|
||||
|
|
Loading…
Reference in New Issue