summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2014-09-23 19:39:59 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2014-09-23 19:39:59 (GMT)
commit6d343e708b44fc7100df0fd9b9f85276360fb4cd (patch)
treeabd82cf916279e06667376acca014ff6509c3f7a
parent1af262c65cbc7012086b389654eff9438acfbe66 (diff)
downloadcpython-6d343e708b44fc7100df0fd9b9f85276360fb4cd.zip
cpython-6d343e708b44fc7100df0fd9b9f85276360fb4cd.tar.gz
cpython-6d343e708b44fc7100df0fd9b9f85276360fb4cd.tar.bz2
Issue #20912: Now directories added to ZIP file have correct Unix and MS-DOS
directory attributes.
-rw-r--r--Lib/test/test_zipfile.py43
-rw-r--r--Lib/zipfile.py7
-rw-r--r--Misc/NEWS3
3 files changed, 49 insertions, 4 deletions
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index c309e37..fbeda53 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -1472,11 +1472,48 @@ class TestWithDirectory(unittest.TestCase):
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"))
with zipfile.ZipFile(TESTFN, "w") as zipf:
- zipf.write(os.path.join(TESTFN2, "x"), "x")
- self.assertTrue(zipf.filelist[0].filename.endswith("x/"))
+ 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 --git a/Lib/zipfile.py b/Lib/zipfile.py
index 6722c40..ecdd8a5 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -1150,6 +1150,7 @@ class ZipFile(object):
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))
@@ -1211,7 +1212,11 @@ class ZipFile(object):
date_time=time.localtime(time.time())[:6])
zinfo.compress_type = self.compression
- zinfo.external_attr = 0600 << 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 --git a/Misc/NEWS b/Misc/NEWS
index 5b69a1b..02e9c4c 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,9 @@ Core and Builtins
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.