Package amplee :: Package atompub :: Module store
[hide private]
[frames] | no frames]

Source Code for Module amplee.atompub.store

  1  # -*- coding: utf-8 -*- 
  2   
  3  __doc__ = """ 
  4  A store is a conceptual representation of your APP instance. 
  5  It is the outter envelop of the underlying entities involved. 
  6  APP does not define the concept of store per se but it is 
  7  a common way of naming and representing an APP instance. 
  8   
  9  A store is not really concerned about the meaning of members and 
 10  media resources however. All it cares about is 'meta-data' and 'content'. 
 11   
 12  A store needs at least one meta-data storage which will be used 
 13  to persist the representation of APP members. 
 14   
 15  A store can accept a second store which will be used to persist 
 16  media resources. If not provided the meta-data storage is then used. 
 17  """ 
 18   
19 -class AtomPubStore(object):
20 - def __init__(self, storage, media_storage=None, 21 autocommit=False, enable_lock=False):
22 """ 23 Store acting has a container of APP entities. 24 25 Operations on the store are only commited to the storage 26 automatically when the 'autocommit' parameter is True. This is 27 however not advised for performance issue. 28 29 30 In any case operations put each resource in distinct internal 31 lists which are processed when commit() is called. 32 33 Keyword arguments: 34 storage -- amplee.storage.* instance to persist member resources 35 media_storage -- amplee.storage.* instance to persist media resources 36 If not provided 'storage' will be used. (default=None) 37 autocommit -- True if the store should automatically call the 38 persist method of the storage (default=False) 39 enable_lock -- True if a thread lock should be used when performing 40 operations against the store (default=False) 41 """ 42 self.storage = storage 43 if not media_storage: 44 media_storage = self.storage 45 self.media_storage = media_storage 46 self.dirty = False 47 self.autocommit = autocommit 48 self.locking_enabled = enable_lock 49 if enable_lock: 50 import threading 51 self.lock = threading.RLock() 52 53 # Non public attributes. 54 self._pending_meta_data_to_add = {} 55 self._pending_resource_to_add = {} 56 self._pending_meta_data_to_remove = [] 57 self._pending_resource_to_remove = []
58
59 - def commit(self, message=None):
60 """ 61 Persist modification to the store into the storages 62 63 Keyword arguments: 64 message -- if the storage accept a string message, 65 like the subversion one (default=None) 66 """ 67 try: 68 if self.locking_enabled: 69 self.lock.acquire() 70 71 for path in self._pending_meta_data_to_remove: 72 self.storage.remove_meta_data(path) 73 74 for path in self._pending_resource_to_remove: 75 self.media_storage.remove_content(path) 76 77 paths = [] 78 media_paths = [] 79 80 for path, infos in self._pending_meta_data_to_add.items(): 81 obj = infos['obj'] 82 if hasattr(obj, 'read'): 83 content = obj.read() 84 else: 85 content = obj 86 del infos['obj'] 87 self.storage.put_meta_data(path, content, **infos) 88 paths.extend(self._pending_meta_data_to_remove) 89 paths.extend(self._pending_meta_data_to_add.keys()) 90 91 for path, infos in self._pending_resource_to_add.items(): 92 obj = infos['obj'] 93 if hasattr(obj, 'read'): 94 content = obj.read() 95 else: 96 content = obj 97 del infos['obj'] 98 self.media_storage.put_content(path, content, **infos) 99 media_paths.extend(self._pending_resource_to_remove) 100 media_paths.extend(self._pending_resource_to_add.keys()) 101 102 if paths: 103 self.storage.persist(paths, msg=message) 104 if media_paths: 105 self.media_storage.persist(media_paths, msg=message) 106 107 self._pending_meta_data_to_remove = [] 108 self._pending_resource_to_remove = [] 109 self._pending_meta_data_to_add.clear() 110 self._pending_resource_to_add.clear() 111 finally: 112 if self.locking_enabled: 113 self.lock.release()
114
115 - def get_meta_data_path(self, *args):
116 """ 117 Returns the path of resource used by the meta-data storage. 118 The returned value should only be seen as read-only. 119 120 Arguments depend on the underlying storage. 121 """ 122 return self.storage.path(*args)
123
124 - def get_content_path(self, *args):
125 """ 126 Returns the path of resource used by the content storage. 127 The returned value should only be seen as read-only. 128 129 Arguments depend on the underlying storage. 130 """ 131 return self.media_storage.path(*args)
132
133 - def add_content(self, path, obj, **kwargs):
134 """ 135 Add contents to the content storage. 136 If self.autocommit is True, the content is immediatly persisted. 137 138 Keyword arguments: 139 path -- value returned by get_content_path() 140 obj -- whatever Python object that should be persisted 141 **kwargs -- any additional parameters to provide to the storage 142 """ 143 try: 144 if self.locking_enabled: 145 self.lock.acquire() 146 infos = {'obj': obj} 147 if kwargs: 148 infos.update(kwargs) 149 self._pending_resource_to_add[path] = infos 150 if self.autocommit: 151 self.commit() 152 finally: 153 if self.locking_enabled: 154 self.lock.release()
155
156 - def add_meta_data(self, path, obj, **kwargs):
157 """ 158 Add meta-data to the meta-data storage. 159 If self.autocommit is True, the meta-date object is immediatly persisted. 160 161 Keyword arguments: 162 path -- value returned by get_meta_data_path() 163 obj -- whatever Python object that should be persisted 164 **kwargs -- any additional parameters to provide to the storage 165 """ 166 try: 167 if self.locking_enabled: 168 self.lock.acquire() 169 infos = {'obj': obj} 170 if kwargs: 171 infos.update(kwargs) 172 self._pending_meta_data_to_add[path] = infos 173 if self.autocommit: 174 self.commit() 175 finally: 176 if self.locking_enabled: 177 self.lock.release()
178
179 - def remove_meta_data(self, path):
180 """ 181 Remove the resource at 'path' from the meta-data storage. 182 If self.autocommit is True, the meta-date object is immediatly persisted. 183 184 Keyword arguments: 185 path -- value returned by get_meta_data_path() 186 """ 187 try: 188 if self.locking_enabled: 189 self.lock.acquire() 190 if path in self._pending_meta_data_to_add: 191 del self._pending_meta_data_to_add[path] 192 self._pending_meta_data_to_remove.append(path) 193 if self.autocommit: 194 self.commit() 195 finally: 196 if self.locking_enabled: 197 self.lock.release()
198
199 - def remove_content(self, path):
200 """ 201 Remove the resource at 'path' from the content storage. 202 If self.autocommit is True, the meta-date object is immediatly persisted. 203 204 Keyword arguments: 205 path -- value returned by get_meta_data_path() 206 """ 207 try: 208 if self.locking_enabled: 209 self.lock.acquire() 210 if path in self._pending_resource_to_add: 211 del self._pending_resource_to_add[path] 212 self._pending_resource_to_remove.append(path) 213 if self.autocommit: 214 self.commit() 215 finally: 216 if self.locking_enabled: 217 self.lock.release()
218
219 - def exists(self, path):
220 """ 221 Returns True if the resource 'path' does exist. 222 223 Keyword arguments: 224 path -- value returned by get_meta_data_path() or get_content_path() 225 """ 226 return self.storage.exists(path)
227
228 - def fetch_content(self, path):
229 """ 230 Returns the content object at 'path'. 231 232 Keyword arguments: 233 path -- value returned by get_content_path() 234 """ 235 return self.media_storage.get_content(path)
236
237 - def fetch_meta_data(self, path):
238 """ 239 Returns the meta-data object at 'path'. 240 241 Keyword arguments: 242 path -- value returned by get_meta_data_path() 243 """ 244 return self.storage.get_meta_data(path)
245
246 - def list_members(self, path, ext=None):
247 """ 248 Returns a dictionary of the form {resource-name: {'path': resource-path}} filtered 249 by the given parameters. 250 251 Keyword arguments: 252 path -- Base path where to perform the lookup 253 ext -- filter by extension of the resource (default=None) 254 """ 255 return self.storage.ls(path, ext=ext)
256