diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index 4f20209927e7b3d..e54f5154af542b5 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -5463,9 +5463,6 @@ def test_mkdir(self): old_zinfo = zipfile.ZipInfo("directory4/") old_zinfo.external_attr = (0o40777 << 16) | 0x10 - old_zinfo.CRC = 0 - old_zinfo.file_size = 0 - old_zinfo.compress_size = 0 zf.mkdir(old_zinfo) new_zinfo = zf.filelist[3] self.assertEqual(old_zinfo.filename, "directory4/") @@ -5476,6 +5473,32 @@ def test_mkdir(self): zf.extractall(target) self.assertEqual(set(os.listdir(target)), {"directory", "directory2", "directory3", "directory4"}) + def test_mkdir_zipinfo_preserves_metadata(self): + zinfo = zipfile.ZipInfo("directory/", (2001, 2, 3, 4, 5, 6)) + zinfo.compress_type = zipfile.ZIP_STORED + zinfo.compress_level = 1 + zinfo.comment = b"comment" + zinfo.extra = b"\x99\x99\x00\x00" + zinfo.external_attr = (0o40700 << 16) | 0x10 + zinfo.file_size = 1 + zinfo.compress_size = 2 + + archive = io.BytesIO() + with zipfile.ZipFile(archive, "w") as zf: + zf.mkdir(zinfo) + self.assertEqual(zinfo.compress_level, 1) + + self.assertEqual(zinfo.CRC, 0) + self.assertEqual(zinfo.file_size, 0) + self.assertEqual(zinfo.compress_size, 0) + with zipfile.ZipFile(archive) as zf: + written = zf.getinfo("directory/") + self.assertEqual(written.date_time, (2001, 2, 3, 4, 5, 6)) + self.assertEqual(written.compress_type, zipfile.ZIP_STORED) + self.assertEqual(written.comment, b"comment") + self.assertEqual(written.extra, b"\x99\x99\x00\x00") + self.assertEqual(written.external_attr, (0o40700 << 16) | 0x10) + def test_create_directory_with_write(self): with zipfile.ZipFile(TESTFN, "w") as zf: zf.writestr(zipfile.ZipInfo('directory/'), '') diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 418933a2e8d9e87..03d18cbc1fcf33a 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -2529,8 +2529,6 @@ def write(self, filename, arcname=None, strict_timestamps=self._strict_timestamps) if zinfo.is_dir(): - zinfo.compress_size = 0 - zinfo.CRC = 0 self.mkdir(zinfo) else: if compress_type is not None: @@ -2590,14 +2588,13 @@ def mkdir(self, zinfo_or_directory_name, mode=511): if not directory_name.endswith("/"): directory_name += "/" zinfo = ZipInfo(directory_name) - zinfo.compress_size = 0 - zinfo.CRC = 0 zinfo.external_attr = ((0o40000 | mode) & 0xFFFF) << 16 - zinfo.file_size = 0 zinfo.external_attr |= 0x10 else: raise TypeError("Expected type str or ZipInfo") + zinfo.CRC = zinfo.compress_size = zinfo.file_size = 0 + with self._lock: if self._seekable: self.fp.seek(self.start_dir) diff --git a/Misc/NEWS.d/next/Library/2026-07-20-04-33-58.gh-issue-154174.A7mQ2x.rst b/Misc/NEWS.d/next/Library/2026-07-20-04-33-58.gh-issue-154174.A7mQ2x.rst new file mode 100644 index 000000000000000..74054a1bc2b6075 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-20-04-33-58.gh-issue-154174.A7mQ2x.rst @@ -0,0 +1,2 @@ +Fix :meth:`zipfile.ZipFile.mkdir` failing with an :class:`zipfile.ZipInfo` +that does not already have a ``CRC`` attribute.