diff options
author | R David Murray <rdmurray@bitdance.com> | 2012-04-12 22:44:42 (GMT) |
---|---|---|
committer | R David Murray <rdmurray@bitdance.com> | 2012-04-12 22:44:42 (GMT) |
commit | 51804e9725dd7e727201ba0dffa42db5592c8023 (patch) | |
tree | 04631039381f53467bbb40b61a61de9f477b6c01 /Lib | |
parent | d46d69c2796172926296bbc5584551355af4a63a (diff) | |
download | cpython-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.py | 22 | ||||
-rw-r--r-- | Lib/zipfile.py | 33 |
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: |