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  <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   
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 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
94 - def set_cache(self, path, data):
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
105 - def get_cache(self, path):
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 # Cache obsoleted 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 # Update access timestamp 125 if data: 126 self._cache_data[path] = now 127 128 return data
129 130 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 131
132 - def clear_cache(self, path):
133 """ 134 Clear cache for given path 135 """ 136 137 try: 138 del(self._cache[path]) 139 except KeyError: 140 pass
141 142 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 143
144 - def _parse_path(self, path):
145 files = [] 146 147 driver = None 148 149 for entry in re.split(self.vfsre, path): 150 if not entry: 151 entry = os.sep 152 153 vfs = self.vfsre2.search(entry) 154 155 if driver is not None: 156 files.append((entry, driver)) 157 driver = None 158 elif vfs: 159 driver = vfs.group(1) 160 else: 161 files.append((entry, None)) 162 163 return files
164 165 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 166
167 - def get_parent(self, path, enc):
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
176 - def get_full_path(self, path, vfs, parent):
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
195 - def get_ext_path(self, parent, vfs):
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