# HG changeset patch # User Goffi # Date 1440088527 -7200 # Node ID ac522c4dab0ee8ed83180aff6f01e4f774cc1418 # Parent 48706f4ff19c0c397b544c0597b6dd02c1453625 core (params): jids_list type management diff -r 48706f4ff19c -r ac522c4dab0e src/memory/params.py --- a/src/memory/params.py Thu Aug 20 18:33:52 2015 +0200 +++ b/src/memory/params.py Thu Aug 20 18:35:27 2015 +0200 @@ -27,8 +27,13 @@ log = getLogger(__name__) from twisted.internet import defer from twisted.python.failure import Failure +from twisted.words.protocols.jabber import jid from sat.tools.xml_tools import paramsXML2XMLUI +# TODO: params should be rewritten using Twisted directly instead of minidom +# general params should be linked to sat.conf and kept synchronised +# this need an overall simplification to make maintenance easier + class Params(object): """This class manage parameters with xml""" @@ -77,7 +82,6 @@ 'new_account_label': D_("Register new account"), 'autoconnect_label': D_('Connect on frontend startup'), 'autodisconnect_label': D_('Disconnect on frontend closure'), - 'category_misc': D_("Misc"), } def load_default_params(self): @@ -113,22 +117,28 @@ def loadGenParams(self): """Load general parameters data from storage - @return: deferred triggered once params are loaded""" + + @return: deferred triggered once params are loaded + """ return self.storage.loadGenParams(self.params_gen) def loadIndParams(self, profile, cache=None): """Load individual parameters + set self.params cache or a temporary cache @param profile: profile to load (*must exist*) @param cache: if not None, will be used to store the value, as a short time cache - @return: deferred triggered once params are loaded""" + @return: deferred triggered once params are loaded + """ if cache is None: self.params[profile] = {} return self.storage.loadIndParams(self.params[profile] if cache is None else cache, profile) def purgeProfile(self, profile): """Remove cache data of a profile - @param profile: %(doc_profile)s""" + + @param profile: %(doc_profile)s + """ try: del self.params[profile] except KeyError: @@ -149,6 +159,7 @@ def asyncCreateProfile(self, profile): """Create a new profile + @param profile: name of the profile @param callback: called when the profile actually exists in database and memory @return: a Deferred instance @@ -210,6 +221,7 @@ def __get_unique_node(self, parent, tag, name): """return node with given tag + @param parent: parent of nodes to check (e.g. documentElement) @param tag: tag to check (e.g. "category") @param name: name to check (e.g. "JID") @@ -224,12 +236,14 @@ def updateParams(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=''): """import xml in parameters, update if the param already exists + If security_limit is specified and greater than -1, the parameters that have a security level greater than security_limit are skipped. @param xml: parameters in xml form @param security_limit: -1 means no security, 0 is the maximum security then the higher the less secure @param app: name of the frontend registering the parameters or empty value """ + # TODO: should word with domish.Element src_parent = minidom.parseString(xml.encode('utf-8')).documentElement def pre_process_app_node(src_parent, security_limit, app): @@ -278,6 +292,7 @@ def paramsRegisterApp(self, xml, security_limit, app): """Register frontend's specific parameters + If security_limit is specified and greater than -1, the parameters that have a security level greater than security_limit are skipped. @param xml: XML definition of the parameters to be added @@ -305,6 +320,7 @@ def setDefault(self, name, category, callback, errback=None): """Set default value of parameter + 'default_cb' attibute of parameter must be set to 'yes' @param name: name of the parameter @param category: category of the parameter @@ -341,7 +357,7 @@ if attr == 'value': 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 if node.getAttribute('type') == 'bool': - return value_to_use.lower() not in ('false', '0', 'no') + return C.bool(value_to_use) if node.getAttribute('type') == 'int': return int(value_to_use) elif node.getAttribute('type') == 'list': @@ -360,6 +376,18 @@ else: log.error(_(u'Parameter (%(cat)s, %(param)s) of type list has more than one default option!') % {'cat': cat, 'param': param}) raise exceptions.DataError + elif node.getAttribute('type') == 'jids_list': + jids = value.split('\t') + to_delete = [] + for idx, value in enumerate(jids): + try: + jids[idx] = jid.JID(value) + except jid.InvalidFormat: + log.warning(u"Incorrect jid value found in jids list: [{}]".format(value)) + to_delete.append(value) + for value in to_delete: + jids.remove(value) + return jids return value_to_use return node.getAttribute(attr) @@ -367,11 +395,10 @@ """Get attribute value (synchronous). /!\ This method can not be used to retrieve password values. - @param node: XML param node @param attr: name of the attribute to get (e.g.: 'value' or 'type') @param value: user defined value - @return: str + @return (unicode, bool, int, list): value to retrieve """ if attr == 'value' and node.getAttribute('type') == 'password': raise exceptions.InternalError('To retrieve password values, use _asyncGetAttr instead of _getAttr') @@ -382,12 +409,11 @@ Profile passwords are returned hashed (if not empty), other passwords are returned decrypted (if not empty). - @param node: XML param node @param attr: name of the attribute to get (e.g.: 'value' or 'type') @param value: user defined value @param profile: %(doc_profile)s - @return: a deferred str + @return (unicode, bool, int, list): Deferred value to retrieve """ value = self._getAttr_internal(node, attr, value) if attr != 'value' or node.getAttribute('type') != 'password': @@ -424,13 +450,12 @@ /!\ This method would return encrypted password values, to get the plain values you have to use _asyncGetParamA. - - @param name: name of the parameter - @param category: category of the parameter - @param attr: name of the attribute (default: "value") - @param profile: owner of the param (@ALL@ for everyone) - @return: attribute - """ + @param name: name of the parameter + @param category: category of the parameter + @param attr: name of the attribute (default: "value") + @param profile: owner of the param (@ALL@ for everyone) + @return: attribute + """ #FIXME: looks really dirty and buggy, need to be reviewed/refactored node = self._getParamNode(name, category) if not node: @@ -466,6 +491,7 @@ def asyncGetParamA(self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE): """Helper method to get a specific attribute. + @param name: name of the parameter @param category: category of the parameter @param attr: name of the attribute (default: "value") @@ -504,6 +530,7 @@ def _getParam(self, category, name, type_=C.INDIVIDUAL, cache=None, profile=C.PROF_KEY_NONE): """Return the param, or None if it doesn't exist + @param category: param category @param name: param name @param type_: GENERAL or INDIVIDUAL @@ -515,7 +542,7 @@ if (category, name) in self.params_gen: return self.params_gen[(category, name)] return None # This general param has the default value - assert (type_ == C.INDIVIDUAL) + assert type_ == C.INDIVIDUAL if profile == C.PROF_KEY_NONE: raise exceptions.ProfileNotSetError if profile in self.params: @@ -527,8 +554,9 @@ return None return cache[(category, name)] - def __constructProfileXml(self, security_limit, app, profile): + def _constructProfileXml(self, security_limit, app, profile): """Construct xml for asked profile, filling values when needed + /!\ as noticed in doc, don't forget to unlink the minidom.Document @param security_limit: NO_SECURITY_LIMIT (-1) to return all the params. Otherwise sole the params which have a security level defined *and* @@ -601,6 +629,12 @@ option.removeAttribute('selected') except NotFoundErr: pass + elif dest_params[name].getAttribute('type') == 'jids_list': + jids = profile_value.split('\t') # FIXME: it's not good to use tabs as separator ! + for jid_ in jids: + jid_elt = prof_xml.createElement('jid') + jid_elt.appendChild(prof_xml.createTextNode(jid_)) + dest_params[name].appendChild(jid_elt) else: dest_params[name].setAttribute('value', profile_value) if new_node: @@ -643,6 +677,7 @@ def getParams(self, security_limit, app, profile_key): """Construct xml for asked profile, take params xml as skeleton + @param security_limit: NO_SECURITY_LIMIT (-1) to return all the params. Otherwise sole the params which have a security level defined *and* lower or equal to the specified value are returned. @@ -660,7 +695,7 @@ prof_xml.unlink() return '\n'.join((line for line in return_xml.split('\n') if line)) - return self.__constructProfileXml(security_limit, app, profile).addCallback(returnXML) + return self._constructProfileXml(security_limit, app, profile).addCallback(returnXML) def getParamsForCategory(self, category, security_limit, app, profile_key): """ @@ -688,7 +723,7 @@ prof_xml.unlink() return "" - d = self.__constructProfileXml(security_limit, app, profile) + d = self._constructProfileXml(security_limit, app, profile) return d.addCallback(returnCategoryXml) def _getParamNode(self, name, category, type_="@ALL@"): # FIXME: is type_ useful ? @@ -783,8 +818,8 @@ self.host.trigger.point("paramUpdateTrigger", name, value, category, node[0], profile) return defer.succeed(None) - assert (node[0] == C.INDIVIDUAL) - assert (profile_key != C.PROF_KEY_NONE) + assert node[0] == C.INDIVIDUAL + assert profile_key != C.PROF_KEY_NONE d_list = [] if type_ == "button":