2 RouteFS is a base class for developing read-only FUSE filesystems that
3 lets you focus on the directory tree instead of the system calls.
5 RouteFS uses the Routes library developed for Pylons. URLs were
6 inspired by filesystems, and now you can have filesystems inspired by
9 When developing a descendent of RouteFS, any methods defined in that
10 class are considered "controllers", and receive any other parameters
11 specified by the URL as keyword arguments.
18 from dictfs import DictFS
20 fuse.fuse_python_api = (0, 2)
22 class RouteStat(fuse.Stat):
24 RouteStat is a descendent of fuse.Stat, defined to make sure that
25 all of the necessary attributes are always defined
39 class RouteMeta(type):
41 Metaclass to calculate controller methods
43 Routes needs to be pre-seeded with a list of "controllers". For
44 all descendents of RouteFS, the list of controllers is defined to
45 be any non-private methods of the class that were not in the
48 def __init__(cls, classname, bases, dict_):
49 super(RouteMeta, cls).__init__(classname, bases, dict_)
50 if bases != (fuse.Fuse,):
51 new_funcs = set(dict_.keys()).difference(dir(RouteFS))
52 cls.controllers([func for func in new_funcs \
53 if not func.startswith('_')])
55 class RouteFS(fuse.Fuse):
57 RouteFS: Web 2.0 for filesystems
59 __metaclass__ = RouteMeta
60 def __init__(self, *args, **kwargs):
61 super(RouteFS, self).__init__(*args, **kwargs)
63 self.map = self.make_map()
64 self.map.create_regs(self.controller_list)
68 This method should be overridden by descendents of RouteFS to
69 define the routing for the filesystem
73 m.connect(':controller')
78 def controllers(cls, lst):
79 cls.controller_list = lst
81 def _get_file(self, path):
83 Find the filesystem entry object for a given path
85 match = self.map.match(path)
88 controller = match.pop('controller')
89 result = getattr(self, controller)(**match)
92 def readdir(self, path, offset):
94 If the path referred to is a directory, return the elements of
97 obj = self._get_file(path)
98 if type(obj) is not Directory:
101 for member in ['.', '..'] + obj:
102 yield fuse.Direntry(str(member))
104 def getattr(self, path):
106 Return the stat information for a path
108 The stat information for a directory, symlink, or file is
109 predetermined based on which it is.
111 obj = self._get_file(path)
116 if type(obj) is Directory:
117 st.st_mode = stat.S_IFDIR | 0755
119 elif type(obj) is Symlink:
120 st.st_mode = stat.S_IFLNK | 0777
122 st.st_size = len(obj)
124 st.st_mode = stat.S_IFREG | 0444
126 st.st_size = len(obj)
130 def read(self, path, length, offset):
132 If the path specified is a file, return the requested portion
135 obj = self._get_file(path)
138 elif type(obj) in (Directory, Symlink):
141 return obj[offset:offset + length]
143 def readlink(self, path):
145 If the path specified is a symlink, return the target
147 obj = self._get_file(path)
148 if type(obj) is not Symlink:
153 class Directory(list):
155 A dummy class representing a filesystem entry that should be a
162 A dummy class representing something that should be a symlink
168 A convenience function for initializing a RouteFS filesystem
170 server = cls(version="%prog " + fuse.__version__,
171 usage=fuse.Fuse.fusage,
172 dash_s_do='setsingle')
173 server.parse(errex=1)
176 __all__ = ['RouteFS', 'DictFS', 'Symlink', 'Directory', 'main']