summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorR David Murray <rdmurray@bitdance.com>2012-04-12 22:44:42 (GMT)
committerR David Murray <rdmurray@bitdance.com>2012-04-12 22:44:42 (GMT)
commit51804e9725dd7e727201ba0dffa42db5592c8023 (patch)
tree04631039381f53467bbb40b61a61de9f477b6c01 /Lib
parentd46d69c2796172926296bbc5584551355af4a63a (diff)
downloadcpython-51804e9725dd7e727201ba0dffa42db5592c8023.zip
cpython-51804e9725dd7e727201ba0dffa42db5592c8023.tar.gz
cpython-51804e9725dd7e727201ba0dffa42db5592c8023.tar.bz2
#14399: zipfile now correctly handles comments added to empty zipfiles.
Patch by Serhiy Storchaka. This also moves the TypeError that results from trying to use a unicode comment from the 'close' step to the point at which the comment is added to the zipfile.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_zipfile.py22
-rw-r--r--Lib/zipfile.py33
2 files changed, 44 insertions, 11 deletions
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index bb0d79a..c0675c6 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -972,6 +972,28 @@ class OtherTests(unittest.TestCase):
with zipfile.ZipFile(TESTFN, mode="r") as zipfr:
self.assertEqual(zipfr.comment, comment2)
+ def test_unicode_comment(self):
+ with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf:
+ zipf.writestr("foo.txt", "O, for a Muse of Fire!")
+ with self.assertRaises(TypeError):
+ zipf.comment = "this is an error"
+
+ def test_change_comment_in_empty_archive(self):
+ with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf:
+ self.assertFalse(zipf.filelist)
+ zipf.comment = b"this is a comment"
+ with zipfile.ZipFile(TESTFN, "r") as zipf:
+ self.assertEqual(zipf.comment, b"this is a comment")
+
+ def test_change_comment_in_nonempty_archive(self):
+ with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf:
+ zipf.writestr("foo.txt", "O, for a Muse of Fire!")
+ with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf:
+ self.assertTrue(zipf.filelist)
+ zipf.comment = b"this is a comment"
+ with zipfile.ZipFile(TESTFN, "r") as zipf:
+ self.assertEqual(zipf.comment, b"this is a comment")
+
def check_testzip_with_bad_crc(self, compression):
"""Tests that files with bad CRCs return their name from testzip."""
zipdata = self.zips_with_bad_crc[compression]
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 6ca269f..435a3e9 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -698,7 +698,7 @@ class ZipFile:
self.compression = compression # Method of compression
self.mode = key = mode.replace('b', '')[0]
self.pwd = None
- self.comment = b''
+ self._comment = b''
# Check if we were passed a file-like object
if isinstance(file, str):
@@ -774,7 +774,7 @@ class ZipFile:
print(endrec)
size_cd = endrec[_ECD_SIZE] # bytes in central directory
offset_cd = endrec[_ECD_OFFSET] # offset of central directory
- self.comment = endrec[_ECD_COMMENT] # archive comment
+ self._comment = endrec[_ECD_COMMENT] # archive comment
# "concat" is zero, unless zip was concatenated to another file
concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
@@ -886,6 +886,24 @@ class ZipFile:
else:
self.pwd = None
+ @property
+ def comment(self):
+ """The comment text associated with the ZIP file."""
+ return self._comment
+
+ @comment.setter
+ def comment(self, comment):
+ if not isinstance(comment, bytes):
+ raise TypeError("comment: expected bytes, got %s" % type(comment))
+ # check for valid comment length
+ if len(comment) >= ZIP_MAX_COMMENT:
+ if self.debug:
+ print('Archive comment is too long; truncating to %d bytes'
+ % ZIP_MAX_COMMENT)
+ comment = comment[:ZIP_MAX_COMMENT]
+ self._comment = comment
+ self._didModify = True
+
def read(self, name, pwd=None):
"""Return file bytes (as a string) for name."""
with self.open(name, "r", pwd) as fp:
@@ -1287,18 +1305,11 @@ class ZipFile:
centDirSize = min(centDirSize, 0xFFFFFFFF)
centDirOffset = min(centDirOffset, 0xFFFFFFFF)
- # check for valid comment length
- if len(self.comment) >= ZIP_MAX_COMMENT:
- if self.debug > 0:
- msg = 'Archive comment is too long; truncating to %d bytes' \
- % ZIP_MAX_COMMENT
- self.comment = self.comment[:ZIP_MAX_COMMENT]
-
endrec = struct.pack(structEndArchive, stringEndArchive,
0, 0, centDirCount, centDirCount,
- centDirSize, centDirOffset, len(self.comment))
+ centDirSize, centDirOffset, len(self._comment))
self.fp.write(endrec)
- self.fp.write(self.comment)
+ self.fp.write(self._comment)
self.fp.flush()
if not self._filePassed: