Mercurial > libervia-backend
comparison src/memory/memory.py @ 592:e5a875a3311b
Fix pep8 support in src/memory.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 18 Jan 2013 17:55:35 +0100 |
parents | beaf6bec2fcd |
children | 84a6e83157c2 |
comparison
equal
deleted
inserted
replaced
591:65821b3fa7ab | 592:e5a875a3311b |
---|---|
31 from sat.core.default_config import default_config | 31 from sat.core.default_config import default_config |
32 from sat.memory.sqlite import SqliteStorage | 32 from sat.memory.sqlite import SqliteStorage |
33 from sat.memory.persistent import PersistentDict | 33 from sat.memory.persistent import PersistentDict |
34 from sat.core import exceptions | 34 from sat.core import exceptions |
35 | 35 |
36 SAVEFILE_PARAM_XML="/param" #xml parameters template | 36 SAVEFILE_PARAM_XML = "/param" # xml parameters template |
37 SAVEFILE_DATABASE="/sat.db" | 37 SAVEFILE_DATABASE = "/sat.db" |
38 | 38 |
39 | 39 |
40 class Params(object): | 40 class Params(object): |
41 """This class manage parameters with xml""" | 41 """This class manage parameters with xml""" |
42 ### TODO: add desciption in params | 42 ### TODO: add desciption in params |
59 <category name="Misc" label="%(category_misc)s"> | 59 <category name="Misc" label="%(category_misc)s"> |
60 <param name="Watched" value="test@Jabber.goffi.int" type="string" /> | 60 <param name="Watched" value="test@Jabber.goffi.int" type="string" /> |
61 </category> | 61 </category> |
62 </individual> | 62 </individual> |
63 </params> | 63 </params> |
64 """ % {'category_connection': _("Connection"), | 64 """ % { |
65 'label_NewAccount': _("Register new account"), | 65 'category_connection': _("Connection"), |
66 'label_autoconnect': _('Connect on frontend startup'), | 66 'label_NewAccount': _("Register new account"), |
67 'label_autodisconnect': _('Disconnect on frontend closure'), | 67 'label_autoconnect': _('Connect on frontend startup'), |
68 'category_misc': _("Misc") | 68 'label_autodisconnect': _('Disconnect on frontend closure'), |
69 } | 69 'category_misc': _("Misc") |
70 } | |
70 | 71 |
71 def load_default_params(self): | 72 def load_default_params(self): |
72 self.dom = minidom.parseString(Params.default_xml.encode('utf-8')) | 73 self.dom = minidom.parseString(Params.default_xml.encode('utf-8')) |
73 | 74 |
74 def _mergeParams(self, source_node, dest_node): | 75 def _mergeParams(self, source_node, dest_node): |
75 """Look for every node in source_node and recursively copy them to dest if they don't exists""" | 76 """Look for every node in source_node and recursively copy them to dest if they don't exists""" |
77 | |
76 def getNodesMap(children): | 78 def getNodesMap(children): |
77 ret = {} | 79 ret = {} |
78 for child in children: | 80 for child in children: |
79 if child.nodeType == child.ELEMENT_NODE: | 81 if child.nodeType == child.ELEMENT_NODE: |
80 ret[(child.tagName, child.getAttribute('name'))] = child | 82 ret[(child.tagName, child.getAttribute('name'))] = child |
107 """Load individual parameters | 109 """Load individual parameters |
108 set self.params cache or a temporary cache | 110 set self.params cache or a temporary cache |
109 @param profile: profile to load (*must exist*) | 111 @param profile: profile to load (*must exist*) |
110 @param cache: if not None, will be used to store the value, as a short time cache | 112 @param cache: if not None, will be used to store the value, as a short time cache |
111 @return: deferred triggered once params are loaded""" | 113 @return: deferred triggered once params are loaded""" |
112 if cache == None: | 114 if cache is None: |
113 self.params[profile] = {} | 115 self.params[profile] = {} |
114 return self.storage.loadIndParams(self.params[profile] if cache==None else cache, profile) | 116 return self.storage.loadIndParams(self.params[profile] if cache is None else cache, profile) |
115 | 117 |
116 def purgeProfile(self, profile): | 118 def purgeProfile(self, profile): |
117 """Remove cache data of a profile | 119 """Remove cache data of a profile |
118 @param profile: %(doc_profile)s""" | 120 @param profile: %(doc_profile)s""" |
119 try: | 121 try: |
120 del self.params[profile] | 122 del self.params[profile] |
121 except KeyError: | 123 except KeyError: |
122 error(_("Trying to purge cache of a profile not in memory: [%s]") % profile) | 124 error(_("Trying to purge cache of a profile not in memory: [%s]") % profile) |
123 | 125 |
124 def save_xml(self, file): | 126 def save_xml(self, filename): |
125 """Save parameters template to xml file""" | 127 """Save parameters template to xml file""" |
126 with open(file, 'wb') as xml_file: | 128 with open(filename, 'wb') as xml_file: |
127 xml_file.write(self.dom.toxml('utf-8')) | 129 xml_file.write(self.dom.toxml('utf-8')) |
128 | 130 |
129 def __init__(self, host, storage): | 131 def __init__(self, host, storage): |
130 debug("Parameters init") | 132 debug("Parameters init") |
131 self.host = host | 133 self.host = host |
139 def createProfile(self, profile): | 141 def createProfile(self, profile): |
140 """Create a new profile | 142 """Create a new profile |
141 @param profile: profile of the profile""" | 143 @param profile: profile of the profile""" |
142 #FIXME: must be asynchronous and call the callback once the profile actually exists | 144 #FIXME: must be asynchronous and call the callback once the profile actually exists |
143 if self.storage.hasProfile(profile): | 145 if self.storage.hasProfile(profile): |
144 info (_('The profile [%s] already exists') % (profile,)) | 146 info(_('The profile [%s] already exists') % (profile, )) |
145 return True | 147 return True |
146 if not self.host.trigger.point("ProfileCreation", profile): | 148 if not self.host.trigger.point("ProfileCreation", profile): |
147 return False | 149 return False |
148 self.storage.createProfile(profile) | 150 self.storage.createProfile(profile) |
149 return False | 151 return False |
155 @param errback: called with a string constant as parameter: | 157 @param errback: called with a string constant as parameter: |
156 - CONFLICT: the profile already exists | 158 - CONFLICT: the profile already exists |
157 - CANCELED: profile creation canceled | 159 - CANCELED: profile creation canceled |
158 """ | 160 """ |
159 if self.storage.hasProfile(profile): | 161 if self.storage.hasProfile(profile): |
160 info (_('The profile name already exists')) | 162 info(_('The profile name already exists')) |
161 return defer.fail("CONFLICT") | 163 return defer.fail("CONFLICT") |
162 if not self.host.trigger.point("ProfileCreation", profile): | 164 if not self.host.trigger.point("ProfileCreation", profile): |
163 return defer.fail("CANCEL") | 165 return defer.fail("CANCEL") |
164 return self.storage.createProfile(profile) | 166 return self.storage.createProfile(profile) |
165 | |
166 | 167 |
167 def deleteProfile(self, profile): | 168 def deleteProfile(self, profile): |
168 """Delete an existing profile | 169 """Delete an existing profile |
169 @param profile: name of the profile""" | 170 @param profile: name of the profile""" |
170 #TODO: async equivalent, like for createProfile | 171 #TODO: async equivalent, like for createProfile |
181 """return profile according to profile_key | 182 """return profile according to profile_key |
182 @param profile_key: profile name or key which can be | 183 @param profile_key: profile name or key which can be |
183 @ALL@ for all profiles | 184 @ALL@ for all profiles |
184 @DEFAULT@ for default profile | 185 @DEFAULT@ for default profile |
185 @return: requested profile name or None if it doesn't exist""" | 186 @return: requested profile name or None if it doesn't exist""" |
186 if profile_key=='@DEFAULT@': | 187 if profile_key == '@DEFAULT@': |
187 default = self.host.memory.memory_data.get('Profile_default') | 188 default = self.host.memory.memory_data.get('Profile_default') |
188 if not default: | 189 if not default: |
189 info(_('No default profile, returning first one')) #TODO: manage real default profile | 190 info(_('No default profile, returning first one')) # TODO: manage real default profile |
190 default = self.host.memory.memory_data['Profile_default'] = self.storage.getProfilesList()[0] | 191 default = self.host.memory.memory_data['Profile_default'] = self.storage.getProfilesList()[0] |
191 return default #FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists | 192 return default # FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists |
192 if not self.storage.hasProfile(profile_key): | 193 if not self.storage.hasProfile(profile_key): |
193 info (_('Trying to access an unknown profile')) | 194 info(_('Trying to access an unknown profile')) |
194 return "" | 195 return "" |
195 return profile_key | 196 return profile_key |
196 | 197 |
197 def __get_unique_node(self, parent, tag, name): | 198 def __get_unique_node(self, parent, tag, name): |
198 """return node with given tag | 199 """return node with given tag |
216 def import_node(tgt_parent, src_parent): | 217 def import_node(tgt_parent, src_parent): |
217 for child in src_parent.childNodes: | 218 for child in src_parent.childNodes: |
218 if child.nodeName == '#text': | 219 if child.nodeName == '#text': |
219 continue | 220 continue |
220 node = self.__get_unique_node(tgt_parent, child.nodeName, child.getAttribute("name")) | 221 node = self.__get_unique_node(tgt_parent, child.nodeName, child.getAttribute("name")) |
221 if not node: #The node is new | 222 if not node: # The node is new |
222 tgt_parent.appendChild(child) | 223 tgt_parent.appendChild(child) |
223 else: | 224 else: |
224 import_node(node, child) | 225 import_node(node, child) |
225 | 226 |
226 import_node(self.dom.documentElement, src_dom.documentElement) | 227 import_node(self.dom.documentElement, src_dom.documentElement) |
227 | 228 |
228 def __default_ok(self, value, name, category): | 229 def __default_ok(self, value, name, category): |
229 #FIXME: gof: will not work with individual parameters | 230 #FIXME: gof: will not work with individual parameters |
230 self.setParam(name, value, category) #FIXME: better to set param xml value ??? | 231 self.setParam(name, value, category) # FIXME: better to set param xml value ??? |
231 | 232 |
232 def __default_ko(self, failure, name, category): | 233 def __default_ko(self, failure, name, category): |
233 error (_("Can't determine default value for [%(category)s/%(name)s]: %(reason)s") % {'category':category, 'name':name, 'reason':str(failure.value)}) | 234 error(_("Can't determine default value for [%(category)s/%(name)s]: %(reason)s") % {'category': category, 'name': name, 'reason': str(failure.value)}) |
234 | 235 |
235 def setDefault(self, name, category, callback, errback=None): | 236 def setDefault(self, name, category, callback, errback=None): |
236 """Set default value of parameter | 237 """Set default value of parameter |
237 'default_cb' attibute of parameter must be set to 'yes' | 238 'default_cb' attibute of parameter must be set to 'yes' |
238 @param name: name of the parameter | 239 @param name: name of the parameter |
239 @param category: category of the parameter | 240 @param category: category of the parameter |
240 @param callback: must return a string with the value (use deferred if needed) | 241 @param callback: must return a string with the value (use deferred if needed) |
241 @param errback: must manage the error with args failure, name, category | 242 @param errback: must manage the error with args failure, name, category |
242 """ | 243 """ |
243 #TODO: send signal param update if value changed | 244 #TODO: send signal param update if value changed |
244 node = self.__getParamNode(name, category, '@ALL@') | 245 node = self.__getParamNode(name, category, '@ALL@') |
245 if not node: | 246 if not node: |
246 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category}) | 247 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category}) |
247 return | 248 return |
248 if node[1].getAttribute('default_cb') == 'yes': | 249 if node[1].getAttribute('default_cb') == 'yes': |
249 del node[1].attributes['default_cb'] | 250 del node[1].attributes['default_cb'] |
250 d = defer.maybeDeferred(callback) | 251 d = defer.maybeDeferred(callback) |
251 d.addCallback(self.__default_ok, name, category) | 252 d.addCallback(self.__default_ok, name, category) |
255 """ get attribute value | 256 """ get attribute value |
256 @param node: XML param node | 257 @param node: XML param node |
257 @param attr: name of the attribute to get (e.g.: 'value' or 'type') | 258 @param attr: name of the attribute to get (e.g.: 'value' or 'type') |
258 @param value: user defined value""" | 259 @param value: user defined value""" |
259 if attr == 'value': | 260 if attr == 'value': |
260 value_to_use = value if value!=None else node.getAttribute(attr) #we use value (user defined) if it exist, else we use node's default value | 261 value_to_use = value if value is not None else node.getAttribute(attr) # we use value (user defined) if it exist, else we use node's default value |
261 if node.getAttribute('type') == 'bool': | 262 if node.getAttribute('type') == 'bool': |
262 return value_to_use.lower() not in ('false','0') | 263 return value_to_use.lower() not in ('false', '0') |
263 return value_to_use | 264 return value_to_use |
264 return node.getAttribute(attr) | 265 return node.getAttribute(attr) |
265 | 266 |
266 def __type_to_string(self, result): | 267 def __type_to_string(self, result): |
267 """ convert result to string, according to its type """ | 268 """ convert result to string, according to its type """ |
268 if isinstance(result,bool): | 269 if isinstance(result, bool): |
269 return "true" if result else "false" | 270 return "true" if result else "false" |
270 return result | 271 return result |
271 | 272 |
272 def getStringParamA(self, name, category, attr="value", profile_key="@DEFAULT@"): | 273 def getStringParamA(self, name, category, attr="value", profile_key="@DEFAULT@"): |
273 """ Same as getParamA but for bridge: convert non string value to string """ | 274 """ Same as getParamA but for bridge: convert non string value to string """ |
282 | 283 |
283 @return: attribute""" | 284 @return: attribute""" |
284 #FIXME: looks really dirty and buggy, need to be reviewed/refactored | 285 #FIXME: looks really dirty and buggy, need to be reviewed/refactored |
285 node = self.__getParamNode(name, category) | 286 node = self.__getParamNode(name, category) |
286 if not node: | 287 if not node: |
287 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category}) | 288 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category}) |
288 raise exceptions.NotFound | 289 raise exceptions.NotFound |
289 | 290 |
290 if node[0] == 'general': | 291 if node[0] == 'general': |
291 value = self.__getParam(None, category, name, 'general') | 292 value = self.__getParam(None, category, name, 'general') |
292 return self.__getAttr(node[1], attr, value) | 293 return self.__getAttr(node[1], attr, value) |
293 | 294 |
294 assert(node[0] == 'individual') | 295 assert node[0] == 'individual' |
295 | 296 |
296 profile = self.getProfileName(profile_key) | 297 profile = self.getProfileName(profile_key) |
297 if not profile: | 298 if not profile: |
298 error(_('Requesting a param for an non-existant profile')) | 299 error(_('Requesting a param for an non-existant profile')) |
299 raise exceptions.ProfileUnknownError | 300 raise exceptions.ProfileUnknownError |
317 @param category: category of the parameter | 318 @param category: category of the parameter |
318 @param attr: name of the attribute (default: "value") | 319 @param attr: name of the attribute (default: "value") |
319 @param profile: owner of the param (@ALL@ for everyone)""" | 320 @param profile: owner of the param (@ALL@ for everyone)""" |
320 node = self.__getParamNode(name, category) | 321 node = self.__getParamNode(name, category) |
321 if not node: | 322 if not node: |
322 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category}) | 323 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category}) |
323 return None | 324 return None |
324 | 325 |
325 if node[0] == 'general': | 326 if node[0] == 'general': |
326 value = self.__getParam(None, category, name, 'general') | 327 value = self.__getParam(None, category, name, 'general') |
327 return defer.succeed(self.__getAttr(node[1], attr, value)) | 328 return defer.succeed(self.__getAttr(node[1], attr, value)) |
328 | 329 |
329 assert(node[0] == 'individual') | 330 assert node[0] == 'individual' |
330 | 331 |
331 profile = self.getProfileName(profile_key) | 332 profile = self.getProfileName(profile_key) |
332 if not profile: | 333 if not profile: |
333 error(_('Requesting a param for a non-existant profile')) | 334 error(_('Requesting a param for a non-existant profile')) |
334 return defer.fail() | 335 return defer.fail() |
351 @param _type: "general" or "individual" | 352 @param _type: "general" or "individual" |
352 @param cache: temporary cache, to use when profile is not logged | 353 @param cache: temporary cache, to use when profile is not logged |
353 @return: param value or None if it doesn't exist | 354 @return: param value or None if it doesn't exist |
354 """ | 355 """ |
355 if _type == 'general': | 356 if _type == 'general': |
356 if self.params_gen.has_key((category, name)): | 357 if (category, name) in self.params_gen: |
357 return self.params_gen[(category, name)] | 358 return self.params_gen[(category, name)] |
358 return None #This general param has the default value | 359 return None # This general param has the default value |
359 assert (_type == 'individual') | 360 assert (_type == 'individual') |
360 if self.params.has_key(profile): | 361 if profile in self.params: |
361 cache = self.params[profile] # if profile is in main cache, we use it, | 362 cache = self.params[profile] # if profile is in main cache, we use it, |
362 # ignoring the temporary cache | 363 # ignoring the temporary cache |
363 elif cache == None: #else we use the temporary cache if it exists, or raise an exception | 364 elif cache is None: # else we use the temporary cache if it exists, or raise an exception |
364 raise exceptions.ProfileNotInCacheError | 365 raise exceptions.ProfileNotInCacheError |
365 if not cache.has_key((category, name)): | 366 if (category, name) not in cache: |
366 return None | 367 return None |
367 return cache[(category, name)] | 368 return cache[(category, name)] |
368 | 369 |
369 def __constructProfileXml(self, profile): | 370 def __constructProfileXml(self, profile): |
370 """Construct xml for asked profile, filling values when needed | 371 """Construct xml for asked profile, filling values when needed |
371 /!\ as noticed in doc, don't forget to unlink the minidom.Document | 372 /!\ as noticed in doc, don't forget to unlink the minidom.Document |
372 @param profile: profile name (not key !) | 373 @param profile: profile name (not key !) |
373 @return: a deferred that fire a minidom.Document of the profile xml (cf warning above) | 374 @return: a deferred that fire a minidom.Document of the profile xml (cf warning above) |
374 """ | 375 """ |
375 def constructProfile(ignore,profile_cache): | 376 |
377 def constructProfile(ignore, profile_cache): | |
376 prof_xml = minidom.parseString('<params/>') | 378 prof_xml = minidom.parseString('<params/>') |
377 cache = {} | 379 cache = {} |
378 | 380 |
379 for type_node in self.dom.documentElement.childNodes: | 381 for type_node in self.dom.documentElement.childNodes: |
380 if type_node.nodeName == 'general' or type_node.nodeName == 'individual': #we use all params, general and individual | 382 if type_node.nodeName == 'general' or type_node.nodeName == 'individual': # we use all params, general and individual |
381 for cat_node in type_node.childNodes: | 383 for cat_node in type_node.childNodes: |
382 if cat_node.nodeName == 'category': | 384 if cat_node.nodeName == 'category': |
383 category = cat_node.getAttribute('name') | 385 category = cat_node.getAttribute('name') |
384 if not cache.has_key(category): | 386 if category not in cache: |
385 cache[category] = dest_cat = cat_node.cloneNode(True) #we make a copy for the new xml | 387 cache[category] = dest_cat = cat_node.cloneNode(True) # we make a copy for the new xml |
386 new_node = True | 388 new_node = True |
387 else: | 389 else: |
388 dest_cat = cache[category] | 390 dest_cat = cache[category] |
389 new_node = False #It's not a new node, we will merge information | 391 new_node = False # It's not a new node, we will merge information |
390 params = cat_node.getElementsByTagName("param") | 392 params = cat_node.getElementsByTagName("param") |
391 dest_params = {} | 393 dest_params = {} |
392 for node in dest_cat.childNodes: | 394 for node in dest_cat.childNodes: |
393 if node.nodeName != "param": | 395 if node.nodeName != "param": |
394 continue | 396 continue |
400 if name not in dest_params: | 402 if name not in dest_params: |
401 dest_params[name] = param_node.cloneNode(True) | 403 dest_params[name] = param_node.cloneNode(True) |
402 dest_cat.appendChild(dest_params[name]) | 404 dest_cat.appendChild(dest_params[name]) |
403 | 405 |
404 profile_value = self.__getParam(profile, category, name, type_node.nodeName, cache=profile_cache) | 406 profile_value = self.__getParam(profile, category, name, type_node.nodeName, cache=profile_cache) |
405 if profile_value!=None: #there is a value for this profile, we must change the default | 407 if profile_value is not None: # there is a value for this profile, we must change the default |
406 dest_params[name].setAttribute('value', profile_value) | 408 dest_params[name].setAttribute('value', profile_value) |
407 if new_node: | 409 if new_node: |
408 prof_xml.documentElement.appendChild(dest_cat) | 410 prof_xml.documentElement.appendChild(dest_cat) |
409 return prof_xml | 411 return prof_xml |
410 | 412 |
411 | 413 if profile in self.params: |
412 if self.params.has_key(profile): | |
413 d = defer.succeed(None) | 414 d = defer.succeed(None) |
414 profile_cache = self.params[profile] | 415 profile_cache = self.params[profile] |
415 else: | 416 else: |
416 #profile is not in cache, we load values in a short time cache | 417 #profile is not in cache, we load values in a short time cache |
417 profile_cache = {} | 418 profile_cache = {} |
424 profile = self.getProfileName(profile_key) | 425 profile = self.getProfileName(profile_key) |
425 if not profile: | 426 if not profile: |
426 error(_("Asking params for inexistant profile")) | 427 error(_("Asking params for inexistant profile")) |
427 return "" | 428 return "" |
428 d = self.getParams(profile) | 429 d = self.getParams(profile) |
429 return d.addCallback(lambda param_xml:paramsXml2xmlUI(param_xml)) | 430 return d.addCallback(lambda param_xml: paramsXml2xmlUI(param_xml)) |
430 | 431 |
431 def getParams(self, profile_key): | 432 def getParams(self, profile_key): |
432 """Construct xml for asked profile | 433 """Construct xml for asked profile |
433 Take params xml as skeleton""" | 434 Take params xml as skeleton""" |
434 profile = self.getProfileName(profile_key) | 435 profile = self.getProfileName(profile_key) |
462 return "<category />" | 463 return "<category />" |
463 | 464 |
464 d = self.__constructProfileXml(profile) | 465 d = self.__constructProfileXml(profile) |
465 return d.addCallback(returnCategoryXml) | 466 return d.addCallback(returnCategoryXml) |
466 | 467 |
467 def __getParamNode(self, name, category, _type="@ALL@"): #FIXME: is _type useful ? | 468 def __getParamNode(self, name, category, _type="@ALL@"): # FIXME: is _type useful ? |
468 """Return a node from the param_xml | 469 """Return a node from the param_xml |
469 @param name: name of the node | 470 @param name: name of the node |
470 @param category: category of the node | 471 @param category: category of the node |
471 @_type: keyword for search: | 472 @_type: keyword for search: |
472 @ALL@ search everywhere | 473 @ALL@ search everywhere |
473 @GENERAL@ only search in general type | 474 @GENERAL@ only search in general type |
474 @INDIVIDUAL@ only search in individual type | 475 @INDIVIDUAL@ only search in individual type |
475 @return: a tuple with the node type and the the node, or None if not found""" | 476 @return: a tuple with the node type and the the node, or None if not found""" |
476 | 477 |
477 for type_node in self.dom.documentElement.childNodes: | 478 for type_node in self.dom.documentElement.childNodes: |
478 if ( ((_type == "@ALL@" or _type == "@GENERAL@") and type_node.nodeName == 'general') | 479 if (((_type == "@ALL@" or _type == "@GENERAL@") and type_node.nodeName == 'general') |
479 or ( (_type == "@ALL@" or _type == "@INDIVIDUAL@") and type_node.nodeName == 'individual') ): | 480 or ((_type == "@ALL@" or _type == "@INDIVIDUAL@") and type_node.nodeName == 'individual')): |
480 for node in type_node.getElementsByTagName('category'): | 481 for node in type_node.getElementsByTagName('category'): |
481 if node.getAttribute("name") == category: | 482 if node.getAttribute("name") == category: |
482 params = node.getElementsByTagName("param") | 483 params = node.getElementsByTagName("param") |
483 for param in params: | 484 for param in params: |
484 if param.getAttribute("name") == name: | 485 if param.getAttribute("name") == name: |
485 return (type_node.nodeName, param) | 486 return (type_node.nodeName, param) |
486 return None | 487 return None |
487 | 488 |
488 def getParamsCategories(self): | 489 def getParamsCategories(self): |
489 """return the categories availables""" | 490 """return the categories availables""" |
490 categories=[] | 491 categories = [] |
491 for cat in self.dom.getElementsByTagName("category"): | 492 for cat in self.dom.getElementsByTagName("category"): |
492 name = cat.getAttribute("name") | 493 name = cat.getAttribute("name") |
493 if name not in categories: | 494 if name not in categories: |
494 categories.append(cat.getAttribute("name")) | 495 categories.append(cat.getAttribute("name")) |
495 return categories | 496 return categories |
496 | 497 |
497 def setParam(self, name, value, category, profile_key='@NONE@'): | 498 def setParam(self, name, value, category, profile_key='@NONE@'): |
498 """Set a parameter, return None if the parameter is not in param xml""" | 499 """Set a parameter, return None if the parameter is not in param xml""" |
499 #TODO: use different behaviour depending of the data type (e.g. password encrypted) | 500 #TODO: use different behaviour depending of the data type (e.g. password encrypted) |
500 if profile_key!="@NONE@": | 501 if profile_key != "@NONE@": |
501 profile = self.getProfileName(profile_key) | 502 profile = self.getProfileName(profile_key) |
502 if not profile: | 503 if not profile: |
503 error(_('Trying to set parameter for an unknown profile')) | 504 error(_('Trying to set parameter for an unknown profile')) |
504 return #TODO: throw an error | 505 return # TODO: throw an error |
505 | 506 |
506 node = self.__getParamNode(name, category, '@ALL@') | 507 node = self.__getParamNode(name, category, '@ALL@') |
507 if not node: | 508 if not node: |
508 error(_('Requesting an unknown parameter (%(category)s/%(name)s)') % {'category':category, 'name':name}) | 509 error(_('Requesting an unknown parameter (%(category)s/%(name)s)') % {'category': category, 'name': name}) |
509 return | 510 return |
510 | 511 |
511 if node[0] == 'general': | 512 if node[0] == 'general': |
512 self.params_gen[(category, name)] = value | 513 self.params_gen[(category, name)] = value |
513 self.storage.setGenParam(category, name, value) | 514 self.storage.setGenParam(category, name, value) |
518 | 519 |
519 assert (node[0] == 'individual') | 520 assert (node[0] == 'individual') |
520 assert (profile_key != "@NONE@") | 521 assert (profile_key != "@NONE@") |
521 | 522 |
522 _type = node[1].getAttribute("type") | 523 _type = node[1].getAttribute("type") |
523 if _type=="button": | 524 if _type == "button": |
524 print "clique",node.toxml() | 525 print "clique", node.toxml() |
525 else: | 526 else: |
526 if self.host.isConnected(profile): #key can not exists if profile is not connected | 527 if self.host.isConnected(profile): # key can not exists if profile is not connected |
527 self.params[profile][(category, name)] = value | 528 self.params[profile][(category, name)] = value |
528 self.host.bridge.paramUpdate(name, value, category, profile) | 529 self.host.bridge.paramUpdate(name, value, category, profile) |
529 self.storage.setIndParam(category, name, value, profile) | 530 self.storage.setIndParam(category, name, value, profile) |
530 | 531 |
532 | |
531 class Memory(object): | 533 class Memory(object): |
532 """This class manage all persistent informations""" | 534 """This class manage all persistent informations""" |
533 | 535 |
534 def __init__(self, host): | 536 def __init__(self, host): |
535 info (_("Memory manager init")) | 537 info(_("Memory manager init")) |
536 self.initialized = defer.Deferred() | 538 self.initialized = defer.Deferred() |
537 self.host = host | 539 self.host = host |
538 self.entitiesCache={} #XXX: keep presence/last resource/other data in cache | 540 self.entitiesCache = {} # XXX: keep presence/last resource/other data in cache |
539 # /!\ an entity is not necessarily in roster | 541 # /!\ an entity is not necessarily in roster |
540 self.subscriptions={} | 542 self.subscriptions = {} |
541 self.server_features={} #used to store discovery's informations | 543 self.server_features = {} # used to store discovery's informations |
542 self.server_identities={} | 544 self.server_identities = {} |
543 self.config = self.parseMainConf() | 545 self.config = self.parseMainConf() |
544 host.set_const('savefile_database', SAVEFILE_DATABASE) | 546 host.set_const('savefile_database', SAVEFILE_DATABASE) |
545 database_file = os.path.expanduser(self.getConfig('','local_dir')+ | 547 database_file = os.path.expanduser(self.getConfig('', 'local_dir') + |
546 self.host.get_const('savefile_database')) | 548 self.host.get_const('savefile_database')) |
547 self.storage = SqliteStorage(database_file) | 549 self.storage = SqliteStorage(database_file) |
548 PersistentDict.storage = self.storage | 550 PersistentDict.storage = self.storage |
549 self.params=Params(host, self.storage) | 551 self.params = Params(host, self.storage) |
550 self.loadFiles() | 552 self.loadFiles() |
551 d = self.storage.initialized.addCallback(lambda ignore:self.load()) | 553 d = self.storage.initialized.addCallback(lambda ignore: self.load()) |
552 self.memory_data = PersistentDict("memory") | 554 self.memory_data = PersistentDict("memory") |
553 d.addCallback(lambda ignore: self.memory_data.load()) | 555 d.addCallback(lambda ignore: self.memory_data.load()) |
554 d.chainDeferred(self.initialized) | 556 d.chainDeferred(self.initialized) |
555 | 557 |
556 def parseMainConf(self): | 558 def parseMainConf(self): |
557 """look for main .ini configuration file, and parse it""" | 559 """look for main .ini configuration file, and parse it""" |
558 _config = SafeConfigParser(defaults=default_config) | 560 _config = SafeConfigParser(defaults=default_config) |
559 try: | 561 try: |
560 _config.read(map(os.path.expanduser, ['/etc/sat.conf', '~/sat.conf', '~/.sat.conf', 'sat.conf', '.sat.conf'])) | 562 _config.read(map(os.path.expanduser, ['/etc/sat.conf', '~/sat.conf', '~/.sat.conf', 'sat.conf', '.sat.conf'])) |
561 except: | 563 except: |
562 error (_("Can't read main config !")) | 564 error(_("Can't read main config !")) |
563 | 565 |
564 return _config | 566 return _config |
565 | 567 |
566 def getConfig(self, section, name): | 568 def getConfig(self, section, name): |
567 """Get the main configuration option | 569 """Get the main configuration option |
568 @param section: section of the config file (None or '' for DEFAULT) | 570 @param section: section of the config file (None or '' for DEFAULT) |
569 @param name: name of the option | 571 @param name: name of the option |
570 """ | 572 """ |
571 if not section: | 573 if not section: |
572 section='DEFAULT' | 574 section = 'DEFAULT' |
573 try: | 575 try: |
574 _value = self.config.get(section, name) | 576 _value = self.config.get(section, name) |
575 except (NoOptionError, NoSectionError): | 577 except (NoOptionError, NoSectionError): |
576 _value = '' | 578 _value = '' |
577 | 579 |
578 return os.path.expanduser(_value) if name.endswith('_path') or name.endswith('_dir') else _value | 580 return os.path.expanduser(_value) if name.endswith('_path') or name.endswith('_dir') else _value |
579 | 581 |
580 | |
581 def loadFiles(self): | 582 def loadFiles(self): |
582 """Load parameters and all memory things from file/db""" | 583 """Load parameters and all memory things from file/db""" |
583 param_file_xml = os.path.expanduser(self.getConfig('','local_dir')+ | 584 param_file_xml = os.path.expanduser(self.getConfig('', 'local_dir') + |
584 self.host.get_const('savefile_param_xml')) | 585 self.host.get_const('savefile_param_xml')) |
585 | 586 |
586 #parameters template | 587 #parameters template |
587 if os.path.exists(param_file_xml): | 588 if os.path.exists(param_file_xml): |
588 try: | 589 try: |
589 self.params.load_xml(param_file_xml) | 590 self.params.load_xml(param_file_xml) |
590 debug(_("params template loaded")) | 591 debug(_("params template loaded")) |
591 except Exception as e: | 592 except Exception as e: |
592 error (_("Can't load params template: %s") % (e,)) | 593 error(_("Can't load params template: %s") % (e, )) |
593 self.params.load_default_params() | 594 self.params.load_default_params() |
594 else: | 595 else: |
595 info (_("No params template, using default template")) | 596 info(_("No params template, using default template")) |
596 self.params.load_default_params() | 597 self.params.load_default_params() |
597 | |
598 | 598 |
599 def load(self): | 599 def load(self): |
600 """Load parameters and all memory things from db""" | 600 """Load parameters and all memory things from db""" |
601 #parameters data | 601 #parameters data |
602 return self.params.loadGenParams() | 602 return self.params.loadGenParams() |
620 try: | 620 try: |
621 del self.entitiesCache[profile] | 621 del self.entitiesCache[profile] |
622 except KeyError: | 622 except KeyError: |
623 error(_("Trying to purge roster status cache for a profile not in memory: [%s]") % profile) | 623 error(_("Trying to purge roster status cache for a profile not in memory: [%s]") % profile) |
624 | 624 |
625 | |
626 def save(self): | 625 def save(self): |
627 """Save parameters and all memory things to file/db""" | 626 """Save parameters and all memory things to file/db""" |
628 #TODO: need to encrypt files (at least passwords !) and set permissions | 627 #TODO: need to encrypt files (at least passwords !) and set permissions |
629 param_file_xml = os.path.expanduser(self.getConfig('','local_dir')+ | 628 param_file_xml = os.path.expanduser(self.getConfig('', 'local_dir') + |
630 self.host.get_const('savefile_param_xml')) | 629 self.host.get_const('savefile_param_xml')) |
631 | 630 |
632 self.params.save_xml(param_file_xml) | 631 self.params.save_xml(param_file_xml) |
633 debug(_("params saved")) | 632 debug(_("params saved")) |
634 | 633 |
635 def getProfilesList(self): | 634 def getProfilesList(self): |
636 return self.storage.getProfilesList() | 635 return self.storage.getProfilesList() |
637 | |
638 | 636 |
639 def getProfileName(self, profile_key): | 637 def getProfileName(self, profile_key): |
640 """Return name of profile from keyword | 638 """Return name of profile from keyword |
641 @param profile_key: can be the profile name or a keywork (like @DEFAULT@) | 639 @param profile_key: can be the profile name or a keywork (like @DEFAULT@) |
642 @return: profile name or None if it doesn't exist""" | 640 @return: profile name or None if it doesn't exist""" |
658 """Delete an existing profile | 656 """Delete an existing profile |
659 @param name: Name of the profile""" | 657 @param name: Name of the profile""" |
660 return self.params.deleteProfile(name) | 658 return self.params.deleteProfile(name) |
661 | 659 |
662 def addToHistory(self, from_jid, to_jid, message, _type='chat', timestamp=None, profile="@NONE@"): | 660 def addToHistory(self, from_jid, to_jid, message, _type='chat', timestamp=None, profile="@NONE@"): |
663 assert(profile!="@NONE@") | 661 assert profile != "@NONE@" |
664 return self.storage.addToHistory(from_jid, to_jid, message, _type, timestamp, profile) | 662 return self.storage.addToHistory(from_jid, to_jid, message, _type, timestamp, profile) |
665 | 663 |
666 def getHistory(self, from_jid, to_jid, limit=0, between=True, profile="@NONE@"): | 664 def getHistory(self, from_jid, to_jid, limit=0, between=True, profile="@NONE@"): |
667 assert(profile != "@NONE@") | 665 assert profile != "@NONE@" |
668 return self.storage.getHistory(jid.JID(from_jid), jid.JID(to_jid), limit, between, profile) | 666 return self.storage.getHistory(jid.JID(from_jid), jid.JID(to_jid), limit, between, profile) |
669 | 667 |
670 def addServerFeature(self, feature, profile): | 668 def addServerFeature(self, feature, profile): |
671 """Add a feature discovered from server | 669 """Add a feature discovered from server |
672 @param feature: string of the feature | 670 @param feature: string of the feature |
673 @param profile: which profile is using this server ?""" | 671 @param profile: which profile is using this server ?""" |
674 if not self.server_features.has_key(profile): | 672 if profile not in self.server_features: |
675 self.server_features[profile] = [] | 673 self.server_features[profile] = [] |
676 self.server_features[profile].append(feature) | 674 self.server_features[profile].append(feature) |
677 | 675 |
678 def addServerIdentity(self, category, _type, entity, profile): | 676 def addServerIdentity(self, category, _type, entity, profile): |
679 """Add an identity discovered from server | 677 """Add an identity discovered from server |
680 @param feature: string of the feature | 678 @param feature: string of the feature |
681 @param profile: which profile is using this server ?""" | 679 @param profile: which profile is using this server ?""" |
682 if not profile in self.server_identities: | 680 if not profile in self.server_identities: |
683 self.server_identities[profile] = {} | 681 self.server_identities[profile] = {} |
684 if not self.server_identities[profile].has_key((category, _type)): | 682 if (category, _type) not in self.server_identities[profile]: |
685 self.server_identities[profile][(category, _type)]=set() | 683 self.server_identities[profile][(category, _type)] = set() |
686 self.server_identities[profile][(category, _type)].add(entity) | 684 self.server_identities[profile][(category, _type)].add(entity) |
687 | 685 |
688 def getServerServiceEntities(self, category, _type, profile): | 686 def getServerServiceEntities(self, category, _type, profile): |
689 """Return all available entities for a service""" | 687 """Return all available entities for a service""" |
690 if profile in self.server_identities: | 688 if profile in self.server_identities: |
693 return None | 691 return None |
694 | 692 |
695 def getServerServiceEntity(self, category, _type, profile): | 693 def getServerServiceEntity(self, category, _type, profile): |
696 """Helper method to get first available entity for a service""" | 694 """Helper method to get first available entity for a service""" |
697 entities = self.getServerServiceEntities(category, _type, profile) | 695 entities = self.getServerServiceEntities(category, _type, profile) |
698 if entities == None: | 696 if entities is None: |
699 warning(_("Entities (%(category)s/%(type)s) not available, maybe they haven't been asked to server yet ?") % {"category":category, | 697 warning(_("Entities (%(category)s/%(type)s) not available, maybe they haven't been asked to server yet ?") % {"category": category, |
700 "type":_type}) | 698 "type": _type}) |
701 return None | 699 return None |
702 else: | 700 else: |
703 return list(entities)[0] if entities else None | 701 return list(entities)[0] if entities else None |
704 | 702 |
705 def hasServerFeature(self, feature, profile_key): | 703 def hasServerFeature(self, feature, profile_key): |
706 """Tell if the server of the profile has the required feature""" | 704 """Tell if the server of the profile has the required feature""" |
707 profile = self.getProfileName(profile_key) | 705 profile = self.getProfileName(profile_key) |
708 if not profile: | 706 if not profile: |
709 error (_('Trying find server feature for a non-existant profile')) | 707 error(_('Trying find server feature for a non-existant profile')) |
710 return | 708 return |
711 assert(self.server_features.has_key(profile)) | 709 assert profile in self.server_features |
712 return feature in self.server_features[profile] | 710 return feature in self.server_features[profile] |
713 | 711 |
714 def getLastResource(self, contact, profile_key): | 712 def getLastResource(self, contact, profile_key): |
715 """Return the last resource used by a contact | 713 """Return the last resource used by a contact |
716 @param contact: contact jid (unicode) | 714 @param contact: contact jid (unicode) |
736 entities_presence = {} | 734 entities_presence = {} |
737 for entity in self.entitiesCache[profile]: | 735 for entity in self.entitiesCache[profile]: |
738 if "presence" in self.entitiesCache[profile][entity]: | 736 if "presence" in self.entitiesCache[profile][entity]: |
739 entities_presence[entity] = self.entitiesCache[profile][entity]["presence"] | 737 entities_presence[entity] = self.entitiesCache[profile][entity]["presence"] |
740 | 738 |
741 debug ("Memory getPresenceStatus (%s)", entities_presence) | 739 debug("Memory getPresenceStatus (%s)", entities_presence) |
742 return entities_presence | 740 return entities_presence |
743 | 741 |
744 def setPresenceStatus(self, entity_jid, show, priority, statuses, profile_key): | 742 def setPresenceStatus(self, entity_jid, show, priority, statuses, profile_key): |
745 """Change the presence status of an entity""" | 743 """Change the presence status of an entity""" |
746 profile = self.getProfileName(profile_key) | 744 profile = self.getProfileName(profile_key) |
747 if not profile: | 745 if not profile: |
748 error(_('Trying to add presence status to a non-existant profile')) | 746 error(_('Trying to add presence status to a non-existant profile')) |
749 return | 747 return |
750 entity_data = self.entitiesCache[profile].setdefault(entity_jid.userhost(),{}) | 748 entity_data = self.entitiesCache[profile].setdefault(entity_jid.userhost(), {}) |
751 resource = jid.parse(entity_jid.full())[2] or '' | 749 resource = jid.parse(entity_jid.full())[2] or '' |
752 if resource: | 750 if resource: |
753 entity_data["last_resource"] = resource | 751 entity_data["last_resource"] = resource |
754 if not "last_resource" in entity_data: | 752 if not "last_resource" in entity_data: |
755 entity_data["last_resource"] = '' | 753 entity_data["last_resource"] = '' |
756 | 754 |
757 entity_data.setdefault("presence",{})[resource] = (show, priority, statuses) | 755 entity_data.setdefault("presence", {})[resource] = (show, priority, statuses) |
758 | 756 |
759 def updateEntityData(self, entity_jid, key, value, profile_key): | 757 def updateEntityData(self, entity_jid, key, value, profile_key): |
760 """Set a misc data for an entity | 758 """Set a misc data for an entity |
761 @param entity_jid: JID of the entity | 759 @param entity_jid: JID of the entity |
762 @param key: key to set (eg: "type") | 760 @param key: key to set (eg: "type") |
766 profile = self.getProfileName(profile_key) | 764 profile = self.getProfileName(profile_key) |
767 if not profile: | 765 if not profile: |
768 raise exceptions.UnknownProfileError(_('Trying to get entity data for a non-existant profile')) | 766 raise exceptions.UnknownProfileError(_('Trying to get entity data for a non-existant profile')) |
769 if not profile in self.entitiesCache: | 767 if not profile in self.entitiesCache: |
770 raise exceptions.ProfileNotInCacheError | 768 raise exceptions.ProfileNotInCacheError |
771 entity_data = self.entitiesCache[profile].setdefault(entity_jid.userhost(),{}) | 769 entity_data = self.entitiesCache[profile].setdefault(entity_jid.userhost(), {}) |
772 entity_data[key] = value | 770 entity_data[key] = value |
773 if isinstance(value,basestring): | 771 if isinstance(value, basestring): |
774 self.host.bridge.entityDataUpdated(entity_jid.userhost(), key, value, profile) | 772 self.host.bridge.entityDataUpdated(entity_jid.userhost(), key, value, profile) |
775 | 773 |
776 def getEntityData(self, entity_jid, keys_list, profile_key): | 774 def getEntityData(self, entity_jid, keys_list, profile_key): |
777 """Get a list of cached values for entity | 775 """Get a list of cached values for entity |
778 @param entity_jid: JID of the entity | 776 @param entity_jid: JID of the entity |
808 try: | 806 try: |
809 del self.entitiesCache[profile][entity_jid.userhost()] | 807 del self.entitiesCache[profile][entity_jid.userhost()] |
810 except KeyError: | 808 except KeyError: |
811 pass | 809 pass |
812 | 810 |
813 | |
814 | |
815 def addWaitingSub(self, _type, entity_jid, profile_key): | 811 def addWaitingSub(self, _type, entity_jid, profile_key): |
816 """Called when a subcription request is received""" | 812 """Called when a subcription request is received""" |
817 profile = self.getProfileName(profile_key) | 813 profile = self.getProfileName(profile_key) |
818 assert(profile) | 814 assert profile |
819 if not self.subscriptions.has_key(profile): | 815 if profile not in self.subscriptions: |
820 self.subscriptions[profile] = {} | 816 self.subscriptions[profile] = {} |
821 self.subscriptions[profile][entity_jid] = _type | 817 self.subscriptions[profile][entity_jid] = _type |
822 | 818 |
823 def delWaitingSub(self, entity_jid, profile_key): | 819 def delWaitingSub(self, entity_jid, profile_key): |
824 """Called when a subcription request is finished""" | 820 """Called when a subcription request is finished""" |
825 profile = self.getProfileName(profile_key) | 821 profile = self.getProfileName(profile_key) |
826 assert(profile) | 822 assert profile |
827 if self.subscriptions.has_key(profile) and self.subscriptions[profile].has_key(entity_jid): | 823 if profile in self.subscriptions and entity_jid in self.subscriptions[profile]: |
828 del self.subscriptions[profile][entity_jid] | 824 del self.subscriptions[profile][entity_jid] |
829 | 825 |
830 def getWaitingSub(self, profile_key): | 826 def getWaitingSub(self, profile_key): |
831 """Called to get a list of currently waiting subscription requests""" | 827 """Called to get a list of currently waiting subscription requests""" |
832 profile = self.getProfileName(profile_key) | 828 profile = self.getProfileName(profile_key) |
833 if not profile: | 829 if not profile: |
834 error(_('Asking waiting subscriptions for a non-existant profile')) | 830 error(_('Asking waiting subscriptions for a non-existant profile')) |
835 return {} | 831 return {} |
836 if not self.subscriptions.has_key(profile): | 832 if profile not in self.subscriptions: |
837 return {} | 833 return {} |
838 | 834 |
839 return self.subscriptions[profile] | 835 return self.subscriptions[profile] |
840 | 836 |
841 def getStringParamA(self, name, category, attr="value", profile_key='@DEFAULT@'): | 837 def getStringParamA(self, name, category, attr="value", profile_key='@DEFAULT@'): |