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 [<prefix>]:<path_to_archive>#vfs#<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 dervied 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 kw = {}
73
74 for p, vfs in data:
75 if vfs not in self._handlers:
76 raise VFSError(
77 _(u"Unable to find VFS handler for %s.") % vfs)
78 else:
79 full_path = self.get_full_path(p, vfs, handler)
80 ext_path = self.get_ext_path(handler, vfs)
81 kwtmp = self.get_cache(p)
82 kw.update(kwtmp)
83 kw.update(kwargs)
84
85 handler = self._handlers[vfs](
86 self.xyz,
87 os.path.abspath(os.path.normpath(p)),
88 full_path,
89 ext_path,
90 vfs,
91 handler,
92 enc,
93 **kw)
94
95 return handler
96
97
98
100 """
101 Save some data for VFS object
102 This data dict is appended to VFSObject's kwargs dict
103 every time dispatch() is called
104 """
105
106 self._cache[path] = data
107
108
109
111 """
112 Return saved cache for the object or {} if none was saved
113 """
114
115 atime = self._cache_data.get(path, None)
116 now = int(time.time())
117
118
119 if atime is not None and \
120 now - atime >= self.xyz.conf["vfs"]["cache_time"]:
121
122 self.clear_cache(path)
123 del(self._cache_data[path])
124
125 data = {}
126 else:
127 data = self._cache.get(path, {}).copy()
128
129
130 if data:
131 self._cache_data[path] = now
132
133 return data
134
135
136
138 """
139 Clear cache for given path
140 """
141
142 try:
143 del(self._cache[path])
144 except KeyError:
145 pass
146
147
148
169
170
171
173 _parent = self.xyz.vfs.dispatch(
174 os.path.abspath(os.path.dirname(path)), enc)
175 _parent.name = ".."
176
177 return _parent
178
179
180
182 """
183 Return full path
184 """
185
186 if parent:
187 p = parent.full_path
188 else:
189 p = ""
190
191 if vfs:
192 v = "#vfs-%s#" % vfs
193 else:
194 v = ""
195
196 return p + v + path
197
198
199
201 """
202 Return external path
203 """
204
205 if parent:
206 p = parent.full_path
207 else:
208 p = ""
209
210 if vfs:
211 v = "#vfs-%s#" % vfs
212 else:
213 v = ""
214
215 return p + v
216