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

Source Code for Module amplee.atompub.store

  1  # -*- coding: utf-8 -*- 
  2  __docformat__ = 'epytext en' 
  3   
  4  __doc__ = """ 
  5  Representation of a store. 
  6   
  7  A store is a conceptual representation of your APP instance. 
  8  It is the outter envelop of the underlying entities involved. 
  9  APP does not define the concept of store per se but it is 
 10  a common way of naming and representing an APP instance. 
 11   
 12  A store is not really concerned about the meaning of members and 
 13  media resources however. All it cares about is 'meta-data' and 'content'. 
 14   
 15  A store needs at least one meta-data storage which will be used 
 16  to persist the representation of APP members. 
 17   
 18  A store can accept a second store which will be used to persist 
 19  media resources. If not provided the meta-data storage is then used. 
 20   
 21  @undocumented: __doc__  
 22  """ 
 23   
 24  __all__ = ['AtomPubStore'] 
 25   
26 -class AtomPubStore(object):
27 - def __init__(self, storage, media_storage=None, 28 enable_lock=True):
29 """Store acting has a container of AtomPub entities. 30 31 Operations on the store are only commited to the storage 32 automatically when the C{autocommit} parameter is C{True}. This is 33 however not advised for performance issue. 34 35 In any case operations put each resource in distinct internal 36 lists which are processed when L{commit()} is called. 37 38 @type storage: L{Storage} 39 @param storage: instance to persist member resources. 40 41 @type media_storage: L{Storage} 42 @param media_storage: instance to persist media resources. 43 If not provided C{storage} will be used. 44 45 @type enable_lock: bool 46 @param enable_lock: when C{True}, a thread lock will be used when performing 47 operations against the store. This is enabled by default. 48 """ 49 self.storage = storage 50 if not media_storage: 51 media_storage = self.storage 52 self.media_storage = media_storage 53 self.locking_enabled = enable_lock 54 if enable_lock: 55 import threading 56 self.lock = threading.Lock() 57 58 # Non public attributes. 59 self._pending_meta_data_to_add = {} 60 self._pending_resource_to_add = {} 61 self._pending_meta_data_to_remove = [] 62 self._pending_resource_to_remove = []
63
64 - def commit(self, message=None):
65 """ 66 Persists modification to the store into the storages. 67 68 @type message: string 69 @param message: if the storage accepts it (like subversion), 70 message to pass to the storage. 71 """ 72 try: 73 if self.locking_enabled: 74 self.lock.acquire() 75 76 for info in self._pending_meta_data_to_remove: 77 self.storage.remove_meta_data(info) 78 79 for info in self._pending_resource_to_remove: 80 self.media_storage.remove_content(info) 81 82 member_infos = [] 83 media_infos = [] 84 85 for info, infos in self._pending_meta_data_to_add.items(): 86 content = infos.get('__obj__', None) 87 if content: 88 del infos['__obj__'] 89 self.storage.put_meta_data(info, content, **infos) 90 91 member_infos.extend(self._pending_meta_data_to_remove) 92 member_infos.extend(self._pending_meta_data_to_add.keys()) 93 94 for info, infos in self._pending_resource_to_add.items(): 95 content = infos.get('__obj__', None) 96 if content: 97 del infos['__obj__'] 98 self.media_storage.put_content(info, content, **infos) 99 100 media_infos.extend(self._pending_resource_to_remove) 101 media_infos.extend(self._pending_resource_to_add.keys()) 102 103 if member_infos: 104 self.storage.persist(member_infos, msg=message) 105 if media_infos: 106 self.media_storage.persist(media_infos, msg=message) 107 108 self._pending_meta_data_to_remove = [] 109 self._pending_resource_to_remove = [] 110 self._pending_meta_data_to_add.clear() 111 self._pending_resource_to_add.clear() 112 finally: 113 if self.locking_enabled: 114 self.lock.release()
115
116 - def get_meta_data_info(self, *args):
117 """ 118 Returns the info of resource used by the meta-data storage. 119 The returned value should only be seen as read-only. 120 121 Arguments depend on the underlying storage. 122 """ 123 return self.storage.info(*args)
124
125 - def get_content_info(self, *args):
126 """ 127 Returns the info of resource used by the content storage. 128 The returned value should only be seen as read-only. 129 130 Arguments depend on the underlying storage. 131 """ 132 return self.media_storage.info(*args)
133
134 - def add_content(self, info, obj, **kwargs):
135 """ 136 Adds content to the content storage. 137 If C{self.autocommit} is C{True} the content is immediatly persisted. 138 139 @type info: L{StorageResourceInfo} or subclass 140 @param info: value returned vy L{get_content_info()} 141 142 @type obj: object 143 @param obj: whatever Python object that should be persisted 144 145 @type **kwargs: dict 146 @param **kwargs: any additional parameters to provide to the storage 147 """ 148 try: 149 if self.locking_enabled: 150 self.lock.acquire() 151 infos = {'__obj__': obj} 152 if kwargs: 153 infos.update(kwargs) 154 self._pending_resource_to_add[info] = infos 155 finally: 156 if self.locking_enabled: 157 self.lock.release()
158
159 - def add_meta_data(self, info, obj, **kwargs):
160 """ 161 Adds meta-data to the meta-data storage. 162 If C{self.autocommit} is C{True} the content is immediatly persisted. 163 164 @type info: L{StorageResourceInfo} or subclass 165 @param info: value returned by L{get_meta_data_info()} 166 167 @type obj: object 168 @param obj: whatever Python object that should be persisted 169 170 @type **kwargs: dict 171 @param **kwargs: any additional parameters to provide to the storage 172 """ 173 try: 174 if self.locking_enabled: 175 self.lock.acquire() 176 infos = {'__obj__': obj} 177 if kwargs: 178 infos.update(kwargs) 179 self._pending_meta_data_to_add[info] = infos 180 finally: 181 if self.locking_enabled: 182 self.lock.release()
183
184 - def remove_meta_data(self, info):
185 """ 186 Removes the resource at C{info} from the meta-data storage. 187 If C{self.autocommit} is C{True} the meta-data object is immediatly persisted. 188 189 @type info: L{StorageResourceInfo} or subclass 190 @param info: value returned by L{get_meta_data_info()} 191 """ 192 try: 193 if self.locking_enabled: 194 self.lock.acquire() 195 if info in self._pending_meta_data_to_add: 196 del self._pending_meta_data_to_add[info] 197 self._pending_meta_data_to_remove.append(info) 198 finally: 199 if self.locking_enabled: 200 self.lock.release()
201
202 - def remove_content(self, info):
203 """ 204 Removes the resource at C{info} from the content storage. 205 If C{self.autocommit} is C{True} the content object is immediatly persisted. 206 207 @type info: L{StorageResourceInfo} or subclass 208 @param info: value returned by L{get_meta_data_info()} 209 """ 210 try: 211 if self.locking_enabled: 212 self.lock.acquire() 213 if info in self._pending_resource_to_add: 214 del self._pending_resource_to_add[info] 215 self._pending_resource_to_remove.append(info) 216 finally: 217 if self.locking_enabled: 218 self.lock.release()
219
220 - def exists(self, info, as_media=False):
221 """ 222 Returns C{True} if the resource C{info} does exist. 223 224 @type info: L{StorageResourceInfo} or subclass 225 @param info: value returned by L{get_meta_data_info()} 226 or L{get_content_info()} 227 228 @type as_media: bool 229 @param as_media: if C{False} the method checks in the member storage 230 otherwise it checks in the media storage. When both are the same it does 231 not matter but if both are different you should set this value 232 accordingly. 233 234 @rtype: bool 235 @return: C{True} if the resource exists in the storage queried 236 """ 237 if as_media: 238 return self.media_storage.exists(info) 239 return self.storage.exists(info)
240
241 - def fetch_content(self, info):
242 """ 243 Returns the content object at C{info}. 244 245 @type info: L{StorageResourceInfo} or subclass 246 @param info: value returned by L{get_content_info()} 247 248 @rtype: object 249 @return: the object as returned by the underlying storage 250 and representing the content. 251 """ 252 return self.media_storage.get_content(info)
253
254 - def fetch_meta_data(self, info):
255 """ 256 Returns the meta-data object at C{info}. 257 258 @type info: L{StorageResourceInfo} or subclass 259 @param info: value returned by L{get_meta_data_info()} 260 261 @rtype: object 262 @return: the object as returned by the underlying storage 263 and representing the content. 264 """ 265 return self.storage.get_meta_data(info)
266
267 - def list_members(self, info, ext=None):
268 """ 269 Returns a dictionary of the form C{{resource-name: StorageResourceInfo}} 270 filtered by the given parameters. 271 272 @type info: string 273 @param info: name of the collection to browse through 274 275 @type ext: string or C{NoneType} 276 @param ext: allows to filter by extension of the resource 277 278 @rtype: dict 279 @return: the resources matching the filter and the info 280 """ 281 return self.storage.ls(info, ext=ext)
282
283 - def iter_members(self, info, ext=None):
284 """ 285 Yield a tuple of the form C{(resource-name, StorageResourceInfo)} 286 filtered by the given parameters. 287 288 @type info: string 289 @param info: name of the collection to browse through 290 291 @type ext: string or C{NoneType} 292 @param ext: allows to filter by extension of the resource 293 294 @rtype: tuple 295 @return: the resources matching the filter and the info 296 """ 297 for item in self.storage.ils(info, ext=ext): 298 yield item 299 300 raise StopIteration()
301