summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2008-12-27 15:50:40 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2008-12-27 15:50:40 (GMT)
commitdb5fe667311745a2bc86355620354449721545f3 (patch)
treea33cb5639ac9b87911c0a934ba5a42737c3df671
parentd88e8fab148359a85f8e2a110a850c74e8ed5244 (diff)
downloadcpython-db5fe667311745a2bc86355620354449721545f3.zip
cpython-db5fe667311745a2bc86355620354449721545f3.tar.gz
cpython-db5fe667311745a2bc86355620354449721545f3.tar.bz2
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. ........
-rw-r--r--Doc/library/zipfile.rst6
-rw-r--r--Lib/test/test_zipfile.py39
-rw-r--r--Lib/zipfile.py26
-rw-r--r--Misc/NEWS3
4 files changed, 60 insertions, 14 deletions
diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst
index 49267c0..75860cc 100644
--- a/Doc/library/zipfile.rst
+++ b/Doc/library/zipfile.rst
@@ -64,9 +64,11 @@ The module defines the following items:
.. function:: is_zipfile(filename)
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
- which have appended comments.
+ otherwise returns ``False``. *filename* may be a file or file-like object too.
+ 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
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index 9e565fb..678ac9f 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -621,20 +621,49 @@ class OtherTests(unittest.TestCase):
def testIsZipErroneousFile(self):
# This test checks that the is_zipfile function correctly identifies
# a file that is not a zip file
- fp = open(TESTFN, "w")
- fp.write("this is not a legal zip file\n")
- fp.close()
+
+ # - passing a filename
+ with open(TESTFN, "w") as fp:
+ fp.write("this is not a legal zip file\n")
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):
# This test checks that the is_zipfile function correctly identifies
# a file that is a zip file
+
+ # - passing a filename
zipf = zipfile.ZipFile(TESTFN, mode="w")
zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
zipf.close()
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):
# make sure we don't raise an AttributeError when a partially-constructed
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 46ec6ef..5054097 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -130,18 +130,30 @@ _CD64_NUMBER_ENTRIES_TOTAL = 7
_CD64_DIRECTORY_SIZE = 8
_CD64_OFFSET_START_CENTDIR = 9
-def is_zipfile(filename):
- """Quickly see if file is a ZIP file by checking the magic number."""
+def _check_zipfile(fp):
try:
- fpin = io.open(filename, "rb")
- endrec = _EndRecData(fpin)
- fpin.close()
- if endrec:
- return True # file has correct magic number
+ if _EndRecData(fp):
+ return True # file has correct magic number
except IOError:
pass
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):
"""
Read the ZIP64 end-of-archive records and use that to update endrec
diff --git a/Misc/NEWS b/Misc/NEWS
index e247506..ed62a01 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -59,6 +59,9 @@ Core and Builtins
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
boundary.