seawolf2357's picture
Add tools
a65138c verified
# -*- coding: utf-8 -*-
from __future__ import with_statement
import logging
import os.path
from zipfile import ZIP_DEFLATED
from path import split as path_split
from path import get_ancestors as path_ancestors
logger = logging.getLogger(__name__)
def zipfile_nodes(zipfile):
seen = set()
for path in zipfile.namelist():
for anc_path in path_ancestors(path):
if anc_path not in seen:
yield anc_path, ZipFileFolder(zipfile, anc_path)
seen.add(anc_path)
if path not in seen:
if path.endswith('/'):
yield path, ZipFileFolder(zipfile, path)
else:
yield path, ZipFileFile(zipfile, path)
seen.add(path)
class ZipFileNode(object):
def __init__(self, zipfile, path):
self.zipfile = zipfile
self.path = path
class ZipFileFile(ZipFileNode):
def open(self, mode='r', compress_type=ZIP_DEFLATED):
if mode.startswith('r'):
return ZipFileStream(self.zipfile.open(self.path, mode))
elif mode == 'w':
return ZipFileStream(ZipFileWritable(self.zipfile, self.path,
compress_type=compress_type))
def put(self, filesystem_path, compress_type=ZIP_DEFLATED):
self.zipfile.write(filesystem_path, self.path, compress_type)
class ZipFileFolder(ZipFileNode):
def childs(self):
prefix = path_split(self.path)
prefix_len = len(prefix)
for path, node in zipfile_nodes(self.zipfile):
path_segments = path_split(path)
if len(path_segments) == prefix_len + 1:
if path_segments[:prefix_len] == prefix:
yield path_segments[-1], node
def __iter__(self):
for name, node in self.childs():
yield name
def __getitem__(self, name):
for node_name, node in self.childs():
if node_name == name:
return node
raise KeyError(name)
def file(self, name):
path = os.path.join(self.path, name)
return ZipFileFile(self.zipfile, path)
def folder(self, name):
path = os.path.join(self.path, name)
return ZipFileFolder(self.zipfile, path)
class ZipFileStorage(ZipFileFolder):
def __init__(self, *args, **kwargs):
import zipfile
self.zipfile = zipfile.ZipFile(*args, **kwargs)
self.path = ''
def childs(self):
for path, node in zipfile_nodes(self.zipfile):
path_segments = path_split(path)
if len(path_segments) == 1:
yield path_segments[-1], node
def close(self):
self.zipfile.close()
def __enter__(self):
return self
def __exit__(self, *args, **kwargs):
self.close()
class ZipFileStream(object):
def __init__(self, stream):
self.stream = stream
def __getattr__(self, name):
return getattr(self.stream, name)
def __enter__(self):
return self.stream
def __exit__(self, *args, **kwargs):
self.close()
class ZipFileWritable(object):
def __init__(self, zipfile, path, compress_type=ZIP_DEFLATED):
self.zipfile = zipfile
self.path = path
self.compress_type = compress_type
import tempfile
fd, tmp_path = tempfile.mkstemp()
self.tmp_f = os.fdopen(fd, 'w')
self.tmp_path = tmp_path
def __getattr__(self, name):
return getattr(self.tmp_f, name)
def close(self):
self.tmp_f.close()
self.zipfile.write(self.tmp_path, self.path, self.compress_type)
os.unlink(self.tmp_path)