"""This is a vfs class for zip files."""
__docformat__ = "restructuredtext"
from cStringIO import StringIO
import posixpath
import time
import zipfile
class Zip:
"""This is a vfs class for zip files.
The following attributes are used:
root
This is the name of the zip file.
zip
This is a ``zipfile.ZipFile`` instance for working with the zip.
Known bugs:
If you think of a zip file as a filesystem, there is no path to represent
the root of the filesystem as a directory. It'd be nice to add code to
treat "" as the root of the filesystem.
"""
def __init__(self, root):
"""Set the name of the zip file.
If this isn't a zip file, raise a ValueError.
"""
if not zipfile.is_zipfile(root):
raise ValueError("root must be a zip file")
self.root = root
self.zip = zipfile.ZipFile(root)
def __repr__(self):
return '<%s root="%s">' % (self.__class__.__name__, self.root)
def __getattr__(self, attr):
"""Delegate methods.
The following methods are delegated:
join, splitext, splitdrive, split, curdir, pardir
I delegate them to ``posixpath`` instead of ``os.path`` because I want
``posixpath`` behavior even if the user is using Windows.
"""
if attr in ("join", "splitext", "splitdrive", "split", "curdir",
"pardir"):
return getattr(posixpath, attr)
# Keep in mind that in the zip, you must specify directories with a
# trailing slash, but in UNIX and in the Web browser, the trailing slash
# is often optional.
def isdir(self, path):
"""Test whether a path is a directory."""
if not path.endswith("/"):
path += "/"
return self.exists(path)
def exists(self, path):
"""Test whether a path exists."""
to_try = [path]
if not path.endswith("/"):
to_try.append(path + "/")
for x in to_try:
try:
self.zip.getinfo(x)
return True
except KeyError:
continue
else:
return False
def isfile(self, path):
"""Test whether a path is a regular file."""
if path.endswith("/"):
return False
try:
self.zip.getinfo(path)
return True
except KeyError:
return False
def open(self, name, mode_ignored="", buffering_ignored=""):
"""Open a file."""
return StringIO(self.zip.read(name))
def stat(self, path):
"""Return a stat for the given path.
The stat that I'm capable of returning is very stripped. It only has
the two attributes ``st_mtime`` and ``st_size``.
"""
info = self.zip.getinfo(path)
time_str = " ".join(map(str, info.date_time))
time_tuple = time.strptime(time_str, "%Y %m %d %H %M %S")
time_float = time.mktime(time_tuple)
return Stat(time_float, info.file_size)
def translate_path(self, path):
"""Translate ``path`` to the local filename syntax.
Actually, ``path`` is already in the local filename syntax, but this is
your last chance to do anything else, such as making it an absolute
path, etc.
"""
if (not path.endswith("/")) and self.isdir(path):
path += "/"
return path
class Stat:
def __init__(self, st_mtime, st_size):
self.st_mtime = st_mtime
self.st_size = st_size
|