(original) (raw)

changeset: 92544:051105a95461 parent: 92541:a57351993623 parent: 92543:b06e25a357de user: Serhiy Storchaka storchaka@gmail.com date: Tue Sep 23 22:42:02 2014 +0300 files: Lib/test/test_zipfile.py Misc/NEWS description: Issue #20912: Now directories added to ZIP file have correct Unix and MS-DOS directory attributes. diff -r a57351993623 -r 051105a95461 Lib/test/test_zipfile.py --- a/Lib/test/test_zipfile.py Tue Sep 23 22:28:03 2014 +0300 +++ b/Lib/test/test_zipfile.py Tue Sep 23 22:42:02 2014 +0300 @@ -1696,11 +1696,48 @@ os.mkdir(os.path.join(TESTFN2, "a")) self.test_extract_dir() - def test_store_dir(self): + def test_write_dir(self): + dirpath = os.path.join(TESTFN2, "x") + os.mkdir(dirpath) + mode = os.stat(dirpath).st_mode & 0xFFFF + with zipfile.ZipFile(TESTFN, "w") as zipf: + zipf.write(dirpath) + zinfo = zipf.filelist[0] + self.assertTrue(zinfo.filename.endswith("/x/")) + self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) + zipf.write(dirpath, "y") + zinfo = zipf.filelist[1] + self.assertTrue(zinfo.filename, "y/") + self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) + with zipfile.ZipFile(TESTFN, "r") as zipf: + zinfo = zipf.filelist[0] + self.assertTrue(zinfo.filename.endswith("/x/")) + self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) + zinfo = zipf.filelist[1] + self.assertTrue(zinfo.filename, "y/") + self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) + target = os.path.join(TESTFN2, "target") + os.mkdir(target) + zipf.extractall(target) + self.assertTrue(os.path.isdir(os.path.join(target, "y"))) + self.assertEqual(len(os.listdir(target)), 2) + + def test_writestr_dir(self): os.mkdir(os.path.join(TESTFN2, "x")) - zipf = zipfile.ZipFile(TESTFN, "w") - zipf.write(os.path.join(TESTFN2, "x"), "x") - self.assertTrue(zipf.filelist[0].filename.endswith("x/")) + with zipfile.ZipFile(TESTFN, "w") as zipf: + zipf.writestr("x/", b'') + zinfo = zipf.filelist[0] + self.assertEqual(zinfo.filename, "x/") + self.assertEqual(zinfo.external_attr, (0o40775 << 16) | 0x10) + with zipfile.ZipFile(TESTFN, "r") as zipf: + zinfo = zipf.filelist[0] + self.assertTrue(zinfo.filename.endswith("x/")) + self.assertEqual(zinfo.external_attr, (0o40775 << 16) | 0x10) + target = os.path.join(TESTFN2, "target") + os.mkdir(target) + zipf.extractall(target) + self.assertTrue(os.path.isdir(os.path.join(target, "x"))) + self.assertEqual(os.listdir(target), ["x"]) def tearDown(self): rmtree(TESTFN2) diff -r a57351993623 -r 051105a95461 Lib/zipfile.py --- a/Lib/zipfile.py Tue Sep 23 22:28:03 2014 +0300 +++ b/Lib/zipfile.py Tue Sep 23 22:42:02 2014 +0300 @@ -1356,6 +1356,7 @@ zinfo.file_size = 0 zinfo.compress_size = 0 zinfo.CRC = 0 + zinfo.external_attr |= 0x10 # MS-DOS directory flag self.filelist.append(zinfo) self.NameToInfo[zinfo.filename] = zinfo self.fp.write(zinfo.FileHeader(False)) @@ -1416,7 +1417,11 @@ zinfo = ZipInfo(filename=zinfo_or_arcname, date_time=time.localtime(time.time())[:6]) zinfo.compress_type = self.compression - zinfo.external_attr = 0o600 << 16 + if zinfo.filename[-1] == '/': + zinfo.external_attr = 0o40775 << 16 # drwxrwxr-x + zinfo.external_attr |= 0x10 # MS-DOS directory flag + else: + zinfo.external_attr = 0o600 << 16 # ?rw------- else: zinfo = zinfo_or_arcname diff -r a57351993623 -r 051105a95461 Misc/NEWS --- a/Misc/NEWS Tue Sep 23 22:28:03 2014 +0300 +++ b/Misc/NEWS Tue Sep 23 22:42:02 2014 +0300 @@ -137,6 +137,9 @@ Library ------- +- Issue #20912: Now directories added to ZIP file have correct Unix and MS-DOS + directory attributes. + - Issue #21866: ZipFile.close() no longer writes ZIP64 central directory records if allowZip64 is false. /storchaka@gmail.com