Kaydet (Commit) 59e4779a authored tarafından Martin v. Löwis's avatar Martin v. Löwis

Merged revisions 68885 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r68885 | martin.v.loewis | 2009-01-24 15:00:33 +0100 (Sa, 24 Jan 2009) | 3 lines

  Issue #4710: Extract directories properly in the zipfile module;
  allow adding directories to a zipfile.
........
üst d9aab519
...@@ -9,9 +9,10 @@ from tempfile import TemporaryFile ...@@ -9,9 +9,10 @@ from tempfile import TemporaryFile
from random import randint, random from random import randint, random
import test.support as support import test.support as support
from test.support import TESTFN, run_unittest from test.support import TESTFN, run_unittest, findfile
TESTFN2 = TESTFN + "2" TESTFN2 = TESTFN + "2"
TESTFNDIR = TESTFN + "d"
FIXEDTEST_SIZE = 1000 FIXEDTEST_SIZE = 1000
SMALL_TEST_DATA = [('_ziptest1', '1q2w3e4r5t'), SMALL_TEST_DATA = [('_ziptest1', '1q2w3e4r5t'),
...@@ -1000,6 +1001,28 @@ class TestsWithMultipleOpens(unittest.TestCase): ...@@ -1000,6 +1001,28 @@ class TestsWithMultipleOpens(unittest.TestCase):
def tearDown(self): def tearDown(self):
os.remove(TESTFN2) os.remove(TESTFN2)
class TestWithDirectory(unittest.TestCase):
def setUp(self):
os.mkdir(TESTFN2)
def testExtractDir(self):
zipf = zipfile.ZipFile(findfile("zipdir.zip"))
zipf.extractall(TESTFN2)
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a")))
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a", "b")))
self.assertTrue(os.path.exists(os.path.join(TESTFN2, "a", "b", "c")))
def testStoreDir(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/"))
def tearDown(self):
shutil.rmtree(TESTFN2)
if os.path.exists(TESTFN):
os.remove(TESTFN)
class UniversalNewlineTests(unittest.TestCase): class UniversalNewlineTests(unittest.TestCase):
def setUp(self): def setUp(self):
...@@ -1114,6 +1137,7 @@ class UniversalNewlineTests(unittest.TestCase): ...@@ -1114,6 +1137,7 @@ class UniversalNewlineTests(unittest.TestCase):
def test_main(): def test_main():
run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests, run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
PyZipFileTests, DecryptionTests, TestsWithMultipleOpens, PyZipFileTests, DecryptionTests, TestsWithMultipleOpens,
TestWithDirectory,
UniversalNewlineTests, TestsWithRandomBinaryFiles) UniversalNewlineTests, TestsWithRandomBinaryFiles)
if __name__ == "__main__": if __name__ == "__main__":
......
This diff was suppressed by a .gitattributes entry.
...@@ -4,7 +4,7 @@ Read and write ZIP files. ...@@ -4,7 +4,7 @@ Read and write ZIP files.
XXX references to utf-8 need further investigation. XXX references to utf-8 need further investigation.
""" """
import struct, os, time, sys, shutil import struct, os, time, sys, shutil
import binascii, io import binascii, io, stat
try: try:
import zlib # We may need its compression method import zlib # We may need its compression method
...@@ -959,11 +959,11 @@ class ZipFile: ...@@ -959,11 +959,11 @@ class ZipFile:
""" """
# build the destination pathname, replacing # build the destination pathname, replacing
# forward slashes to platform specific separators. # forward slashes to platform specific separators.
if targetpath[-1:] == "/": if targetpath[-1:] in (os.path.sep, os.path.altsep):
targetpath = targetpath[:-1] targetpath = targetpath[:-1]
# don't include leading "/" from file name if present # don't include leading "/" from file name if present
if os.path.isabs(member.filename): if member.filename[0] == '/':
targetpath = os.path.join(targetpath, member.filename[1:]) targetpath = os.path.join(targetpath, member.filename[1:])
else: else:
targetpath = os.path.join(targetpath, member.filename) targetpath = os.path.join(targetpath, member.filename)
...@@ -975,6 +975,10 @@ class ZipFile: ...@@ -975,6 +975,10 @@ class ZipFile:
if upperdirs and not os.path.exists(upperdirs): if upperdirs and not os.path.exists(upperdirs):
os.makedirs(upperdirs) os.makedirs(upperdirs)
if member.filename[-1] == '/':
os.mkdir(targetpath)
return targetpath
source = self.open(member, pwd=pwd) source = self.open(member, pwd=pwd)
target = open(targetpath, "wb") target = open(targetpath, "wb")
shutil.copyfileobj(source, target) shutil.copyfileobj(source, target)
...@@ -1014,6 +1018,7 @@ class ZipFile: ...@@ -1014,6 +1018,7 @@ class ZipFile:
"Attempt to write to ZIP archive that was already closed") "Attempt to write to ZIP archive that was already closed")
st = os.stat(filename) st = os.stat(filename)
isdir = stat.S_ISDIR(st.st_mode)
mtime = time.localtime(st.st_mtime) mtime = time.localtime(st.st_mtime)
date_time = mtime[0:6] date_time = mtime[0:6]
# Create ZipInfo instance to store file information # Create ZipInfo instance to store file information
...@@ -1022,6 +1027,8 @@ class ZipFile: ...@@ -1022,6 +1027,8 @@ class ZipFile:
arcname = os.path.normpath(os.path.splitdrive(arcname)[1]) arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
while arcname[0] in (os.sep, os.altsep): while arcname[0] in (os.sep, os.altsep):
arcname = arcname[1:] arcname = arcname[1:]
if isdir:
arcname += '/'
zinfo = ZipInfo(arcname, date_time) zinfo = ZipInfo(arcname, date_time)
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
if compress_type is None: if compress_type is None:
...@@ -1035,6 +1042,16 @@ class ZipFile: ...@@ -1035,6 +1042,16 @@ class ZipFile:
self._writecheck(zinfo) self._writecheck(zinfo)
self._didModify = True self._didModify = True
if isdir:
zinfo.file_size = 0
zinfo.compress_size = 0
zinfo.CRC = 0
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
self.fp.write(zinfo.FileHeader())
return
fp = io.open(filename, "rb") fp = io.open(filename, "rb")
# Must overwrite CRC and sizes with correct data later # Must overwrite CRC and sizes with correct data later
zinfo.CRC = CRC = 0 zinfo.CRC = CRC = 0
......
...@@ -139,6 +139,9 @@ Core and Builtins ...@@ -139,6 +139,9 @@ Core and Builtins
Library Library
------- -------
- Issue #4710: Extract directories properly in the zipfile module;
allow adding directories to a zipfile.
- Issue #3807: _multiprocessing build fails when configure is passed - Issue #3807: _multiprocessing build fails when configure is passed
--without-threads argument. When this occurs, _multiprocessing will --without-threads argument. When this occurs, _multiprocessing will
be disabled, and not compiled. be disabled, and not compiled.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment