diff src/memory/params.py @ 1477:ac522c4dab0e

core (params): jids_list type management
author Goffi <goffi@goffi.org>
date Thu, 20 Aug 2015 18:35:27 +0200
parents c7fd121a6180
children 8d61160ee4b8
line wrap: on
line diff
--- 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 "<category />"
 
-        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":