1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 VFSDispatcher - Dispatching to appropriate VFS module based on path.
19 Path format is following:
20 <path_to_archive>#vfs-<driver>#<path_inside_archive>
21 """
22
23 import os
24 import re
25 import time
26
27 from libxyz.vfs import VFSObject
28 from libxyz.exceptions import VFSError
29
32 self.xyz = xyz
33 self._handlers = {}
34 self._cache = {}
35 self._cache_data = {}
36
37 self.vfsre = re.compile(r'(#vfs-\w+#)')
38 self.vfsre2 = re.compile(r'^#vfs-(\w+)#$')
39
40
41
42 - def register(self, prefix, vfs_obj_class):
43 """
44 Register new VFS handler
45
46 @param prefix: Patch prefix
47 @param vfs_obj_class: VFSObject derived class
48 """
49
50 if not issubclass(vfs_obj_class, VFSObject):
51 raise VFSError(
52 _(u"Invalid class: %s. VFSObject derived expected.") %
53 str(vfs_obj_class))
54
55 self._handlers[prefix] = vfs_obj_class
56
57
58
59 - def dispatch(self, path, enc=None, **kwargs):
60 """
61 Dispatch provided path to corresponding VFS object handler
62 """
63
64 enc = enc or xyzenc
65 data = self._parse_path(path)
66
67 if not data:
68 raise VFSError(_(u"Invalid path: %s.") % path)
69
70 handler = None
71
72 for p, vfs in data:
73 if vfs not in self._handlers:
74 raise VFSError(
75 _(u"Unable to find VFS handler for %s.") % vfs)
76 else:
77 full_path = self.get_full_path(p, vfs, handler)
78 ext_path = self.get_ext_path(handler, vfs)
79
80 handler = self._handlers[vfs](
81 self.xyz,
82 os.path.abspath(os.path.normpath(p)),
83 full_path,
84 ext_path,
85 vfs,
86 handler,
87 enc,
88 **kwargs)
89
90 return handler
91
92
93
95 """
96 Save some data for VFS object
97 This data dict is appended to VFSObject's kwargs dict
98 every time dispatch() is called
99 """
100
101 self._cache[path] = data
102
103
104
106 """
107 Return saved cache for the object or {} if none was saved
108 """
109
110 atime = self._cache_data.get(path, None)
111 now = int(time.time())
112
113
114 if atime is not None and \
115 now - atime >= self.xyz.conf["vfs"]["cache_time"]:
116
117 self.clear_cache(path)
118 del(self._cache_data[path])
119
120 data = None
121 else:
122 data = self._cache.get(path, None)
123
124
125 if data:
126 self._cache_data[path] = now
127
128 return data
129
130
131
133 """
134 Clear cache for given path
135 """
136
137 try:
138 del(self._cache[path])
139 except KeyError:
140 pass
141
142
143
164
165
166
168 _parent = self.xyz.vfs.dispatch(
169 os.path.abspath(os.path.dirname(path)), enc)
170 _parent.name = ".."
171
172 return _parent
173
174
175
177 """
178 Return full path
179 """
180
181 if parent:
182 p = parent.full_path
183 else:
184 p = ""
185
186 if vfs:
187 v = "#vfs-%s#" % vfs
188 else:
189 v = ""
190
191 return p + v + path
192
193
194
196 """
197 Return external path
198 """
199
200 if parent:
201 p = parent.full_path
202 else:
203 p = ""
204
205 if vfs:
206 v = "#vfs-%s#" % vfs
207 else:
208 v = ""
209
210 return p + v
211