diff src/memory/memory.py @ 777:5642939d254e

core, bridge: new method paramsRegisterApp to register frontend's specific parameters
author souliane <souliane@mailoo.org>
date Fri, 27 Dec 2013 13:28:26 +0100
parents bfabeedbf32e
children bfafed251b40
line wrap: on
line diff
--- a/src/memory/memory.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/src/memory/memory.py	Fri Dec 27 13:28:26 2013 +0100
@@ -295,10 +295,40 @@
         #the node is new
         return None
 
-    def updateParams(self, xml):
+    def updateParams(self, xml, security_limit=NO_SECURITY_LIMIT, app=''):
         """import xml in parameters, do nothing if the param already exist
-        @param xml: parameters in xml form"""
-        src_dom = minidom.parseString(xml.encode('utf-8'))
+        If security_limit is specified and greater than -1, the parameters
+        that have a security level lower than security_limit are skipped.
+        @param xml: parameters in xml form
+        @param security_limit: -1 means no security then the higher the most secure
+        @param app: name of the frontend registering the parameters or empty value
+        """
+        src_parent = minidom.parseString(xml.encode('utf-8')).documentElement
+
+        def pre_process_app_node(src_parent, security_limit, app):
+            """Parameters that are registered from a frontend must be checked"""
+            to_remove = []
+            for type_node in src_parent.childNodes:
+                if type_node.nodeName != INDIVIDUAL:
+                    to_remove.append(type_node)  # accept individual parameters only
+                    continue
+                for cat_node in type_node.childNodes:
+                    if cat_node.nodeName != 'category':
+                        to_remove.append(cat_node)
+                        continue
+                    to_remove_count = 0  # count the params to be removed from current category
+                    for node in cat_node.childNodes:
+                        if node.nodeName != "param" or not self.checkSecurityLimit(node, security_limit):
+                            to_remove.append(node)
+                            to_remove_count += 1
+                            continue
+                        node.setAttribute('app', app)
+                    if len(cat_node.childNodes) == to_remove_count:  # remove empty category
+                        for dummy in xrange(0, to_remove_count):
+                            to_remove.pop()
+                        to_remove.append(cat_node)
+            for node in to_remove:
+                node.parentNode.removeChild(node)
 
         def import_node(tgt_parent, src_parent):
             for child in src_parent.childNodes:
@@ -315,7 +345,28 @@
                         # the node already exists, we recurse 1 more level
                         import_node(node, child)
 
-        import_node(self.dom.documentElement, src_dom.documentElement)
+        if app:
+            pre_process_app_node(src_parent, security_limit, app)
+        import_node(self.dom.documentElement, src_parent)
+
+    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 lower than security_limit are skipped.
+        @param xml: XML definition of the parameters to be added
+        @param security_limit: -1 means no security then the higher the most secure
+        @param app: name of the frontend registering the parameters
+        """
+        if not app:
+            warning(_("Trying to register frontends parameters with no specified app: aborted"))
+            return
+        if not hasattr(self, "frontends_cache"):
+            self.frontends_cache = {}
+        if app in self.frontends_cache:
+            warning(_("Trying to register twice frontends parameters for %(app)s: aborted" % {"app": app}))
+            return
+        self.updateParams(xml, security_limit, app)
+        debug("Frontends parameters registered for %(app)s" % {'app': app})
 
     def __default_ok(self, value, name, category):
         #FIXME: will not work with individual parameters
@@ -471,12 +522,13 @@
             return None
         return cache[(category, name)]
 
-    def __constructProfileXml(self, security_limit, 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
-        @security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
+        @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.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
         @param profile: profile name (not key !)
         @return: a deferred that fire a minidom.Document of the profile xml (cf warning above)
         """
@@ -518,6 +570,8 @@
                         name = param_node.getAttribute('name')
                         if not self.checkSecurityLimit(param_node, security_limit):
                             continue
+                        if not self.checkApp(param_node, app):
+                            continue
                         if name not in dest_params:
                             # this is reached when a previous category exists
                             dest_params[name] = param_node.cloneNode(True)
@@ -551,18 +605,31 @@
 
         return d.addCallback(constructProfile, profile_cache)
 
-    def getParamsUI(self, security_limit, profile_key):
-        """Return a SàT XMLUI for parameters, with given profile"""
+    def getParamsUI(self, security_limit, app, profile_key):
+        """
+        @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.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @param profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
+        @return: a SàT XMLUI for parameters
+        """
         profile = self.getProfileName(profile_key)
         if not profile:
             error(_("Asking params for inexistant profile"))
             return ""
-        d = self.getParams(security_limit, profile)
+        d = self.getParams(security_limit, app, profile)
         return d.addCallback(lambda param_xml: paramsXml2xmlUI(param_xml))
 
-    def getParams(self, security_limit, profile_key):
-        """Construct xml for asked profile
-        Take params xml as skeleton"""
+    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.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @param profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
+        @return: XML of parameters
+        """
         profile = self.getProfileName(profile_key)
         if not profile:
             error(_("Asking params for inexistant profile"))
@@ -573,10 +640,18 @@
             prof_xml.unlink()
             return '\n'.join((line for line in return_xml.split('\n') if line))
 
-        return self.__constructProfileXml(security_limit, profile).addCallback(returnXML)
+        return self.__constructProfileXml(security_limit, app, profile).addCallback(returnXML)
 
-    def getParamsForCategory(self, category, security_limit, profile_key):
-        """Return node's xml for selected category"""
+    def getParamsForCategory(self, category, security_limit, app, profile_key):
+        """
+        @param category: the desired category
+        @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.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @param profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
+        @return: node's xml for selected category
+        """
         #TODO: manage category of general type (without existant profile)
         profile = self.getProfileName(profile_key)
         if not profile:
@@ -593,7 +668,7 @@
             prof_xml.unlink()
             return "<category />"
 
-        d = self.__constructProfileXml(security_limit, profile)
+        d = self.__constructProfileXml(security_limit, app, profile)
         return d.addCallback(returnCategoryXml)
 
     def _getParamNode(self, name, category, type_="@ALL@"):  # FIXME: is type_ useful ?
@@ -680,6 +755,16 @@
                 return True
         return False
 
+    def checkApp(self, node, app):
+        """Check the given node against the given app.
+        @param node: parameter node
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @return: True if this node concerns the given app.
+        """
+        if not app or not node.hasAttribute("app"):
+            return True
+        return node.getAttribute("app") == app
+
 
 class Memory(object):
     """This class manage all persistent informations"""
@@ -1063,14 +1148,14 @@
     def asyncGetStringParamA(self, name, category, attr="value", security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
         return self.params.asyncGetStringParamA(name, category, attr, security_limit, profile_key)
 
-    def getParamsUI(self, security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
-        return self.params.getParamsUI(security_limit, profile_key)
+    def getParamsUI(self, security_limit=NO_SECURITY_LIMIT, app='', profile_key='@NONE@'):
+        return self.params.getParamsUI(security_limit, app, profile_key)
 
-    def getParams(self, security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
-        return self.params.getParams(security_limit, profile_key)
+    def getParams(self, security_limit=NO_SECURITY_LIMIT, app='', profile_key='@NONE@'):
+        return self.params.getParams(security_limit, app, profile_key)
 
-    def getParamsForCategory(self, category, security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
-        return self.params.getParamsForCategory(category, security_limit, profile_key)
+    def getParamsForCategory(self, category, security_limit=NO_SECURITY_LIMIT, app='', profile_key='@NONE@'):
+        return self.params.getParamsForCategory(category, security_limit, app, profile_key)
 
     def getParamsCategories(self):
         return self.params.getParamsCategories()
@@ -1081,5 +1166,8 @@
     def updateParams(self, xml):
         return self.params.updateParams(xml)
 
+    def paramsRegisterApp(self, xml, security_limit=NO_SECURITY_LIMIT, app=''):
+        return self.params.paramsRegisterApp(xml, security_limit, app)
+
     def setDefault(self, name, category, callback, errback=None):
         return self.params.setDefault(name, category, callback, errback)