mirror of https://github.com/python/cpython
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. ........
This commit is contained in:
parent
19fec8b58f
commit
3a8071a26f
|
@ -11,9 +11,10 @@ from tempfile import TemporaryFile
|
||||||
from random import randint, random
|
from random import randint, random
|
||||||
|
|
||||||
import test.test_support as support
|
import test.test_support as support
|
||||||
from test.test_support import TESTFN, run_unittest
|
from test.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'),
|
||||||
|
@ -982,6 +983,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):
|
||||||
|
@ -1090,6 +1113,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__":
|
||||||
|
|
Binary file not shown.
|
@ -2,7 +2,7 @@
|
||||||
Read and write ZIP files.
|
Read and write ZIP files.
|
||||||
"""
|
"""
|
||||||
import struct, os, time, sys, shutil
|
import struct, os, time, sys, shutil
|
||||||
import binascii, cStringIO
|
import binascii, cStringIO, stat
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import zlib # We may need its compression method
|
import zlib # We may need its compression method
|
||||||
|
@ -940,11 +940,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)
|
||||||
|
@ -956,6 +956,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 = file(targetpath, "wb")
|
target = file(targetpath, "wb")
|
||||||
shutil.copyfileobj(source, target)
|
shutil.copyfileobj(source, target)
|
||||||
|
@ -995,6 +999,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
|
||||||
|
@ -1003,6 +1008,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) << 16L # Unix attributes
|
zinfo.external_attr = (st[0] & 0xFFFF) << 16L # Unix attributes
|
||||||
if compress_type is None:
|
if compress_type is None:
|
||||||
|
@ -1016,6 +1023,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 = open(filename, "rb")
|
fp = 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
|
||||||
|
|
|
@ -76,6 +76,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #4710: Extract directories properly in the zipfile module;
|
||||||
|
allow adding directories to a zipfile.
|
||||||
|
|
||||||
- Issue #5008: When a file is opened in append mode with the new IO library,
|
- Issue #5008: When a file is opened in append mode with the new IO library,
|
||||||
do an explicit seek to the end of file (so that e.g. tell() returns the
|
do an explicit seek to the end of file (so that e.g. tell() returns the
|
||||||
file size rather than 0). This is consistent with the behaviour of the
|
file size rather than 0). This is consistent with the behaviour of the
|
||||||
|
|
Loading…
Reference in New Issue