From 837e818319e2394caf2dcab5e40b18dcad3c6f0b Mon Sep 17 00:00:00 2001 From: Evan Broder Date: Sun, 21 Feb 2010 08:06:11 -0800 Subject: [PATCH] I apparently used to have a crappy sense of style. Let's fix that. --- routefs/__init__.py | 47 +++++++++++++++++++++++++--------------- routefs/dictfs.py | 22 +++++++++++-------- routefs/examples/dictexfs.py | 3 +++ routefs/examples/homefs.py | 13 +++++++---- routefs/examples/pyhesiodfs.py | 18 +++++++++------ 5 files changed, 66 insertions(+), 37 deletions(-) diff --git a/routefs/__init__.py b/routefs/__init__.py index a9a9144..294ec93 100644 --- a/routefs/__init__.py +++ b/routefs/__init__.py @@ -7,13 +7,17 @@ inspired by filesystems, and now you can have filesystems inspired by URLs. """ -import fuse -import routes + import errno import stat +import fuse +import routes + + fuse.fuse_python_api = (0, 2) + class RouteStat(fuse.Stat): """ RouteStat is a descendent of fuse.Stat, defined to make sure that @@ -31,10 +35,11 @@ class RouteStat(fuse.Stat): self.st_mtime = 0 self.st_ctime = 0 + class RouteFS(fuse.Fuse): """ RouteFS: Web 2.0 for filesystems - + Any method that will be used as the controller in a Routes mapping (either by explicitly specifying the controller or by using the ':controller' variable) must be added to RouteFS.controllers @@ -42,21 +47,21 @@ class RouteFS(fuse.Fuse): controllers = [] def __init__(self, *args, **kwargs): super(RouteFS, self).__init__(*args, **kwargs) - + self.map = self.make_map() self.map.create_regs(self.controllers) - + def make_map(self): """ This method should be overridden by descendents of RouteFS to define the routing for the filesystem """ m = routes.Mapper() - + m.connect(':controller') - + return m - + def _get_file(self, path): """ Find the filesystem entry object for a given path @@ -73,36 +78,36 @@ class RouteFS(fuse.Fuse): if type(result) is list: result = Directory(result) return result - + def readdir(self, path, offset): """ If the path referred to is a directory, return the elements of that diectory """ return self._get_file(path).readdir(offset) - + def getattr(self, path): """ Return the stat information for a path - + The stat information for a directory, symlink, or file is predetermined based on which it is. """ return self._get_file(path).getattr() - + def read(self, path, length, offset): """ If the path specified is a file, return the requested portion of the file """ return self._get_file(path).read(length, offset) - + def readlink(self, path): """ If the path specified is a symlink, return the target """ return self._get_file(path).readlink() - + def write(self, path, buf, offset): """ If the path specified is a file, call the appropriate member @@ -110,6 +115,7 @@ class RouteFS(fuse.Fuse): """ return self._get_file(path).write(buf, offset) + class TreeKey(object): def getattr(self): return -errno.EINVAL @@ -122,6 +128,7 @@ class TreeKey(object): def write(self, length, offset): return -errno.EINVAL + class NoEntry(TreeKey): def getattr(self): return -errno.ENOENT @@ -134,20 +141,22 @@ class NoEntry(TreeKey): def write(self, length, offset): return -errno.ENOENT + class TreeEntry(TreeKey): default_mode = 0444 - + def __new__(cls, contents, mode=None): return super(TreeEntry, cls).__new__(cls, contents) - + def __init__(self, contents, mode=None): if mode is None: self.mode = self.default_mode else: self.mode = mode - + super(TreeEntry, self).__init__(contents) + class Directory(TreeEntry, list): """ A dummy class representing a filesystem entry that should be a @@ -165,6 +174,7 @@ class Directory(TreeEntry, list): for member in ['.', '..'] + self: yield fuse.Direntry(str(member)) + class Symlink(TreeEntry, str): """ A dummy class representing something that should be a symlink @@ -181,6 +191,7 @@ class Symlink(TreeEntry, str): def readlink(self): return self + class File(TreeEntry, str): """ A dummy class representing something that should be a file @@ -197,6 +208,7 @@ class File(TreeEntry, str): def read(self, length, offset): return self[offset:offset + length] + def main(cls): """ A convenience function for initializing a RouteFS filesystem @@ -207,6 +219,7 @@ def main(cls): server.parse(values=server, errex=1) server.main() + from dictfs import DictFS __all__ = ['RouteFS', 'DictFS', 'Symlink', 'Directory', 'File', 'main'] diff --git a/routefs/dictfs.py b/routefs/dictfs.py index 77baf63..25904b1 100644 --- a/routefs/dictfs.py +++ b/routefs/dictfs.py @@ -10,40 +10,44 @@ A dictionary represents a directory, with keys corresponding to file names and the values corresponding to the file contents. """ -import routefs -from routes import Mapper + import os +from routes import Mapper + +import routefs + + class DictFS(routefs.RouteFS): controllers = ['handler'] - + @property def files(self): """ This property should be overridden in your DictFS descendant """ return dict() - + def make_map(self): m = Mapper() - + m.connect('*path', controller='handler') - + return m - + def handler(self, path, **kwargs): if path != '': elements = path.split(os.path.sep) else: elements = [] - + try: tree = self.files for elt in elements: tree = tree[elt] except KeyError: return - + if type(tree) is dict: return tree.keys() else: diff --git a/routefs/examples/dictexfs.py b/routefs/examples/dictexfs.py index 5533f04..5402e7d 100755 --- a/routefs/examples/dictexfs.py +++ b/routefs/examples/dictexfs.py @@ -1,10 +1,13 @@ #!/usr/bin/python + import routefs + class DictExFS(routefs.DictFS): files = dict(Hello='World', Directory=dict(a='a', b='b', c=routefs.Symlink('a'))) + if __name__ == '__main__': routefs.main(DictExFS) diff --git a/routefs/examples/homefs.py b/routefs/examples/homefs.py index 1666fdd..a832c39 100755 --- a/routefs/examples/homefs.py +++ b/routefs/examples/homefs.py @@ -8,22 +8,26 @@ will automatically create symlinks from user -> their homedir whenever /home/user is accessed in any way. """ + import pwd -import routefs + from routes import Mapper +import routefs + + class HomeFS(routefs.RouteFS): controllers = ['getList', 'getUser'] def __init__(self, *args, **kwargs): super(HomeFS, self).__init__(*args, **kwargs) self.cache = {} - + def make_map(self): m = Mapper() m.connect('', controller='getList') m.connect(':action', controller='getUser') return m - + def getUser(self, action, **kwargs): try: if action not in self.cache: @@ -31,9 +35,10 @@ class HomeFS(routefs.RouteFS): return routefs.Symlink(self.cache[action]) except KeyError: return - + def getList(self, **kwargs): return self.cache.keys() + if __name__ == '__main__': routefs.main(HomeFS) diff --git a/routefs/examples/pyhesiodfs.py b/routefs/examples/pyhesiodfs.py index 880dbb4..2a9bfb0 100755 --- a/routefs/examples/pyhesiodfs.py +++ b/routefs/examples/pyhesiodfs.py @@ -1,28 +1,31 @@ #!/usr/bin/python + import hesiod -import routefs from routes import Mapper +import routefs + + class PyHesiodFS(routefs.RouteFS): controllers = ['getList', 'getReadme', 'getLocker'] def __init__(self, *args, **kwargs): super(PyHesiodFS, self).__init__(*args, **kwargs) self.fuse_args.add("allow_other", True) - + self.cache = {} - + def make_map(self): m = Mapper() m.connect('', controller='getList') m.connect('README.txt', controller='getReadme') m.connect(':action', controller='getLocker') return m - + def getLocker(self, action, **kwargs): if action in self.cache: return routefs.Symlink(self.cache[action]) - + try: filsys = hesiod.FilsysLookup(action).filsys[0] if filsys['type'] == 'AFS': @@ -30,10 +33,10 @@ class PyHesiodFS(routefs.RouteFS): return routefs.Symlink(self.cache[action]) except (TypeError, KeyError, IndexError): return - + def getList(self, **kwargs): return self.cache.keys() + ['README.txt'] - + def getReadme(self, **kwargs): return """ This is the pyHesiodFS FUSE automounter. To access a Hesiod filsys, @@ -43,5 +46,6 @@ If you're using the Finder, try pressing Cmd+Shift+G and then entering /mit/name """ + if __name__ == '__main__': routefs.main(PyHesiodFS) -- 1.7.9.5