Commit 9284f4e2 by willmcgugan

Expanded on ZipFS and fixed a few bugs.

parent 0b8d5041
......@@ -24,7 +24,7 @@ class InfoFrame(wx.Frame):
self.list_ctrl.SetColumnWidth(1, 300)
for key in keys:
self.list_ctrl.Append((key, str(info[key])))
self.list_ctrl.Append((key, repr(info[key])))
......@@ -38,7 +38,7 @@ class BrowseFrame(wx.Frame):
self.SetTitle("FS Browser - "+str(fs))
self.tree = wx.gizmos.TreeListCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
self.tree.AddColumn("FS", 300)
self.tree.AddColumn("File System", 300)
self.tree.AddColumn("Description", 250)
self.tree.AddColumn("Size", 150)
self.tree.AddColumn("Created", 250)
......
......@@ -156,6 +156,9 @@ class MemoryFS(FS):
def __str__(self):
return "<MemoryFS>"
def __unicode__(self):
return unicode(self.__str__())
def _get_dir_entry(self, dirpath):
self._lock.acquire()
try:
......@@ -212,6 +215,8 @@ class MemoryFS(FS):
self._lock.release()
def makedir(self, dirname, mode=0777, recursive=False, allow_recreate=False):
if not dirname:
raise PathError("INVALID_PATH", "Path is empty")
self._lock.acquire()
try:
fullpath = dirname
......@@ -234,7 +239,7 @@ class MemoryFS(FS):
break
if not dir_item.isdir():
raise ResourceNotFoundError("NO_DIR", dirname, msg="Can not create a directory, because path references a file: %(path)s")
current_dir = dir_item.contents
current_dir = dir_item
current_dir = self.root
for path_component in _iteratepath(dirpath):
......
......@@ -3,6 +3,7 @@
from fs import *
from zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
from memoryfs import MemoryFS
try:
from cStringIO import StringIO
......@@ -44,7 +45,7 @@ class _ExceptionProxy(object):
class ZipFS(FS):
def __init__(self, zip_file, mode="r", compression="deflated", allowZip64=False):
FS.__init__(self)
FS.__init__(self, thread_syncronize=True)
if compression == "deflated":
compression_type = ZIP_DEFLATED
elif compression == "stored":
......@@ -57,73 +58,134 @@ class ZipFS(FS):
self.zip_mode = mode
self.zf = ZipFile(zip_file, mode, compression_type, allowZip64)
self.zip_path = str(zip_file)
self.temp_fs = None
if mode in 'wa':
self.temp_fs = tempfs.TempFS()
self.resource_list = None
if mode == 'r':
self.resource_list = self.zf.namelist()
self._path_fs = MemoryFS()
if mode in 'ra':
self._parse_resource_list()
def __str__(self):
return "<ZipFS: %s>" % self.zip_path
def __unicode__(self):
return unicode(self.__str__())
def _parse_resource_list(self):
for path in self.zf.namelist():
self._add_resource(path)
def _add_resource(self, path):
if path.endswith('/'):
path = path[:-1]
self._path_fs.makedir(path, recursive=True, allow_recreate=True)
else:
dirpath, filename = pathsplit(path)
if dirpath:
self._path_fs.makedir(dirpath, recursive=True, allow_recreate=True)
f = self._path_fs.open(path, 'w')
f.close()
def _get_resource_list(self):
if not self.zf:
raise ValueError("Zip file has been closed")
return self.resource_list or self.zf.namelist()
def close(self):
"""Finalizes the zip file so that it can be read.
No further operations will work after this method is called."""
if self.zf:
self.zf.close()
self.zf = _ExceptionProxy()
self._lock.acquire()
try:
if self.zf:
self.zf.close()
self.zf = _ExceptionProxy()
finally:
self._lock.release()
def __del__(self):
self.close()
def open(self, path, mode="r", **kwargs):
path = normpath(path)
self._lock.acquire()
try:
path = normpath(path)
self.zip_path = path
if 'r' in mode:
if self.zip_mode not in 'ra':
raise OperationFailedError("OPEN_FAILED", path=path, msg="Zip file must be opened for reading ('r') or appending ('a')")
try:
contents = self.zf.read(path)
except KeyError:
raise ResourceNotFoundError("NO_FILE", path)
return StringIO(contents)
if 'r' in mode:
if self.zip_mode not in 'ra':
raise OperationFailedError("OPEN_FAILED", path=path, msg="Zip file must be opened for reading ('r') or appending ('a')")
try:
contents = self.zf.read(path)
except KeyError:
raise ResourceNotFoundError("NO_FILE", path)
return StringIO(contents)
if 'w' in mode:
dirname, filename = pathsplit(path)
if dirname:
self.temp_fs.makedir(dirname, recursive=True, allow_recreate=True)
if 'w' in mode:
dirname, filename = pathsplit(path)
if dirname:
self.temp_fs.makedir(dirname, recursive=True, allow_recreate=True)
f = _TempWriteFile(self.temp_fs, path, self._on_write_close)
self._add_resource(path)
f = _TempWriteFile(self.temp_fs, path, self._on_write_close)
return f
return f
raise ValueError("Mode must contain be 'r' or 'w'")
raise ValueError("Mode must contain be 'r' or 'w'")
finally:
self._lock.release()
def _on_write_close(self, filename):
sys_path = self.temp_fs.getsyspath(filename)
self.zf.write(sys_path, filename)
self._lock.acquire()
try:
sys_path = self.temp_fs.getsyspath(filename)
self.zf.write(sys_path, filename)
except:
self._lock.release()
def desc(self, path):
if self.isdir(path):
return "Dir in zip file: %s" % self.zip_path
else:
return "File in zip file: %s" % self.zip_path
def isdir(self, path):
return self._path_fs.isdir(path)
def listdir(self, path="/", wildcard=None, full=False, absolute=False, hidden=False, dirs_only=False, files_only=False):
def isfile(self, path):
return self._path_fs.isdir(path)
def exists(self, path):
return self._path_fs.exists(path)
path = normpath(path)
def makedir(self, dirname, mode=0777, recursive=False, allow_recreate=False):
dirname = normpath(dirname)
if self.zip_mode not in "wa":
raise OperationFailedError("MAKEDIR_FAILED", dirname, "Zip file must be opened for writing ('w') or appending ('a')")
if not dirname.endswith('/'):
dirname += '/'
self._add_resource(dirname)
def indir(p):
p = makeabsolute(p)
list_dir = makeabsolute(path)
sub_path = normpath(p[len(list_dir)+1:])
return sub_path and '/' not in sub_path
def listdir(self, path="/", wildcard=None, full=False, absolute=False, hidden=False, dirs_only=False, files_only=False):
paths = [getresourcename(p.rstrip('/')) for p in self._get_resource_list() if indir(p.rstrip('/'))]
return self._path_fs.listdir(path, wildcard, full, absolute, hidden, dirs_only, files_only)
return self._listdir_helper(path, paths, wildcard, full, absolute, hidden, dirs_only, files_only)
def getinfo(self, path):
self._lock.acquire()
try:
if not self.exists(path):
return ResourceNotFoundError("NO_RESOURCE", path)
path = normpath(path).lstrip('/')
try:
zi = self.zf.getinfo(path)
zinfo = dict((attrib, getattr(zi, attrib)) for attrib in dir(zi) if not attrib.startswith('_'))
except KeyError:
zinfo = {'file_size':0}
info = {'size' : zinfo['file_size']}
info.update(zinfo)
return info
finally:
self._lock.release()
if __name__ == "__main__":
def test():
......@@ -138,9 +200,31 @@ if __name__ == "__main__":
zfs = ZipFS("t2.zip", "r")
print zfs.listdir("/tagging-trunk")
print zfs.listdir("/")
import browsewin
browsewin.browse(zfs)
zfs.close()
zfs.open("t.txt")
print zfs.listdir("/")
#zfs.open("t.txt")
#print zfs.listdir("/")
test2()
zfs = ZipFS("t3.zip", "w")
zfs.createfile("t.txt", "Hello, World!")
zfs.createfile("foo/bar/baz/t.txt", "Hello, World!")
#print zfs.isdir("t.txt")
#print zfs.isfile("t.txt")
#print zfs.isfile("foo/bar")
zfs.close()
zfs = ZipFS("t3.zip", "r")
print "--"
print zfs.listdir("foo")
print zfs.isdir("foo/bar")
print zfs.listdir("foo/bar")
print zfs.listdir("foo/bar/baz")
print_fs(zfs)
#zfs = ZipFS("t3.zip", "r")
#print zfs.zf.getinfo("asd.txt")
#zfs.close()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment