class ZipPath(Path):
modulesuffixes = set()
def __init__(self, pathobj=""):
self.sep = "/"
self.files = {}
if pathobj:
self.zippath, self.path = ZipPath.split_zip_path(pathobj)
F = zipfile.ZipFile(self.zippath)
for Z in F.filelist:
self.files[Z.filename] = Z
else:
self.zippath, self.path = "", ""
 
def new_in_zip(self, path):
zippathobj = self.__class__()
zippathobj.path = path
zippathobj.zippath = self.zippath
zippathobj.files = self.files
return zippathobj
 
@classmethod
def add_suffix(cls, suffixinfo):
cls.modulesuffixes.add(suffixinfo)
 
@classmethod
def split_zip_path(cls, pathobj, sep="/"):
path = pathobj
filename = ""
while True:
if zipfile.is_zipfile(path):
return path, filename
p = os.path.dirname(path)
if p == path:
raise ValueError("path not in zipped file")
filename = (os.path.basename(path) + sep + filename if filename \
else os.path.basename(path))
path = p
 
def fullpath(self):
if self.ismodule():
module = self.base()
name, ext = os.path.splitext(module)
P = self.parent().fullpath()
return P+"."+name if P else name
elif self.ispackage():
directory, name = self.splitbase()
P = directory.fullpath()
return P+"."+name if P else name
else:
return ""
 
def exists(self):
return self.ispackage() or self.ismodule()
 
def isempty(self):
return self.path == ""
 
def ispackage(self):
return self.path+self.sep+"__init__.py" in self.files
 
def ismodule(self):
suffixes = [""]+[suffix.suffix for suffix in self.modulesuffixes]
for suffix in suffixes:
if self.path+suffix in self.files:
return True
return False
 
def parent(self):
return self.new_in_zip(os.path.dirname(self.path))
 
def children(self):
if os.path.isdir(self.path):
return [self.new_in_zip(self.path.joinpath(f)) for f in os.path.listdir(self.path)]
 
def joinpath(self, *args):
return self.new_in_zip(self.sep.join([self.path]+list(args)))
 
def base(self):
return os.path.basename(self.path)
 
def split(self):
return self.path.split(self.sep)
 
def splitbase(self):
return self.parent(), self.base()
# # # # # --  Tests --  # # # 
 
# required: jinja2 installation =>
#
# python easy_install.py --zip-ok Jinja2==dev
#
 
import jinja2
for suffix in imp.get_suffixes():
ZipPath.add_suffix(SuffixInfo(suffix))
ZP = ZipPath(jinja2.__file__)
assert ZP.ismodule()
assert ZP.parent().ispackage()
sandbox = ZP.parent().joinpath("sandbox.py")
assert sandbox.ismodule()
assert sandbox.fullpath() == "jinja2.sandbox"
assert ZP.find(".sandbox").fullpath() == "jinja2.sandbox"