diff sat/memory/params.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 26edcf3a30eb
children e9cd473a2f46
line wrap: on
line diff
--- a/sat/memory/params.py	Wed Jun 27 07:51:29 2018 +0200
+++ b/sat/memory/params.py	Wed Jun 27 20:14:46 2018 +0200
@@ -24,6 +24,7 @@
 from sat.memory.crypto import BlockCipher, PasswordHasher
 from xml.dom import minidom, NotFoundErr
 from sat.core.log import getLogger
+
 log = getLogger(__name__)
 from twisted.internet import defer
 from twisted.python.failure import Failure
@@ -43,17 +44,18 @@
     @return (generator[domish.Element]): <jid/> elements
     """
     for jid_ in jids:
-        jid_elt = domish.Element((None, 'jid'))
+        jid_elt = domish.Element((None, "jid"))
         jid_elt.addContent(jid_.full())
         yield jid_elt
 
 
 class Params(object):
     """This class manage parameters with xml"""
+
     ### TODO: add desciption in params
 
-    #TODO: when priority is changed, a new presence stanza must be emitted
-    #TODO: int type (Priority should be int instead of string)
+    # TODO: when priority is changed, a new presence stanza must be emitted
+    # TODO: int type (Priority should be int instead of string)
     default_xml = u"""
     <params>
     <general>
@@ -77,23 +79,23 @@
     </individual>
     </params>
     """ % {
-        'category_general': D_("General"),
-        'category_connection': D_("Connection"),
-        'history_param': C.HISTORY_LIMIT,
-        'history_label': D_('Chat history limit'),
-        'show_offline_contacts': C.SHOW_OFFLINE_CONTACTS,
-        'show_offline_contacts_label': D_('Show offline contacts'),
-        'show_empty_groups': C.SHOW_EMPTY_GROUPS,
-        'show_empty_groups_label': D_('Show empty groups'),
-        'force_server_param': C.FORCE_SERVER_PARAM,
-        'force_port_param': C.FORCE_PORT_PARAM,
-        'new_account_label': D_("Register new account"),
-        'autoconnect_label': D_('Connect on frontend startup'),
-        'autodisconnect_label': D_('Disconnect on frontend closure'),
+        "category_general": D_("General"),
+        "category_connection": D_("Connection"),
+        "history_param": C.HISTORY_LIMIT,
+        "history_label": D_("Chat history limit"),
+        "show_offline_contacts": C.SHOW_OFFLINE_CONTACTS,
+        "show_offline_contacts_label": D_("Show offline contacts"),
+        "show_empty_groups": C.SHOW_EMPTY_GROUPS,
+        "show_empty_groups_label": D_("Show empty groups"),
+        "force_server_param": C.FORCE_SERVER_PARAM,
+        "force_port_param": C.FORCE_PORT_PARAM,
+        "new_account_label": D_("Register new account"),
+        "autoconnect_label": D_("Connect on frontend startup"),
+        "autodisconnect_label": D_("Disconnect on frontend closure"),
     }
 
     def load_default_params(self):
-        self.dom = minidom.parseString(Params.default_xml.encode('utf-8'))
+        self.dom = minidom.parseString(Params.default_xml.encode("utf-8"))
 
     def _mergeParams(self, source_node, dest_node):
         """Look for every node in source_node and recursively copy them to dest if they don't exists"""
@@ -102,8 +104,9 @@
             ret = {}
             for child in children:
                 if child.nodeType == child.ELEMENT_NODE:
-                    ret[(child.tagName, child.getAttribute('name'))] = child
+                    ret[(child.tagName, child.getAttribute("name"))] = child
             return ret
+
         source_map = getNodesMap(source_node.childNodes)
         dest_map = getNodesMap(dest_node.childNodes)
         source_set = set(source_map.keys())
@@ -120,7 +123,7 @@
     def load_xml(self, xml_file):
         """Load parameters template from xml file"""
         self.dom = minidom.parse(xml_file)
-        default_dom = minidom.parseString(Params.default_xml.encode('utf-8'))
+        default_dom = minidom.parseString(Params.default_xml.encode("utf-8"))
         self._mergeParams(default_dom.documentElement, self.dom.documentElement)
 
     def loadGenParams(self):
@@ -140,7 +143,9 @@
         """
         if cache is None:
             self.params[profile] = {}
-        return self.storage.loadIndParams(self.params[profile] if cache is None else cache, 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
@@ -150,12 +155,14 @@
         try:
             del self.params[profile]
         except KeyError:
-            log.error(_(u"Trying to purge cache of a profile not in memory: [%s]") % profile)
+            log.error(
+                _(u"Trying to purge cache of a profile not in memory: [%s]") % profile
+            )
 
     def save_xml(self, filename):
         """Save parameters template to xml file"""
-        with open(filename, 'wb') as xml_file:
-            xml_file.write(self.dom.toxml('utf-8'))
+        with open(filename, "wb") as xml_file:
+            xml_file.write(self.dom.toxml("utf-8"))
 
     def __init__(self, host, storage):
         log.debug("Parameters init")
@@ -174,7 +181,7 @@
         @return: a Deferred instance
         """
         if self.storage.hasProfile(profile):
-            log.info(_('The profile name already exists'))
+            log.info(_("The profile name already exists"))
             return defer.fail(Failure(exceptions.ConflictError))
         if not self.host.trigger.point("ProfileCreation", profile):
             return defer.fail(Failure(exceptions.CancelError))
@@ -189,7 +196,7 @@
         @return: a Deferred instance
         """
         if not self.storage.hasProfile(profile):
-            log.info(_('Trying to delete an unknown profile'))
+            log.info(_("Trying to delete an unknown profile"))
             return defer.fail(Failure(exceptions.ProfileUnknownError(profile)))
         if self.host.isConnected(profile):
             if force:
@@ -210,22 +217,26 @@
         @raise exceptions.ProfileUnknownError: profile doesn't exists
         @raise exceptions.ProfileNotSetError: if C.PROF_KEY_NONE is used
         """
-        if profile_key == '@DEFAULT@':
-            default = self.host.memory.memory_data.get('Profile_default')
+        if profile_key == "@DEFAULT@":
+            default = self.host.memory.memory_data.get("Profile_default")
             if not default:
-                log.info(_('No default profile, returning first one'))
+                log.info(_("No default profile, returning first one"))
                 try:
-                    default = self.host.memory.memory_data['Profile_default'] = self.storage.getProfilesList()[0]
+                    default = self.host.memory.memory_data[
+                        "Profile_default"
+                    ] = self.storage.getProfilesList()[0]
                 except IndexError:
-                    log.info(_('No profile exist yet'))
+                    log.info(_("No profile exist yet"))
                     raise exceptions.ProfileUnknownError(profile_key)
-            return default  # FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists
+            return (
+                default
+            )  # FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists
         elif profile_key == C.PROF_KEY_NONE:
             raise exceptions.ProfileNotSetError
         elif return_profile_keys and profile_key in [C.PROF_KEY_ALL]:
-            return profile_key # this value must be managed by the caller
+            return profile_key  # this value must be managed by the caller
         if not self.storage.hasProfile(profile_key):
-            log.error(_(u'Trying to access an unknown profile (%s)') % profile_key)
+            log.error(_(u"Trying to access an unknown profile (%s)") % profile_key)
             raise exceptions.ProfileUnknownError(profile_key)
         return profile_key
 
@@ -239,12 +250,12 @@
         """
         for node in parent.childNodes:
             if node.nodeName == tag and node.getAttribute("name") == name:
-                #the node already exists
+                # the node already exists
                 return node
-        #the node is new
+        # the node is new
         return None
 
-    def updateParams(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=''):
+    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
@@ -254,7 +265,7 @@
         @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
+        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"""
@@ -264,17 +275,23 @@
                     to_remove.append(type_node)  # accept individual parameters only
                     continue
                 for cat_node in type_node.childNodes:
-                    if cat_node.nodeName != 'category':
+                    if cat_node.nodeName != "category":
                         to_remove.append(cat_node)
                         continue
-                    to_remove_count = 0  # count the params to be removed from current category
+                    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):
+                        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
+                        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)
@@ -283,9 +300,11 @@
 
         def import_node(tgt_parent, src_parent):
             for child in src_parent.childNodes:
-                if child.nodeName == '#text':
+                if child.nodeName == "#text":
                     continue
-                node = self.__get_unique_node(tgt_parent, child.nodeName, child.getAttribute("name"))
+                node = self.__get_unique_node(
+                    tgt_parent, child.nodeName, child.getAttribute("name")
+                )
                 if not node:  # The node is new
                     tgt_parent.appendChild(child.cloneNode(True))
                 else:
@@ -310,23 +329,35 @@
         @param app: name of the frontend registering the parameters
         """
         if not app:
-            log.warning(_(u"Trying to register frontends parameters with no specified app: aborted"))
+            log.warning(
+                _(
+                    u"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:
-            log.debug(_(u"Trying to register twice frontends parameters for %(app)s: aborted" % {"app": app}))
+            log.debug(
+                _(
+                    u"Trying to register twice frontends parameters for %(app)s: aborted"
+                    % {"app": app}
+                )
+            )
             return
         self.frontends_cache.append(app)
         self.updateParams(xml, security_limit, app)
-        log.debug(u"Frontends parameters registered for %(app)s" % {'app': app})
+        log.debug(u"Frontends parameters registered for %(app)s" % {"app": app})
 
     def __default_ok(self, value, name, category):
-        #FIXME: will not work with individual parameters
+        # FIXME: will not work with individual parameters
         self.setParam(name, value, category)
 
     def __default_ko(self, failure, name, category):
-        log.error(_(u"Can't determine default value for [%(category)s/%(name)s]: %(reason)s") % {'category': category, 'name': name, 'reason': str(failure.value)})
+        log.error(
+            _(u"Can't determine default value for [%(category)s/%(name)s]: %(reason)s")
+            % {"category": category, "name": name, "reason": str(failure.value)}
+        )
 
     def setDefault(self, name, category, callback, errback=None):
         """Set default value of parameter
@@ -337,19 +368,27 @@
         @param callback: must return a string with the value (use deferred if needed)
         @param errback: must manage the error with args failure, name, category
         """
-        #TODO: send signal param update if value changed
-        #TODO: manage individual paramaters
-        log.debug ("setDefault called for %(category)s/%(name)s" % {"category": category, "name": name})
-        node = self._getParamNode(name, category, '@ALL@')
+        # TODO: send signal param update if value changed
+        # TODO: manage individual paramaters
+        log.debug(
+            "setDefault called for %(category)s/%(name)s"
+            % {"category": category, "name": name}
+        )
+        node = self._getParamNode(name, category, "@ALL@")
         if not node:
-            log.error(_(u"Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category})
+            log.error(
+                _(
+                    u"Requested param [%(name)s] in category [%(category)s] doesn't exist !"
+                )
+                % {"name": name, "category": category}
+            )
             return
-        if node[1].getAttribute('default_cb') == 'yes':
+        if node[1].getAttribute("default_cb") == "yes":
             # del node[1].attributes['default_cb'] # default_cb is not used anymore as a flag to know if we have to set the default value,
-                                                   # and we can still use it later e.g. to call a generic setDefault method
+            # and we can still use it later e.g. to call a generic setDefault method
             value = self._getParam(category, name, C.GENERAL)
-            if value is None: # no value set by the user: we have the default value
-                log.debug ("Default value to set, using callback")
+            if value is None:  # no value set by the user: we have the default value
+                log.debug("Default value to set, using callback")
                 d = defer.maybeDeferred(callback)
                 d.addCallback(self.__default_ok, name, category)
                 d.addErrback(errback or self.__default_ko, name, category)
@@ -364,30 +403,61 @@
         @param value: user defined value
         @return: value (can be str, bool, int, list, None)
         """
-        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':
+        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 C.bool(value_to_use)
-            if node.getAttribute('type') == 'int':
+            if node.getAttribute("type") == "int":
                 return int(value_to_use)
-            elif node.getAttribute('type') == 'list':
-                if not value_to_use:  # no user defined value, take default value from the XML
-                    options = [option for option in node.childNodes if option.nodeName == 'option']
-                    selected = [option for option in options if option.getAttribute('selected') == 'true']
-                    cat, param = node.parentNode.getAttribute('name'), node.getAttribute('name')
+            elif node.getAttribute("type") == "list":
+                if (
+                    not value_to_use
+                ):  # no user defined value, take default value from the XML
+                    options = [
+                        option
+                        for option in node.childNodes
+                        if option.nodeName == "option"
+                    ]
+                    selected = [
+                        option
+                        for option in options
+                        if option.getAttribute("selected") == "true"
+                    ]
+                    cat, param = (
+                        node.parentNode.getAttribute("name"),
+                        node.getAttribute("name"),
+                    )
                     if len(selected) == 1:
-                        value_to_use = selected[0].getAttribute('value')
-                        log.info(_("Unset parameter (%(cat)s, %(param)s) of type list will use the default option '%(value)s'") %
-                                 {'cat': cat, 'param': param, 'value': value_to_use})
+                        value_to_use = selected[0].getAttribute("value")
+                        log.info(
+                            _(
+                                "Unset parameter (%(cat)s, %(param)s) of type list will use the default option '%(value)s'"
+                            )
+                            % {"cat": cat, "param": param, "value": value_to_use}
+                        )
                         return value_to_use
                     if len(selected) == 0:
-                        log.error(_(u'Parameter (%(cat)s, %(param)s) of type list has no default option!') % {'cat': cat, 'param': param})
+                        log.error(
+                            _(
+                                u"Parameter (%(cat)s, %(param)s) of type list has no default option!"
+                            )
+                            % {"cat": cat, "param": param}
+                        )
                     else:
-                        log.error(_(u'Parameter (%(cat)s, %(param)s) of type list has more than one default option!') % {'cat': cat, 'param': param})
+                        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':
+            elif node.getAttribute("type") == "jids_list":
                 if value_to_use:
-                    jids = value_to_use.split('\t')  # FIXME: it's not good to use tabs as separator !
+                    jids = value_to_use.split(
+                        "\t"
+                    )  # FIXME: it's not good to use tabs as separator !
                 else:  # no user defined value, take default value from the XML
                     jids = [getText(jid_) for jid_ in node.getElementsByTagName("jid")]
                 to_delete = []
@@ -395,7 +465,9 @@
                     try:
                         jids[idx] = jid.JID(value)
                     except (RuntimeError, jid.InvalidFormat, AttributeError):
-                        log.warning(u"Incorrect jid value found in jids list: [{}]".format(value))
+                        log.warning(
+                            u"Incorrect jid value found in jids list: [{}]".format(value)
+                        )
                         to_delete.append(value)
                 for value in to_delete:
                     jids.remove(value)
@@ -412,8 +484,10 @@
         @param value: user defined value
         @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')
+        if attr == "value" and node.getAttribute("type") == "password":
+            raise exceptions.InternalError(
+                "To retrieve password values, use _asyncGetAttr instead of _getAttr"
+            )
         return self._getAttr_internal(node, attr, value)
 
     def _asyncGetAttr(self, node, attr, value, profile=None):
@@ -428,19 +502,27 @@
         @return (unicode, bool, int, list): Deferred value to retrieve
         """
         value = self._getAttr_internal(node, attr, value)
-        if attr != 'value' or node.getAttribute('type') != 'password':
+        if attr != "value" or node.getAttribute("type") != "password":
             return defer.succeed(value)
-        param_cat = node.parentNode.getAttribute('name')
-        param_name = node.getAttribute('name')
+        param_cat = node.parentNode.getAttribute("name")
+        param_name = node.getAttribute("name")
         if ((param_cat, param_name) == C.PROFILE_PASS_PATH) or not value:
-            return defer.succeed(value)  # profile password and empty passwords are returned "as is"
+            return defer.succeed(
+                value
+            )  # profile password and empty passwords are returned "as is"
         if not profile:
-            raise exceptions.ProfileNotSetError('The profile is needed to decrypt a password')
+            raise exceptions.ProfileNotSetError(
+                "The profile is needed to decrypt a password"
+            )
         d = self.host.memory.decryptValue(value, profile)
 
         def gotPlainPassword(password):
-            if password is None:  # empty value means empty password, None means decryption failure
-                raise exceptions.InternalError(_('The stored password could not be decrypted!'))
+            if (
+                password is None
+            ):  # empty value means empty password, None means decryption failure
+                raise exceptions.InternalError(
+                    _("The stored password could not be decrypted!")
+                )
             return password
 
         return d.addCallback(gotPlainPassword)
@@ -455,9 +537,13 @@
 
     def getStringParamA(self, name, category, attr="value", profile_key=C.PROF_KEY_NONE):
         """ Same as getParamA but for bridge: convert non string value to string """
-        return self.__type_to_string(self.getParamA(name, category, attr, profile_key=profile_key))
+        return self.__type_to_string(
+            self.getParamA(name, category, attr, profile_key=profile_key)
+        )
 
-    def getParamA(self, name, category, attr="value", use_default=True, profile_key=C.PROF_KEY_NONE):
+    def getParamA(
+        self, name, category, attr="value", use_default=True, profile_key=C.PROF_KEY_NONE
+    ):
         """Helper method to get a specific attribute.
 
         /!\ This method would return encrypted password values,
@@ -474,15 +560,22 @@
         # FIXME: security_limit is not managed here !
         node = self._getParamNode(name, category)
         if not node:
-            log.error(_(u"Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category})
+            log.error(
+                _(
+                    u"Requested param [%(name)s] in category [%(category)s] doesn't exist !"
+                )
+                % {"name": name, "category": category}
+            )
             raise exceptions.NotFound
 
-        if attr == 'value' and node[1].getAttribute('type') == 'password':
-            raise exceptions.InternalError('To retrieve password values, use asyncGetParamA instead of getParamA')
+        if attr == "value" and node[1].getAttribute("type") == "password":
+            raise exceptions.InternalError(
+                "To retrieve password values, use asyncGetParamA instead of getParamA"
+            )
 
         if node[0] == C.GENERAL:
             value = self._getParam(category, name, C.GENERAL)
-            if value is None and attr=='value' and not use_default:
+            if value is None and attr == "value" and not use_default:
                 return value
             return self._getAttr(node[1], attr, value)
 
@@ -490,25 +583,39 @@
 
         profile = self.getProfileName(profile_key)
         if not profile:
-            log.error(_('Requesting a param for an non-existant profile'))
+            log.error(_("Requesting a param for an non-existant profile"))
             raise exceptions.ProfileUnknownError(profile_key)
 
         if profile not in self.params:
-            log.error(_('Requesting synchronous param for not connected profile'))
+            log.error(_("Requesting synchronous param for not connected profile"))
             raise exceptions.ProfileNotConnected(profile)
 
         if attr == "value":
             value = self._getParam(category, name, profile=profile)
-            if value is None and attr=='value' and not use_default:
+            if value is None and attr == "value" and not use_default:
                 return value
             return self._getAttr(node[1], attr, value)
 
-    def asyncGetStringParamA(self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE):
+    def asyncGetStringParamA(
+        self,
+        name,
+        category,
+        attr="value",
+        security_limit=C.NO_SECURITY_LIMIT,
+        profile_key=C.PROF_KEY_NONE,
+    ):
         d = self.asyncGetParamA(name, category, attr, security_limit, profile_key)
         d.addCallback(self.__type_to_string)
         return d
 
-    def asyncGetParamA(self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE):
+    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
@@ -519,12 +626,21 @@
         """
         node = self._getParamNode(name, category)
         if not node:
-            log.error(_(u"Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category})
+            log.error(
+                _(
+                    u"Requested param [%(name)s] in category [%(category)s] doesn't exist !"
+                )
+                % {"name": name, "category": category}
+            )
             raise ValueError("Requested param doesn't exist")
 
         if not self.checkSecurityLimit(node[1], security_limit):
-            log.warning(_(u"Trying to get parameter '%(param)s' in category '%(cat)s' without authorization!!!"
-                      % {'param': name, 'cat': category}))
+            log.warning(
+                _(
+                    u"Trying to get parameter '%(param)s' in category '%(cat)s' without authorization!!!"
+                    % {"param": name, "cat": category}
+                )
+            )
             raise exceptions.PermissionError
 
         if node[0] == C.GENERAL:
@@ -535,7 +651,9 @@
 
         profile = self.getProfileName(profile_key)
         if not profile:
-            raise exceptions.InternalError(_('Requesting a param for a non-existant profile'))
+            raise exceptions.InternalError(
+                _("Requesting a param for a non-existant profile")
+            )
 
         if attr != "value":
             return defer.succeed(node[1].getAttribute(attr))
@@ -543,9 +661,11 @@
             value = self._getParam(category, name, profile=profile)
             return self._asyncGetAttr(node[1], attr, value, profile)
         except exceptions.ProfileNotInCacheError:
-            #We have to ask data to the storage manager
+            # We have to ask data to the storage manager
             d = self.storage.getIndParam(category, name, profile)
-            return d.addCallback(lambda value: self._asyncGetAttr(node[1], attr, value, profile))
+            return d.addCallback(
+                lambda value: self._asyncGetAttr(node[1], attr, value, profile)
+            )
 
     def asyncGetParamsValuesFromCategory(self, category, security_limit, profile_key):
         """Get all parameters "attribute" for a category
@@ -557,7 +677,7 @@
         @param profile_key: %(doc_profile_key)s
         @return (dict): key: param name, value: param value (converted to string if needed)
         """
-        #TODO: manage category of general type (without existant profile)
+        # TODO: manage category of general type (without existant profile)
         profile = self.getProfileName(profile_key)
         if not profile:
             log.error(_("Asking params for inexistant profile"))
@@ -572,11 +692,20 @@
             for category_node in prof_xml.getElementsByTagName("category"):
                 if category_node.getAttribute("name") == category:
                     for param_node in category_node.getElementsByTagName("param"):
-                        name = param_node.getAttribute('name')
+                        name = param_node.getAttribute("name")
                         if not name:
-                            log.warning(u"ignoring attribute without name: {}".format(param_node.toxml()))
+                            log.warning(
+                                u"ignoring attribute without name: {}".format(
+                                    param_node.toxml()
+                                )
+                            )
                             continue
-                        d = self.asyncGetStringParamA(name, category, security_limit=security_limit, profile_key=profile)
+                        d = self.asyncGetStringParamA(
+                            name,
+                            category,
+                            security_limit=security_limit,
+                            profile_key=profile,
+                        )
                         d.addCallback(setValue, ret, name)
                         names_d_list.append(d)
                     break
@@ -586,10 +715,12 @@
             dlist.addCallback(lambda dummy: ret)
             return ret
 
-        d = self._constructProfileXml(security_limit, '', profile)
+        d = self._constructProfileXml(security_limit, "", profile)
         return d.addCallback(returnCategoryXml)
 
-    def _getParam(self, category, name, type_=C.INDIVIDUAL, cache=None, profile=C.PROF_KEY_NONE):
+    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
@@ -608,8 +739,10 @@
             raise exceptions.ProfileNotSetError
         if profile in self.params:
             cache = self.params[profile]  # if profile is in main cache, we use it,
-                                          # ignoring the temporary cache
-        elif cache is None:  # else we use the temporary cache if it exists, or raise an exception
+            # ignoring the temporary cache
+        elif (
+            cache is None
+        ):  # else we use the temporary cache if it exists, or raise an exception
             raise exceptions.ProfileNotInCacheError
         if (category, name) not in cache:
             return None
@@ -629,11 +762,13 @@
 
         def checkNode(node):
             """Check the node against security_limit and app"""
-            return self.checkSecurityLimit(node, security_limit) and self.checkApp(node, app)
+            return self.checkSecurityLimit(node, security_limit) and self.checkApp(
+                node, app
+            )
 
         def constructProfile(ignore, profile_cache):
             # init the result document
-            prof_xml = minidom.parseString('<params/>')
+            prof_xml = minidom.parseString("<params/>")
             cache = {}
 
             for type_node in self.dom.documentElement.childNodes:
@@ -641,9 +776,9 @@
                     continue
                 # we use all params, general and individual
                 for cat_node in type_node.childNodes:
-                    if cat_node.nodeName != 'category':
+                    if cat_node.nodeName != "category":
                         continue
-                    category = cat_node.getAttribute('name')
+                    category = cat_node.getAttribute("name")
                     dest_params = {}  # result (merged) params for category
                     if category not in cache:
                         # we make a copy for the new xml
@@ -655,7 +790,7 @@
                             if not checkNode(node):
                                 to_remove.append(node)
                                 continue
-                            dest_params[node.getAttribute('name')] = node
+                            dest_params[node.getAttribute("name")] = node
                         for node in to_remove:
                             dest_cat.removeChild(node)
                         new_node = True
@@ -668,7 +803,7 @@
                     for param_node in params:
                         # we have to merge new params (we are parsing individual parameters, we have to add them
                         # to the previously parsed general ones)
-                        name = param_node.getAttribute('name')
+                        name = param_node.getAttribute("name")
                         if not checkNode(param_node):
                             continue
                         if name not in dest_params:
@@ -676,35 +811,53 @@
                             dest_params[name] = param_node.cloneNode(True)
                             dest_cat.appendChild(dest_params[name])
 
-                        profile_value = self._getParam(category,
-                                                        name, type_node.nodeName,
-                                                        cache=profile_cache, profile=profile)
+                        profile_value = self._getParam(
+                            category,
+                            name,
+                            type_node.nodeName,
+                            cache=profile_cache,
+                            profile=profile,
+                        )
                         if profile_value is not None:
                             # there is a value for this profile, we must change the default
-                            if dest_params[name].getAttribute('type') == 'list':
-                                for option in dest_params[name].getElementsByTagName("option"):
-                                    if option.getAttribute('value') == profile_value:
-                                        option.setAttribute('selected', 'true')
+                            if dest_params[name].getAttribute("type") == "list":
+                                for option in dest_params[name].getElementsByTagName(
+                                    "option"
+                                ):
+                                    if option.getAttribute("value") == profile_value:
+                                        option.setAttribute("selected", "true")
                                     else:
                                         try:
-                                            option.removeAttribute('selected')
+                                            option.removeAttribute("selected")
                                         except NotFoundErr:
                                             pass
-                            elif dest_params[name].getAttribute('type') == 'jids_list':
-                                jids = profile_value.split('\t')
-                                for jid_elt in dest_params[name].getElementsByTagName("jid"):
-                                    dest_params[name].removeChild(jid_elt)  # remove all default
+                            elif dest_params[name].getAttribute("type") == "jids_list":
+                                jids = profile_value.split("\t")
+                                for jid_elt in dest_params[name].getElementsByTagName(
+                                    "jid"
+                                ):
+                                    dest_params[name].removeChild(
+                                        jid_elt
+                                    )  # remove all default
                                 for jid_ in jids:  # rebuilt the children with use values
                                     try:
                                         jid.JID(jid_)
-                                    except (RuntimeError, jid.InvalidFormat, AttributeError):
-                                        log.warning(u"Incorrect jid value found in jids list: [{}]".format(jid_))
+                                    except (
+                                        RuntimeError,
+                                        jid.InvalidFormat,
+                                        AttributeError,
+                                    ):
+                                        log.warning(
+                                            u"Incorrect jid value found in jids list: [{}]".format(
+                                                jid_
+                                            )
+                                        )
                                     else:
-                                        jid_elt = prof_xml.createElement('jid')
+                                        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)
+                                dest_params[name].setAttribute("value", profile_value)
                     if new_node:
                         prof_xml.documentElement.appendChild(dest_cat)
 
@@ -721,7 +874,7 @@
             d = defer.succeed(None)
             profile_cache = self.params[profile]
         else:
-            #profile is not in cache, we load values in a short time cache
+            # profile is not in cache, we load values in a short time cache
             profile_cache = {}
             d = self.loadIndParams(profile, profile_cache)
 
@@ -761,9 +914,11 @@
         def returnXML(prof_xml):
             return_xml = prof_xml.toxml()
             prof_xml.unlink()
-            return '\n'.join((line for line in return_xml.split('\n') if line))
+            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 _getParamNode(self, name, category, type_="@ALL@"):  # FIXME: is type_ useful ?
         """Return a node from the param_xml
@@ -776,9 +931,14 @@
         @return: a tuple (node type, node) or None if not found"""
 
         for type_node in self.dom.documentElement.childNodes:
-            if (((type_ == "@ALL@" or type_ == "@GENERAL@") and type_node.nodeName == C.GENERAL)
-                    or ((type_ == "@ALL@" or type_ == "@INDIVIDUAL@") and type_node.nodeName == C.INDIVIDUAL)):
-                for node in type_node.getElementsByTagName('category'):
+            if (
+                (type_ == "@ALL@" or type_ == "@GENERAL@")
+                and type_node.nodeName == C.GENERAL
+            ) or (
+                (type_ == "@ALL@" or type_ == "@INDIVIDUAL@")
+                and type_node.nodeName == C.INDIVIDUAL
+            ):
+                for node in type_node.getElementsByTagName("category"):
                     if node.getAttribute("name") == category:
                         params = node.getElementsByTagName("param")
                         for param in params:
@@ -795,7 +955,14 @@
                 categories.append(cat.getAttribute("name"))
         return categories
 
-    def setParam(self, name, value, category, security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE):
+    def setParam(
+        self,
+        name,
+        value,
+        category,
+        security_limit=C.NO_SECURITY_LIMIT,
+        profile_key=C.PROF_KEY_NONE,
+    ):
         """Set a parameter, return None if the parameter is not in param xml.
 
         Parameter of type 'password' that are not the SàT profile password are
@@ -813,42 +980,59 @@
         if profile_key != C.PROF_KEY_NONE:
             profile = self.getProfileName(profile_key)
             if not profile:
-                log.error(_(u'Trying to set parameter for an unknown profile'))
+                log.error(_(u"Trying to set parameter for an unknown profile"))
                 raise exceptions.ProfileUnknownError(profile_key)
 
-        node = self._getParamNode(name, category, '@ALL@')
+        node = self._getParamNode(name, category, "@ALL@")
         if not node:
-            log.error(_(u'Requesting an unknown parameter (%(category)s/%(name)s)')
-                      % {'category': category, 'name': name})
+            log.error(
+                _(u"Requesting an unknown parameter (%(category)s/%(name)s)")
+                % {"category": category, "name": name}
+            )
             return defer.succeed(None)
 
         if not self.checkSecurityLimit(node[1], security_limit):
-            log.warning(_(u"Trying to set parameter '%(param)s' in category '%(cat)s' without authorization!!!"
-                          % {'param': name, 'cat': category}))
+            log.warning(
+                _(
+                    u"Trying to set parameter '%(param)s' in category '%(cat)s' without authorization!!!"
+                    % {"param": name, "cat": category}
+                )
+            )
             return defer.succeed(None)
 
         type_ = node[1].getAttribute("type")
-        if type_ == 'int':
+        if type_ == "int":
             if not value:  # replace with the default value (which might also be '')
                 value = node[1].getAttribute("value")
             else:
                 try:
                     int(value)
                 except ValueError:
-                    log.debug(_(u"Trying to set parameter '%(param)s' in category '%(cat)s' with an non-integer value"
-                                % {'param': name, 'cat': category}))
+                    log.debug(
+                        _(
+                            u"Trying to set parameter '%(param)s' in category '%(cat)s' with an non-integer value"
+                            % {"param": name, "cat": category}
+                        )
+                    )
                     return defer.succeed(None)
                 if node[1].hasAttribute("constraint"):
                     constraint = node[1].getAttribute("constraint")
                     try:
                         min_, max_ = [int(limit) for limit in constraint.split(";")]
                     except ValueError:
-                        raise exceptions.InternalError("Invalid integer parameter constraint: %s" % constraint)
+                        raise exceptions.InternalError(
+                            "Invalid integer parameter constraint: %s" % constraint
+                        )
                     value = str(min(max(int(value), min_), max_))
 
-
-        log.info(_("Setting parameter (%(category)s, %(name)s) = %(value)s") %
-                 {'category': category, 'name': name, 'value': value if type_ != 'password' else '********'})
+        log.info(
+            _("Setting parameter (%(category)s, %(name)s) = %(value)s")
+            % {
+                "category": category,
+                "name": name,
+                "value": value if type_ != "password" else "********",
+            }
+        )
 
         if node[0] == C.GENERAL:
             self.params_gen[(category, name)] = value
@@ -856,7 +1040,9 @@
             for profile in self.storage.getProfilesList():
                 if self.host.memory.isSessionStarted(profile):
                     self.host.bridge.paramUpdate(name, value, category, profile)
-                    self.host.trigger.point("paramUpdateTrigger", name, value, category, node[0], profile)
+                    self.host.trigger.point(
+                        "paramUpdateTrigger", name, value, category, node[0], profile
+                    )
             return defer.succeed(None)
 
         assert node[0] == C.INDIVIDUAL
@@ -867,16 +1053,24 @@
             return defer.succeed(None)
         elif type_ == "password":
             try:
-                personal_key = self.host.memory.auth_sessions.profileGetUnique(profile)[C.MEMORY_CRYPTO_KEY]
+                personal_key = self.host.memory.auth_sessions.profileGetUnique(profile)[
+                    C.MEMORY_CRYPTO_KEY
+                ]
             except TypeError:
-                raise exceptions.InternalError(_('Trying to encrypt a password while the personal key is undefined!'))
+                raise exceptions.InternalError(
+                    _("Trying to encrypt a password while the personal key is undefined!")
+                )
             if (category, name) == C.PROFILE_PASS_PATH:
                 # using 'value' as the encryption key to encrypt another encryption key... could be confusing!
-                d = self.host.memory.encryptPersonalData(data_key=C.MEMORY_CRYPTO_KEY,
-                                                         data_value=personal_key,
-                                                         crypto_key=value,
-                                                         profile=profile)
-                d.addCallback(lambda dummy: PasswordHasher.hash(value))  # profile password is hashed (empty value stays empty)
+                d = self.host.memory.encryptPersonalData(
+                    data_key=C.MEMORY_CRYPTO_KEY,
+                    data_value=personal_key,
+                    crypto_key=value,
+                    profile=profile,
+                )
+                d.addCallback(
+                    lambda dummy: PasswordHasher.hash(value)
+                )  # profile password is hashed (empty value stays empty)
             elif value:  # other non empty passwords are encrypted with the personal key
                 d = BlockCipher.encrypt(personal_key, value)
             else:
@@ -888,7 +1082,9 @@
             if self.host.memory.isSessionStarted(profile):
                 self.params[profile][(category, name)] = value
                 self.host.bridge.paramUpdate(name, value, category, profile)
-                self.host.trigger.point("paramUpdateTrigger", name, value, category, node[0], profile)
+                self.host.trigger.point(
+                    "paramUpdateTrigger", name, value, category, node[0], profile
+                )
                 return self.storage.setIndParam(category, name, value, profile)
             else:
                 raise exceptions.ProfileNotConnected
@@ -912,10 +1108,15 @@
         """
         ret = {}
         for type_node in self.dom.documentElement.childNodes:
-            if (((node_type == "@ALL@" or node_type == "@GENERAL@") and type_node.nodeName == C.GENERAL) or
-                ((node_type == "@ALL@" or node_type == "@INDIVIDUAL@") and type_node.nodeName == C.INDIVIDUAL)):
-                for cat_node in type_node.getElementsByTagName('category'):
-                    cat = cat_node.getAttribute('name')
+            if (
+                (node_type == "@ALL@" or node_type == "@GENERAL@")
+                and type_node.nodeName == C.GENERAL
+            ) or (
+                (node_type == "@ALL@" or node_type == "@INDIVIDUAL@")
+                and type_node.nodeName == C.INDIVIDUAL
+            ):
+                for cat_node in type_node.getElementsByTagName("category"):
+                    cat = cat_node.getAttribute("name")
                     params = cat_node.getElementsByTagName("param")
                     for param in params:
                         if param.getAttribute("type") == attr_type: