Merged revisions 67946 via svnmerge from

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

........
  r67946 | antoine.pitrou | 2008-12-27 16:43:12 +0100 (sam., 27 déc. 2008) | 4 lines

  Issue #4756: zipfile.is_zipfile() now supports file-like objects.
  Patch by Gabriel Genellina.
........
This commit is contained in:
Antoine Pitrou 2008-12-27 15:50:40 +00:00
parent d88e8fab14
commit db5fe66731
4 changed files with 60 additions and 14 deletions

View File

@ -64,9 +64,11 @@ The module defines the following items:
.. function:: is_zipfile(filename) .. function:: is_zipfile(filename)
Returns ``True`` if *filename* is a valid ZIP file based on its magic number, Returns ``True`` if *filename* is a valid ZIP file based on its magic number,
otherwise returns ``False``. This module does not currently handle ZIP files otherwise returns ``False``. *filename* may be a file or file-like object too.
which have appended comments. This module does not currently handle ZIP files which have appended comments.
.. versionchanged:: 2.7
Support for file and file-like objects.
.. data:: ZIP_STORED .. data:: ZIP_STORED

View File

@ -621,20 +621,49 @@ class OtherTests(unittest.TestCase):
def testIsZipErroneousFile(self): def testIsZipErroneousFile(self):
# This test checks that the is_zipfile function correctly identifies # This test checks that the is_zipfile function correctly identifies
# a file that is not a zip file # a file that is not a zip file
fp = open(TESTFN, "w")
fp.write("this is not a legal zip file\n") # - passing a filename
fp.close() with open(TESTFN, "w") as fp:
fp.write("this is not a legal zip file\n")
chk = zipfile.is_zipfile(TESTFN) chk = zipfile.is_zipfile(TESTFN)
self.assert_(chk is False) self.assert_(not chk)
# - passing a file object
with open(TESTFN, "rb") as fp:
chk = zipfile.is_zipfile(fp)
self.assert_(not chk)
# - passing a file-like object
fp = io.BytesIO()
fp.write(b"this is not a legal zip file\n")
chk = zipfile.is_zipfile(fp)
self.assert_(not chk)
fp.seek(0,0)
chk = zipfile.is_zipfile(fp)
self.assert_(not chk)
def testIsZipValidFile(self): def testIsZipValidFile(self):
# This test checks that the is_zipfile function correctly identifies # This test checks that the is_zipfile function correctly identifies
# a file that is a zip file # a file that is a zip file
# - passing a filename
zipf = zipfile.ZipFile(TESTFN, mode="w") zipf = zipfile.ZipFile(TESTFN, mode="w")
zipf.writestr("foo.txt", b"O, for a Muse of Fire!") zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
zipf.close() zipf.close()
chk = zipfile.is_zipfile(TESTFN) chk = zipfile.is_zipfile(TESTFN)
self.assert_(chk is True) self.assert_(chk)
# - passing a file object
with open(TESTFN, "rb") as fp:
chk = zipfile.is_zipfile(fp)
self.assert_(chk)
fp.seek(0,0)
zip_contents = fp.read()
# - passing a file-like object
fp = io.BytesIO()
fp.write(zip_contents)
chk = zipfile.is_zipfile(fp)
self.assert_(chk)
fp.seek(0,0)
chk = zipfile.is_zipfile(fp)
self.assert_(chk)
def testNonExistentFileRaisesIOError(self): def testNonExistentFileRaisesIOError(self):
# make sure we don't raise an AttributeError when a partially-constructed # make sure we don't raise an AttributeError when a partially-constructed

View File

@ -130,18 +130,30 @@ _CD64_NUMBER_ENTRIES_TOTAL = 7
_CD64_DIRECTORY_SIZE = 8 _CD64_DIRECTORY_SIZE = 8
_CD64_OFFSET_START_CENTDIR = 9 _CD64_OFFSET_START_CENTDIR = 9
def is_zipfile(filename): def _check_zipfile(fp):
"""Quickly see if file is a ZIP file by checking the magic number."""
try: try:
fpin = io.open(filename, "rb") if _EndRecData(fp):
endrec = _EndRecData(fpin) return True # file has correct magic number
fpin.close()
if endrec:
return True # file has correct magic number
except IOError: except IOError:
pass pass
return False return False
def is_zipfile(filename):
"""Quickly see if a file is a ZIP file by checking the magic number.
The filename argument may be a file or file-like object too.
"""
result = False
try:
if hasattr(filename, "read"):
result = _check_zipfile(fp=filename)
else:
with open(filename, "rb") as fp:
result = _check_zipfile(fp)
except IOError:
pass
return result
def _EndRecData64(fpin, offset, endrec): def _EndRecData64(fpin, offset, endrec):
""" """
Read the ZIP64 end-of-archive records and use that to update endrec Read the ZIP64 end-of-archive records and use that to update endrec

View File

@ -59,6 +59,9 @@ Core and Builtins
Library Library
------- -------
- Issue #4756: zipfile.is_zipfile() now supports file-like objects. Patch by
Gabriel Genellina.
- Issue #4574: reading an UTF16-encoded text file crashes if \r on 64-char - Issue #4574: reading an UTF16-encoded text file crashes if \r on 64-char
boundary. boundary.