Commit 274827b9 by willmcgugan

Refactor and ehancements to mountfs

parent fe9f7194
...@@ -15,7 +15,7 @@ class BrowseFrame(wx.Frame): ...@@ -15,7 +15,7 @@ class BrowseFrame(wx.Frame):
self.SetTitle("FS Browser - "+str(fs)) self.SetTitle("FS Browser - "+str(fs))
self.tree = wx.gizmos.TreeListCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT) self.tree = wx.gizmos.TreeListCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
self.tree.AddColumn("FS", 300) self.tree.AddColumn("FS", 300)
self.tree.AddColumn("Description", 250) self.tree.AddColumn("Description", 250)
self.tree.AddColumn("Size", 150) self.tree.AddColumn("Size", 150)
self.tree.AddColumn("Created", 250) self.tree.AddColumn("Created", 250)
...@@ -97,7 +97,7 @@ class BrowseFrame(wx.Frame): ...@@ -97,7 +97,7 @@ class BrowseFrame(wx.Frame):
self.tree.SetItemText(new_item, ct.ctime(), 3) self.tree.SetItemText(new_item, ct.ctime(), 3)
else: else:
self.tree.SetItemText(new_item, 'unknown', 3) self.tree.SetItemText(new_item, 'unknown', 3)
self.tree.SetItemText(new_item, self.fs.desc(new_path), 1) self.tree.SetItemText(new_item, self.fs.desc(new_path), 1)
item_data['expanded'] = True item_data['expanded'] = True
...@@ -119,5 +119,6 @@ def browse(fs): ...@@ -119,5 +119,6 @@ def browse(fs):
if __name__ == "__main__": if __name__ == "__main__":
home_fs = fs.OSFS("~/") from osfs import OSFS
home_fs = OSFS("~/")
browse(home_fs) browse(home_fs)
...@@ -321,6 +321,9 @@ class MemoryFS(FS): ...@@ -321,6 +321,9 @@ class MemoryFS(FS):
def getinfo(self, path): def getinfo(self, path):
dir_entry = self._get_dir_entry(path) dir_entry = self._get_dir_entry(path)
if dir_entry is None:
raise ResourceNotFoundError("NO_RESOURCE", path)
info = {} info = {}
info['created_time'] = dir_entry.created_time info['created_time'] = dir_entry.created_time
......
#!/usr/bin/env python #!/usr/bin/env python
from fs import FS, FSError, pathjoin, pathsplit, print_fs, _iteratepath from fs import FS, FSError, pathjoin, pathsplit, print_fs, _iteratepath, normpath, makeabsolute, makerelative
from objecttree import ObjectTree
from memoryfs import MemoryFS from memoryfs import MemoryFS
class MountFS(FS): class MountFS(FS):
class Mount(object): class DirMount(object):
def __init__(self, path, memory_fs, value, mode): def __init__(self, path, fs):
self.path = path self.path = path
memory_fs._on_close_memory_file(path, self) self.fs = fs
self.fs = None
def __str__(self): def __str__(self):
return "Mount pont: %s, %s" % (self.path, str(self.fs)) return "Mount point: %s"%self.path
def get_mount(self, path, memory_fs, value, mode): class FileMount(object):
def __init__(self, path, open_callable, info_callable=None):
self.open_callable = open_callable
def no_info_callable(path):
return {}
self.info_callable = info_callable or no_info_callable
dir_entry = memory_fs._get_dir_entry(path)
if dir_entry is None or dir_entry.data is None:
return MountFS.Mount(path, memory_fs, value, mode)
else:
return dir_entry.data
def __init__(self): def __init__(self):
self.mounts = {} self.mount_tree = ObjectTree()
self.mem_fs = MemoryFS(file_factory=self.get_mount)
def _delegate(self, path): def _delegate(self, path):
path_components = list(_iteratepath(path)) path = normpath(path)
head_path, object, tail_path = self.mount_tree.partialget(path)
current_dir = self.mem_fs.root
for i, path_component in enumerate(path_components):
if current_dir is None:
return None, None, None
if '.mount' in current_dir.contents:
break
dir_entry = current_dir.contents.get(path_component, None)
current_dir = dir_entry
else:
i = len(path_components)
if '.mount' in current_dir.contents:
mount_point = '/'.join(path_components[:i]) if type(object) is MountFS.DirMount:
mount_filename = pathjoin(mount_point, '.mount') dirmount = object
return dirmount.fs, head_path, tail_path
mount = self.mem_fs.open(mount_filename, 'r') if object is None:
delegate_path = '/'.join(path_components[i:]) return None, None, None
return mount.fs, mount_point, delegate_path
return self, "", path return self, head_path, tail_path
def desc(self, path): def desc(self, path):
fs, mount_path, delegate_path = self._delegate(path) fs, mount_path, delegate_path = self._delegate(path)
if fs is self: if fs is self:
return "Mount dir" if fs.isdir(path):
return "Mount dir"
else:
return "Mounted file"
return "Mounted dir, maps to path %s on %s" % (delegate_path, str(fs)) return "Mounted dir, maps to path %s on %s" % (delegate_path, str(fs))
def isdir(self, path): def isdir(self, path):
fs, mount_path, delegate_path = self._delegate(path) fs, mount_path, delegate_path = self._delegate(path)
if fs is None: if fs is None:
return False raise ResourceNotFoundError("NO_RESOURCE", path)
if fs is self: if fs is self:
return True object = self.mount_tree.get(path, None)
return isinstance(object, dict)
else: else:
return fs.isdir(delegate_path) return fs.isdir(delegate_path)
def isfile(self, path):
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
return ResourceNotFoundError("NO_RESOURCE", path)
if fs is self:
object = self.mount_tree.get(path, None)
return type(object) is MountFS.FileMount
else:
return fs.isfile(delegate_path)
def listdir(self, path="/", wildcard=None, full=False, absolute=False, hidden=False, dirs_only=False, files_only=False): def listdir(self, path="/", wildcard=None, full=False, absolute=False, hidden=False, dirs_only=False, files_only=False):
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path) fs, mount_path, delegate_path = self._delegate(path)
if fs is None: if fs is None:
...@@ -80,38 +81,180 @@ class MountFS(FS): ...@@ -80,38 +81,180 @@ class MountFS(FS):
if fs is self: if fs is self:
if files_only: if files_only:
return [] return []
return self.mem_fs.listdir(path,
wildcard=wildcard, paths = self.mount_tree[path].keys()
full=full, return self._listdir_helper(path,
absolute=absolute, paths,
hidden=hidden, wildcard,
dirs_only=True, full,
files_only=False) absolute,
hidden,
dirs_only,
files_only)
else: else:
paths = fs.listdir(delegate_path, paths = fs.listdir(delegate_path,
wildcard=wildcard, wildcard=wildcard,
full=full, full=False,
absolute=absolute, absolute=False,
hidden=hidden, hidden=hidden,
dirs_only=dirs_only, dirs_only=dirs_only,
files_only=files_only) files_only=files_only)
if full or absolute: if full or absolute:
if full: if full:
mount_path = makeabsolute(mount_path) path = makeabsolute(path)
else: else:
mount_path = makerelative(mount_path) path = makerelative(path)
paths = [pathjoin(mount_path, path) for path in paths] paths = [pathjoin(path, p) for p in paths]
return paths return paths
def mount(self, name, path, fs): def open(self, path, mode="r", **kwargs):
self.mem_fs.mkdir(path, recursive=True)
mount_filename = pathjoin(path, '.mount') object = self.mount_tree.get(path, None)
mount = self.mem_fs.open(mount_filename, 'w') if type(object) is MountFS.FileMount:
mount.name = name callable = object.open_callable
mount.fs = fs return callable(path, mode, **kwargs)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError("NO_FILE", path)
return fs.open(delegate_path, mode, **kwargs)
def mountdir(self, path, fs):
path = normpath(path)
self.mount_tree[path] = MountFS.DirMount(path, fs)
def mountfile(self, path, open_callable=None, info_callable=None):
path = normpath(path)
self.mount_tree[path] = MountFS.FileMount(path, callable, info_callable)
def getinfo(self, path):
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError("NO_RESOURCE", path)
self.mounts[name] = (path, fs) if fs is self:
if self.isfile(path):
return self.mount_tree[path].info_callable(path)
return {}
return fs.getinfo(delegate_path)
#
#class MountFS(FS):
#
# class Mount(object):
# def __init__(self, path, memory_fs, value, mode):
# self.path = path
# memory_fs._on_close_memory_file(path, self)
# self.fs = None
#
# def __str__(self):
# return "Mount pont: %s, %s" % (self.path, str(self.fs))
#
# def get_mount(self, path, memory_fs, value, mode):
#
# dir_entry = memory_fs._get_dir_entry(path)
# if dir_entry is None or dir_entry.data is None:
# return MountFS.Mount(path, memory_fs, value, mode)
# else:
# return dir_entry.data
#
# def __init__(self):
# self.mounts = {}
# self.mem_fs = MemoryFS(file_factory=self.get_mount)
#
# def _delegate(self, path):
# path_components = list(_iteratepath(path))
#
# current_dir = self.mem_fs.root
# for i, path_component in enumerate(path_components):
#
# if current_dir is None:
# return None, None, None
#
# if '.mount' in current_dir.contents:
# break
#
# dir_entry = current_dir.contents.get(path_component, None)
# current_dir = dir_entry
# else:
# i = len(path_components)
#
# if '.mount' in current_dir.contents:
#
# mount_point = '/'.join(path_components[:i])
# mount_filename = pathjoin(mount_point, '.mount')
#
# mount = self.mem_fs.open(mount_filename, 'r')
# delegate_path = '/'.join(path_components[i:])
# return mount.fs, mount_point, delegate_path
#
# return self, "", path
#
# def desc(self, path):
# fs, mount_path, delegate_path = self._delegate(path)
# if fs is self:
# return "Mount dir"
#
# return "Mounted dir, maps to path %s on %s" % (delegate_path, str(fs))
#
# def isdir(self, path):
# fs, mount_path, delegate_path = self._delegate(path)
# if fs is None:
# return False
#
# if fs is self:
# return True
# else:
# return fs.isdir(delegate_path)
#
# def listdir(self, path="/", wildcard=None, full=False, absolute=False, hidden=False, dirs_only=False, files_only=False):
# fs, mount_path, delegate_path = self._delegate(path)
#
# if fs is None:
# raise ResourceNotFoundError("NO_DIR", path)
#
# if fs is self:
# if files_only:
# return []
# return self.mem_fs.listdir(path,
# wildcard=wildcard,
# full=full,
# absolute=absolute,
# hidden=hidden,
# dirs_only=True,
# files_only=False)
# else:
# paths = fs.listdir(delegate_path,
# wildcard=wildcard,
# full=full,
# absolute=absolute,
# hidden=hidden,
# dirs_only=dirs_only,
# files_only=files_only)
# if full or absolute:
# if full:
# mount_path = makeabsolute(mount_path)
# else:
# mount_path = makerelative(mount_path)
# paths = [pathjoin(mount_path, path) for path in paths]
#
# return paths
#
# def mount(self, name, path, fs):
# self.mem_fs.mkdir(path, recursive=True)
# mount_filename = pathjoin(path, '.mount')
# mount = self.mem_fs.open(mount_filename, 'w')
# mount.name = name
# mount.fs = fs
#
# self.mounts[name] = (path, fs)
if __name__ == "__main__": if __name__ == "__main__":
...@@ -123,12 +266,30 @@ if __name__ == "__main__": ...@@ -123,12 +266,30 @@ if __name__ == "__main__":
mountfs = MountFS() mountfs = MountFS()
mountfs.mount("fs1", '1/2', fs1) mountfs.mountdir('1/2', fs1)
mountfs.mount("fs1", '1/another', fs1) mountfs.mountdir('1/another', fs1)
def testfile(*args, **kwargs):
print args, kwargs
def testfile_info(*args, **kwargs):
print "testfile_info", args, kwargs
return {'size':100}
mountfs.mountfile('filedir/file.txt', testfile, testfile_info)
print mountfs.getinfo("filedir/file.txt")
#print mountfs.listdir('1/2/Memroot/B/C') #print mountfs.listdir('1/2/Memroot/B/C')
print mountfs.isdir("1")
print mountfs.desc('1/2/Memroot/B') print mountfs.desc('1/2/Memroot/B')
print_fs(mountfs) print_fs(mountfs)
import browsewin
browsewin.browse(mountfs)
print mountfs.getinfo("1/2")
#print mountfs._delegate('1/2/Memroot/B') #print mountfs._delegate('1/2/Memroot/B')
\ No newline at end of file
...@@ -12,23 +12,26 @@ class ObjectTree(object): ...@@ -12,23 +12,26 @@ class ObjectTree(object):
def __init__(self): def __init__(self):
self.root = _ObjectDict() self.root = _ObjectDict()
def _splitpath(self, path):
return [p for p in path.split('/') if p]
def _locate(self, path): def _locate(self, path):
current = self.root current = self.root
for path_component in path.split('/'): for path_component in self._splitpath(path):
if type(current) is not _ObjectDict: if type(current) is not _ObjectDict:
return None return None
node = current.get(path_component, None) node = current.get(path_component, None)
if node is None: if node is None:
return None return None
current = node current = node
return node return current
def __setitem__(self, path, object): def __setitem__(self, path, object):
if not path: if not path:
raise IndexError("No path supplied") raise IndexError("No path supplied")
current = self.root current = self.root
path, name = path.rsplit('/', 1) path, name = path.rsplit('/', 1)
for path_component in path.split('/'): for path_component in self._splitpath(path):
node = current.get(path_component, None) node = current.get(path_component, None)
if type(node) is not _ObjectDict: if type(node) is not _ObjectDict:
new_dict = _ObjectDict() new_dict = _ObjectDict()
...@@ -57,6 +60,21 @@ class ObjectTree(object): ...@@ -57,6 +60,21 @@ class ObjectTree(object):
return default return default
return node return node
def partialget(self, path, default=None):
current = self.root
partial_path = []
remaining_path = self._splitpath(path)
for path_component in remaining_path[:]:
if type(current) is not _ObjectDict:
return "/".join(partial_path), current, "/".join(remaining_path)
partial_path.append(path_component)
remaining_path.pop(0)
node = current.get(path_component, None)
if node is None:
return None, default, None
current = node
return path, current, ""
def isobject(self, path): def isobject(self, path):
node = self._locate(path) node = self._locate(path)
return type(node) is not _ObjectDict return type(node) is not _ObjectDict
...@@ -87,6 +105,8 @@ if __name__ == "__main__": ...@@ -87,6 +105,8 @@ if __name__ == "__main__":
print ot['a/b/c'] print ot['a/b/c']
print ot.partialget("/a/b/c/d/e/f")
ot['a/b/c/d'] = "?" ot['a/b/c/d'] = "?"
print ot['a/b/c'].keys() print ot['a/b/c'].keys()
\ No newline at end of file
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