Commit aece1874 by willmcgugan

Refinements to the memoryfs class, and added a 'walk' generator to the base class

parent 36b626d8
...@@ -62,7 +62,7 @@ class BrowseFrame(wx.Frame): ...@@ -62,7 +62,7 @@ class BrowseFrame(wx.Frame):
if not is_dir and name.endswith('.txt'): if not is_dir and name.endswith('.txt'):
txt = self.fs.open(new_path).read(50) txt = self.fs.open(new_path).readline()[:50].rstrip()
name += " - "+txt name += " - "+txt
new_item = self.tree.AppendItem(item_id, name, data=wx.TreeItemData({'path':new_path, 'expanded':False})) new_item = self.tree.AppendItem(item_id, name, data=wx.TreeItemData({'path':new_path, 'expanded':False}))
......
...@@ -13,7 +13,8 @@ error_msgs = { ...@@ -13,7 +13,8 @@ error_msgs = {
"LISTDIR_FAILED" : "Unable to get directory listing: %(path)s", "LISTDIR_FAILED" : "Unable to get directory listing: %(path)s",
"NO_SYS_PATH" : "No mapping to OS filesytem: %(path)s,", "NO_SYS_PATH" : "No mapping to OS filesytem: %(path)s,",
"DIR_EXISTS" : "Directory exists (try allow_recreate=True): %(path)s", "DIR_EXISTS" : "Directory exists (try allow_recreate=True): %(path)s",
"OPEN_FAILED" : "Unable to open file: %(path)s" "OPEN_FAILED" : "Unable to open file: %(path)s",
"FILE_LOCKED" : "File is locked: %(path)s",
} }
error_codes = error_msgs.keys() error_codes = error_msgs.keys()
...@@ -29,9 +30,9 @@ class FSError(Exception): ...@@ -29,9 +30,9 @@ class FSError(Exception):
def __str__(self): def __str__(self):
msg = self.msg % dict((k, str(v)) for k,v in self.__dict__.iteritems()) msg = self.msg % dict((k, str(v)) for k, v in self.__dict__.iteritems())
return '%s %s' % (self.code, msg) return '%s. %s' % (self.code, msg)
class NullFile: class NullFile:
...@@ -224,17 +225,40 @@ class FS(object): ...@@ -224,17 +225,40 @@ class FS(object):
elif absolute: elif absolute:
paths = [self.abspath(pathjoin(path, p)) for p in paths] paths = [self.abspath(pathjoin(path, p)) for p in paths]
return paths return paths
def walk_files(self, path="/", wildcard=None, dir_wildcard=None):
dirs = [path]
files = []
while dirs:
path = dirs.pop()
for path in self.listdir(path, full=True):
if self.isdir(path):
if dir_wildcard is not None:
if fnmatch.fnmatch(path, dir_wilcard):
dirs.append(path)
else:
dirs.append(path)
else:
if wildcard is not None:
if fnmatch.fnmatch(path, wildcard):
yield path
else:
yield path
class SubFS(FS): class SubFS(FS):
def __init__(self, parent, sub_dir): def __init__(self, parent, sub_dir):
self.parent = parent self.parent = parent
self.sub_dir = parent.abspath(sub_dir) self.sub_dir = parent.abspath(sub_dir)
#print "sub_dir", self.sub_dir
def __str__(self): def __str__(self):
return "<SubFS \"%s\" of %s>" % (self.sub_dir, self.parent) return "<SubFS \"%s\" of %s>" % (self.sub_dir, self.parent)
...@@ -242,7 +266,6 @@ class SubFS(FS): ...@@ -242,7 +266,6 @@ class SubFS(FS):
def _delegate(self, dirname): def _delegate(self, dirname):
delegate_path = pathjoin(self.sub_dir, resolvepath(makerelative(dirname))) delegate_path = pathjoin(self.sub_dir, resolvepath(makerelative(dirname)))
#print "delegate path", delegate_path
return delegate_path return delegate_path
def getsyspath(self, pathname): def getsyspath(self, pathname):
...@@ -274,7 +297,6 @@ class OSFS(FS): ...@@ -274,7 +297,6 @@ class OSFS(FS):
raise FSError("NO_DIR", expanded_path, msg="Root path is not a directory: %(path)s") raise FSError("NO_DIR", expanded_path, msg="Root path is not a directory: %(path)s")
self.root_path = normpath(os.path.abspath(expanded_path)) self.root_path = normpath(os.path.abspath(expanded_path))
#print "Root path", self.root_path
def __str__(self): def __str__(self):
return "<OSFS \"%s\">" % self.root_path return "<OSFS \"%s\">" % self.root_path
...@@ -320,7 +342,7 @@ class OSFS(FS): ...@@ -320,7 +342,7 @@ class OSFS(FS):
try: try:
paths = os.listdir(self.getsyspath(path)) paths = os.listdir(self.getsyspath(path))
except IOError, e: except (OSError, IOError), e:
raise FSError("LISTDIR_FAILED", path, details=e, msg="Unable to get directory listing: %(path)s - (%(details)s)") raise FSError("LISTDIR_FAILED", path, details=e, msg="Unable to get directory listing: %(path)s - (%(details)s)")
return self._listdir_helper(path, paths, wildcard, full, absolute, hidden, dirs_only, files_only) return self._listdir_helper(path, paths, wildcard, full, absolute, hidden, dirs_only, files_only)
...@@ -470,9 +492,11 @@ class MountFS(FS): ...@@ -470,9 +492,11 @@ class MountFS(FS):
if __name__ == "__main__": if __name__ == "__main__":
osfs = OSFS("~/") osfs = OSFS("~/projects")
print osfs print osfs
#print osfs
for filename in osfs.walk_files("/prettycharts", "*.pov"):
print filename
import browsewin import browsewin
browsewin.browse(osfs) browsewin.browse(osfs)
......
#!/usr/bin/env python #!/usr/bin/env python
import os
from fs import FS, pathsplit, _iteratepath, FSError, print_fs from fs import FS, pathsplit, _iteratepath, FSError, print_fs
try: try:
...@@ -7,6 +8,12 @@ try: ...@@ -7,6 +8,12 @@ try:
except ImportError: except ImportError:
from StringIO import StringIO from StringIO import StringIO
def _check_mode(mode, mode_chars):
for c in mode_chars:
if c not in mode:
return False
return True
class MemoryFile(object): class MemoryFile(object):
def __init__(self, path, memory_fs, value, mode): def __init__(self, path, memory_fs, value, mode):
...@@ -15,32 +22,38 @@ class MemoryFile(object): ...@@ -15,32 +22,38 @@ class MemoryFile(object):
self.memory_fs = memory_fs self.memory_fs = memory_fs
self.mode = mode self.mode = mode
def check_mode(mode_chars):
for c in mode_chars:
if c not in mode:
return False
return True
self.mem_file = None self.mem_file = None
if check_mode('w'): if _check_mode(mode, 'wa'):
if check_mode('+'):
self.mem_file = StringIO(value)
else:
self.mem_file = StringIO() self.mem_file = StringIO()
self.mem_file.write(value)
elif _check_mode(mode, 'w'):
self.mem_file = StringIO()
elif _check_mode(mode, 'ra'):
self.mem_file = StringIO()
self.mem_file.write(value)
elif _check_mode(mode, 'r'):
elif check_mode('r'):
if check_mode('+'):
self.mem_file = StringIO(value) self.mem_file = StringIO(value)
else: else:
if value is not None:
self.mem_file = StringIO(value) self.mem_file = StringIO(value)
else:
self.mem_file = StringIO()
if check_mode('a'): assert self.mem_file is not None, "self.mem_file should have a value"
self.mem_file.seek(0, os.SEEK_END)
self.closed = False self.closed = False
def __del__(self): def __del__(self):
if not self.closed: if not self.closed:
self.close() self.close()
...@@ -58,13 +71,15 @@ class MemoryFile(object): ...@@ -58,13 +71,15 @@ class MemoryFile(object):
return self.mem_file.readline(*args, **kwargs) return self.mem_file.readline(*args, **kwargs)
def close(self): def close(self):
if not self.closed:
value = self.mem_file.getvalue() value = self.mem_file.getvalue()
if 'w' in self.mode:
self.memory_fs._on_close_memory_file(self.path, value) self.memory_fs._on_close_memory_file(self.path, value)
self.mem_file.close() self.mem_file.close()
self.closed = True self.closed = True
def read(self, size=None): def read(self, size=None):
if size is None:
size = -1
return self.mem_file.read(size) return self.mem_file.read(size)
def seek(self, *args, **kwargs): def seek(self, *args, **kwargs):
...@@ -100,18 +115,14 @@ class MemoryFS(FS): ...@@ -100,18 +115,14 @@ class MemoryFS(FS):
self.contents = contents self.contents = contents
self.num_reading = 0
self.num_writing = 0
self.data = None self.data = None
self.locks = 0 self.locks = 0
def lock(self): def lock(self):
return
self.locks += 1 self.locks += 1
def unlock(self): def unlock(self):
return
self.locks -=1 self.locks -=1
assert self.locks >=0, "Lock / Unlock mismatch!" assert self.locks >=0, "Lock / Unlock mismatch!"
...@@ -240,27 +251,26 @@ class MemoryFS(FS): ...@@ -240,27 +251,26 @@ class MemoryFS(FS):
return self return self
def _lock_dir(self, dirpath): def _lock_dir_entry(self, path):
dir_entry = self._get_dir_entry(dirpath) dir_entry = self._get_dir_entry(path)
dir_entry.lock() dir_entry.lock()
def _unlock_dir(self, dirpath): def _unlock_dir_entry(self, path):
dir_entry = self._get_dir_entry(dirpath) dir_entry = self._get_dir_entry(path)
dir_entry.unlock() dir_entry.unlock()
def _is_dir_locked(self, dirpath): def _is_dir_locked(self, path):
dir_entry = self._get_dir_entry(dirpath) dir_entry = self._get_dir_entry(path)
return dir_entry.islocked() return dir_entry.islocked()
def open(self, path, mode="r", **kwargs): def open(self, path, mode="r", **kwargs):
filepath, filename = pathsplit(path) filepath, filename = pathsplit(path)
dir_entry = self._get_dir_entry(path)
parent_dir_entry = self._get_dir_entry(filepath) parent_dir_entry = self._get_dir_entry(filepath)
if parent_dir_entry is None or not parent_dir_entry.isdir(): if parent_dir_entry is None or not parent_dir_entry.isdir():
...@@ -270,22 +280,30 @@ class MemoryFS(FS): ...@@ -270,22 +280,30 @@ class MemoryFS(FS):
if filename not in parent_dir_entry.contents: if filename not in parent_dir_entry.contents:
raise FSError("NO_FILE", path) raise FSError("NO_FILE", path)
self._lock_dir(filepath)
file_dir_entry = parent_dir_entry.contents[filename] file_dir_entry = parent_dir_entry.contents[filename]
if 'a' in mode and file_dir_entry.islocked():
raise FSError("FILE_LOCKED", path)
self._lock_dir_entry(path)
mem_file = MemoryFile(path, self, file_dir_entry.data, mode) mem_file = MemoryFile(path, self, file_dir_entry.data, mode)
file_dir_entry.num_reading += 1
return mem_file return mem_file
elif 'w' in mode: elif 'w' in mode:
if filename not in parent_dir_entry.contents: if filename not in parent_dir_entry.contents:
file_dir_entry = self._make_dir_entry("file", filename) file_dir_entry = self._make_dir_entry("file", filename)
parent_dir_entry.contents[filename] = file_dir_entry parent_dir_entry.contents[filename] = file_dir_entry
else: else:
file_dir_entry = parent_dir_entry.contents[fielname] file_dir_entry = parent_dir_entry.contents[filename]
if file_dir_entry.islocked():
raise FSError("FILE_LOCKED", path)
self._lock_dir_entry(path)
mem_file = MemoryFile(path, self, None, mode) mem_file = MemoryFile(path, self, None, mode)
file_dir_entry.num_writing = 1
return mem_file return mem_file
if parent_dir_entry is None: if parent_dir_entry is None:
...@@ -296,9 +314,9 @@ class MemoryFS(FS): ...@@ -296,9 +314,9 @@ class MemoryFS(FS):
def _on_close_memory_file(self, path, value): def _on_close_memory_file(self, path, value):
filepath, filename = pathsplit(path) filepath, filename = pathsplit(path)
self._unlock_dir(filepath)
dir_entry = self._get_dir_entry(path) dir_entry = self._get_dir_entry(path)
dir_entry.data = value dir_entry.data = value
self._unlock_dir_entry(path)
...@@ -313,15 +331,34 @@ class MemoryFS(FS): ...@@ -313,15 +331,34 @@ class MemoryFS(FS):
def ishidden(self, pathname): def ishidden(self, pathname):
return False return False
if __name__ == "__main__":
def main():
mem_fs = MemoryFS() mem_fs = MemoryFS()
mem_fs.mkdir('test/test2', recursive=True) mem_fs.mkdir('test/test2', recursive=True)
mem_fs.mkdir('test/A', recursive=True) mem_fs.mkdir('test/A', recursive=True)
mem_fs.mkdir('test/A/B', recursive=True) mem_fs.mkdir('test/A/B', recursive=True)
mem_fs.open("test/readme.txt", 'w').write("Hello, World!") mem_fs.open("test/readme.txt", 'w').write("Hello, World!")
mem_fs.open("test/readme.txt", 'wa').write("\nSecond Line")
print mem_fs.open("test/readme.txt", 'r').read()
f1 = mem_fs.open("/test/readme.txt", 'r')
f2 = mem_fs.open("/test/readme.txt", 'r')
print f1.read(10)
print f2.read(10)
f1.close()
f2.close()
f3 = mem_fs.open("/test/readme.txt", 'w')
#print mem_fs.listdir('test') #print mem_fs.listdir('test')
#print mem_fs.isdir("test/test2") #print mem_fs.isdir("test/test2")
#print mem_fs.root #print mem_fs.root
...@@ -329,3 +366,8 @@ if __name__ == "__main__": ...@@ -329,3 +366,8 @@ if __name__ == "__main__":
from browsewin import browse from browsewin import browse
browse(mem_fs) browse(mem_fs)
if __name__ == "__main__":
main()
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