Package libxyz :: Package vfs :: Module dispatcher
[hide private]
[frames] | no frames]

Source Code for Module libxyz.vfs.dispatcher

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <mek@mek.uz.ua> 2008-2009 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 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   
30 -class VFSDispatcher(object):
31 - def __init__(self, xyz):
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
99 - def set_cache(self, path, data):
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
110 - def get_cache(self, path):
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 # Cache obsoleted 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 # Update access timestamp 130 if data: 131 self._cache_data[path] = now 132 133 return data
134 135 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 136
137 - def clear_cache(self, path):
138 """ 139 Clear cache for given path 140 """ 141 142 try: 143 del(self._cache[path]) 144 except KeyError: 145 pass
146 147 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 148
149 - def _parse_path(self, path):
150 files = [] 151 152 driver = None 153 154 for entry in re.split(self.vfsre, path): 155 if not entry: 156 entry = os.sep 157 158 vfs = self.vfsre2.search(entry) 159 160 if driver is not None: 161 files.append((entry, driver)) 162 driver = None 163 elif vfs: 164 driver = vfs.group(1) 165 else: 166 files.append((entry, None)) 167 168 return files
169 170 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 171
172 - def get_parent(self, path, enc):
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
181 - def get_full_path(self, path, vfs, parent):
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
200 - def get_ext_path(self, parent, vfs):
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