summaryrefslogtreecommitdiff
path: root/Lib
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-04-04 18:56:49 +0000
committerTim Peters <tim.peters@gmail.com>2001-04-04 18:56:49 +0000
commit819a5f28e9e47737c9303846c1a3cb3ae31a0e0b (patch)
tree1e0e2ea1c8403d1c1726031e987f85bbcccc3822 /Lib
parent199504cd535cadfd752daf2aec5385f6badc6922 (diff)
downloadcpython-819a5f28e9e47737c9303846c1a3cb3ae31a0e0b.tar.gz
Sf bug [ #412214 ] ZipFile constructor leaves files open.
This applies the patch Fred Drake created to fix it. I'm checking it in since I had to apply the patch anyway in order to test its behavior on Windows.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_zipfile.py16
-rw-r--r--Lib/zipfile.py14
2 files changed, 30 insertions, 0 deletions
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index 50b8b36a85..bf7770b8cb 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -42,6 +42,22 @@ finally:
if os.path.isfile(zipname):
os.unlink(zipname)
+
+# This test checks that the ZipFile constructor closes the file object
+# it opens if there's an error in the file. If it doesn't, the traceback
+# holds a reference to the ZipFile object and, indirectly, the file object.
+# On Windows, this causes the os.unlink() call to fail because the
+# underlying file is still open. This is SF bug #412214.
+#
+fp = open(srcname, "w")
+fp.write("this is not a legal zip file\n")
+fp.close()
+try:
+ zf = zipfile.ZipFile(srcname)
+except zipfile.BadZipfile:
+ os.unlink(srcname)
+
+
# make sure we don't raise an AttributeError when a partially-constructed
# ZipFile instance is finalized; this tests for regression on SF tracker
# bug #403871.
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index b638592a7a..5dedc1ba8c 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -186,9 +186,23 @@ class ZipFile:
else: # file is not a zip file, just append
fp.seek(0, 2)
else:
+ if not self._filePassed:
+ self.fp.close()
+ self.fp = None
raise RuntimeError, 'Mode must be "r", "w" or "a"'
def _GetContents(self):
+ """Read the directory, making sure we close the file if the format
+ is bad."""
+ try:
+ self._RealGetContents()
+ except BadZipfile:
+ if not self._filePassed:
+ self.fp.close()
+ self.fp = None
+ raise
+
+ def _RealGetContents(self):
"""Read in the table of contents for the ZIP file."""
fp = self.fp
fp.seek(-22, 2) # Start of end-of-archive record