.. codeauthor:: Intra2net AG <info@intra2net>
"""
-import sys
-import os
-
-if sys.version_info.major < 3:
- raise ImportError('Did not backport zipfile from python 3.5 to py2')
-if sys.version_info.minor >= 6:
- # imports for _write_stream_36
- import shutil
-else:
- # imports for create_zipinfo, _write_stream_35 and _get_compressor
- from stat import S_ISDIR
- import time
- import zlib
- crc32 = zlib.crc32
- import bz2
- import struct
-if sys.version_info.minor >= 5:
- from zipfile import *
-else:
- # backport of zipfile from python 3.5 to support stream output
- from zipfile35 import *
+import shutil
+from zipfile import *
from .type_helpers import isstr
-# copied from zipfile.py
-ZIP64_LIMIT = (1 << 31) - 1
-
-
-def _get_compressor(compress_type):
- """Copied fomr zipfile.py in py3.5 (cannot legally import)"""
- if compress_type == ZIP_DEFLATED:
- return zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
- zlib.DEFLATED, -15)
- elif compress_type == ZIP_BZIP2:
- return bz2.BZ2Compressor()
- elif compress_type == ZIP_LZMA:
- return LZMACompressor()
- else:
- return None
-
-
class BytesTellWrapper:
"""
Wrapper around a write-only stream that supports tell but not seek
Create ZipInfo for given file
Optionally set arcname as name of file inside archive.
-
- Adapted from zipfile.py in (ZipInfo.from_file in py3.6, ZipFile.write
- in py3.5)
"""
- if sys.version_info.major >= 3 and sys.version_info.minor >= 6:
- return ZipInfo.from_file(filename, arcname)
-
- st = os.stat(filename)
- isdir = S_ISDIR(st.st_mode)
- mtime = time.localtime(st.st_mtime)
- date_time = mtime[0:6]
- # Create ZipInfo instance to store file information
- if arcname is None:
- arcname = filename
- arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
- while arcname[0] in (os.sep, os.altsep):
- arcname = arcname[1:]
- if isdir:
- arcname += '/'
- zinfo = ZipInfo(arcname, date_time)
- zinfo.external_attr = (st.st_mode & 0xFFFF) << 16 # Unix attributes
- if isdir:
- zinfo.compress_type = ZIP_STORED
- zinfo.file_size = 0
- zinfo.external_attr |= 0x10 # MS-DOS directory flag
- else:
- zinfo.compress_type = self.compression
- zinfo.file_size = st.st_size
-
- return zinfo
+ return ZipInfo.from_file(filename, arcname)
def write_stream(self, src, zinfo):
"""
This is a shortened version of python's
:py:func:`zipfile.ZipFile.write`.
"""
- if sys.version_info.major >= 3 and sys.version_info.minor >= 6:
- return self._write_stream_36(src, zinfo)
- else:
- return self._write_stream_35(src, zinfo)
-
- def _write_stream_35(self, src, zinfo):
- """Implementation of _write_stream based on ZipFile.write (py 3.5)"""
- if not self.fp:
- raise RuntimeError(
- "Attempt to write to ZIP archive that was already closed")
-
- zinfo.flag_bits = 0x00
-
- with self._lock:
- zinfo.header_offset = self.fp.tell() # Start of header bytes
- if zinfo.compress_type == ZIP_LZMA:
- # Compressed data includes an end-of-stream (EOS) marker
- zinfo.flag_bits |= 0x02
-
- self._writecheck(zinfo)
- self._didModify = True
-
- cmpr = _get_compressor(zinfo.compress_type)
- zinfo.flag_bits |= 0x08
-
- # Must overwrite CRC and sizes with correct data later
- zinfo.CRC = CRC = 0
- zinfo.compress_size = compress_size = 0
- # Compressed size can be larger than uncompressed size
- zip64 = self._allowZip64 and \
- zinfo.file_size * 1.05 > ZIP64_LIMIT
- self.fp.write(zinfo.FileHeader(zip64))
- file_size = 0
- while 1:
- buf = src.read(1024 * 8)
- if not buf:
- break
- file_size = file_size + len(buf)
- CRC = crc32(buf, CRC) & 0xffffffff
- if cmpr:
- buf = cmpr.compress(buf)
- compress_size = compress_size + len(buf)
- self.fp.write(buf)
- if cmpr:
- buf = cmpr.flush()
- compress_size = compress_size + len(buf)
- self.fp.write(buf)
- zinfo.compress_size = compress_size
- else:
- zinfo.compress_size = file_size
- zinfo.CRC = CRC
- zinfo.file_size = file_size
-
- # Write CRC and file sizes after the file data
- fmt = '<LQQ' if zip64 else '<LLL'
- self.fp.write(struct.pack(fmt, zinfo.CRC, zinfo.compress_size,
- zinfo.file_size))
- self.start_dir = self.fp.tell()
- self.filelist.append(zinfo)
- self.NameToInfo[zinfo.filename] = zinfo
-
- def _write_stream_36(self, src, zinfo):
- """Implementation of _write_stream based on ZipFile.write (py 3.6)"""
if not self.fp:
raise ValueError(
"Attempt to write to ZIP archive that was already closed")