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

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 9446f1ea9eac
children 5060cbeec01e
line wrap: on
line diff
--- a/sat/memory/memory.py	Wed Jun 27 07:51:29 2018 +0200
+++ b/sat/memory/memory.py	Wed Jun 27 20:14:46 2018 +0200
@@ -20,6 +20,7 @@
 from sat.core.i18n import _
 
 from sat.core.log import getLogger
+
 log = getLogger(__name__)
 
 import os.path
@@ -44,11 +45,13 @@
 import time
 
 
-PresenceTuple = namedtuple("PresenceTuple", ('show', 'priority', 'statuses'))
+PresenceTuple = namedtuple("PresenceTuple", ("show", "priority", "statuses"))
 MSG_NO_SESSION = "Session id doesn't exist or is finished"
 
+
 class Sessions(object):
     """Sessions are data associated to key used for a temporary moment, with optional profile checking."""
+
     DEFAULT_TIMEOUT = 600
 
     def __init__(self, timeout=None, resettable_timeout=True):
@@ -72,11 +75,15 @@
         if session_id is None:
             session_id = str(uuid4())
         elif session_id in self._sessions:
-            raise exceptions.ConflictError(u"Session id {} is already used".format(session_id))
+            raise exceptions.ConflictError(
+                u"Session id {} is already used".format(session_id)
+            )
         timer = reactor.callLater(self.timeout, self._purgeSession, session_id)
         if session_data is None:
             session_data = {}
-        self._sessions[session_id] = (timer, session_data) if profile is None else (timer, session_data, profile)
+        self._sessions[session_id] = (
+            (timer, session_data) if profile is None else (timer, session_data, profile)
+        )
         return session_id, session_data
 
     def _purgeSession(self, session_id):
@@ -91,7 +98,12 @@
             # if the session is time-outed, the timer has been called
             pass
         del self._sessions[session_id]
-        log.debug(u"Session {} purged{}".format(session_id, u' (profile {})'.format(profile) if profile is not None else u''))
+        log.debug(
+            u"Session {} purged{}".format(
+                session_id,
+                u" (profile {})".format(profile) if profile is not None else u"",
+            )
+        )
 
     def __len__(self):
         return len(self._sessions)
@@ -103,7 +115,9 @@
         try:
             timer, session_data, profile_set = self._sessions[session_id]
         except ValueError:
-            raise exceptions.InternalError("You need to use __getitem__ when profile is not set")
+            raise exceptions.InternalError(
+                "You need to use __getitem__ when profile is not set"
+            )
         except KeyError:
             raise failure.Failure(KeyError(MSG_NO_SESSION))
         if profile_set != profile:
@@ -116,7 +130,9 @@
         try:
             timer, session_data = self._sessions[session_id]
         except ValueError:
-            raise exceptions.InternalError("You need to use profileGet instead of __getitem__ when profile is set")
+            raise exceptions.InternalError(
+                "You need to use profileGet instead of __getitem__ when profile is set"
+            )
         except KeyError:
             raise failure.Failure(KeyError(MSG_NO_SESSION))
         if self.resettable_timeout:
@@ -169,8 +185,12 @@
         """
         ids = self._profileGetAllIds(profile)
         if len(ids) > 1:
-            raise exceptions.InternalError('profileGetUnique has been used but more than one session has been found!')
-        return self.profileGet(ids[0], profile) if len(ids) == 1 else None  # XXX: timeout might be reset
+            raise exceptions.InternalError(
+                "profileGetUnique has been used but more than one session has been found!"
+            )
+        return (
+            self.profileGet(ids[0], profile) if len(ids) == 1 else None
+        )  # XXX: timeout might be reset
 
     def profileDelUnique(self, profile):
         """Delete the unique session that is associated to the given profile.
@@ -180,7 +200,9 @@
         """
         ids = self._profileGetAllIds(profile)
         if len(ids) > 1:
-            raise exceptions.InternalError('profileDelUnique has been used but more than one session has been found!')
+            raise exceptions.InternalError(
+                "profileDelUnique has been used but more than one session has been found!"
+            )
         if len(ids) == 1:
             del self._sessions[ids[0]]
 
@@ -194,7 +216,9 @@
         ProfileSessions.__init__(self, timeout, resettable_timeout=False)
 
     def _purgeSession(self, session_id):
-        log.debug("FIXME: PasswordSessions should ask for the profile password after the session expired")
+        log.debug(
+            "FIXME: PasswordSessions should ask for the profile password after the session expired"
+        )
 
 
 # XXX: tmp update code, will be removed in the future
@@ -211,16 +235,20 @@
     except:
         pass  # file is readable but its structure if wrong
     try:
-        current_value = user_config.get('DEFAULT', 'local_dir')
+        current_value = user_config.get("DEFAULT", "local_dir")
     except (NoOptionError, NoSectionError):
-        current_value = ''
+        current_value = ""
     if current_value:
         return  # nothing to do
-    old_default = '~/.sat'
-    if os.path.isfile(os.path.expanduser(old_default) + '/' + C.SAVEFILE_DATABASE):
+    old_default = "~/.sat"
+    if os.path.isfile(os.path.expanduser(old_default) + "/" + C.SAVEFILE_DATABASE):
         if not silent:
-            log.warning(_(u"A database has been found in the default local_dir for previous versions (< 0.5)"))
-        tools_config.fixConfigOption('', 'local_dir', old_default, silent)
+            log.warning(
+                _(
+                    u"A database has been found in the default local_dir for previous versions (< 0.5)"
+                )
+            )
+        tools_config.fixConfigOption("", "local_dir", old_default, silent)
 
 
 class Memory(object):
@@ -230,17 +258,19 @@
         log.info(_("Memory manager init"))
         self.initialized = defer.Deferred()
         self.host = host
-        self._entities_cache = {} # XXX: keep presence/last resource/other data in cache
-                                  #     /!\ an entity is not necessarily in roster
-                                  #     main key is bare jid, value is a dict
-                                  #     where main key is resource, or None for bare jid
-        self._key_signals = set() # key which need a signal to frontends when updated
+        self._entities_cache = {}  # XXX: keep presence/last resource/other data in cache
+        #     /!\ an entity is not necessarily in roster
+        #     main key is bare jid, value is a dict
+        #     where main key is resource, or None for bare jid
+        self._key_signals = set()  # key which need a signal to frontends when updated
         self.subscriptions = {}
         self.auth_sessions = PasswordSessions()  # remember the authenticated profiles
         self.disco = Discovery(host)
         fixLocalDir(False)  # XXX: tmp update code, will be removed in the future
         self.config = tools_config.parseMainConf()
-        database_file = os.path.expanduser(os.path.join(self.getConfig('', 'local_dir'), C.SAVEFILE_DATABASE))
+        database_file = os.path.expanduser(
+            os.path.join(self.getConfig("", "local_dir"), C.SAVEFILE_DATABASE)
+        )
         self.storage = SqliteStorage(database_file, host.version)
         PersistentDict.storage = self.storage
         self.params = Params(host, self.storage)
@@ -290,7 +320,7 @@
         """
         if not filename:
             return False
-        #TODO: need to encrypt files (at least passwords !) and set permissions
+        # TODO: need to encrypt files (at least passwords !) and set permissions
         filename = os.path.expanduser(filename)
         try:
             self.params.save_xml(filename)
@@ -302,7 +332,7 @@
 
     def load(self):
         """Load parameters and all memory things from db"""
-        #parameters data
+        # parameters data
         return self.params.loadGenParams()
 
     def loadIndividualParams(self, profile):
@@ -340,7 +370,9 @@
                     session_d = self._entities_cache[profile]
                 except KeyError:
                     # else we do request the params
-                    session_d = self._entities_cache[profile] = self.loadIndividualParams(profile)
+                    session_d = self._entities_cache[profile] = self.loadIndividualParams(
+                        profile
+                    )
                     session_d.addCallback(createSession)
                 finally:
                     return session_d
@@ -396,12 +428,20 @@
 
         def check_result(result):
             if not result:
-                log.warning(u'Authentication failure of profile {}'.format(profile))
-                raise failure.Failure(exceptions.PasswordError(u"The provided profile password doesn't match."))
-            if not session_data:  # avoid to create two profile sessions when password if specified
+                log.warning(u"Authentication failure of profile {}".format(profile))
+                raise failure.Failure(
+                    exceptions.PasswordError(
+                        u"The provided profile password doesn't match."
+                    )
+                )
+            if (
+                not session_data
+            ):  # avoid to create two profile sessions when password if specified
                 return self.newAuthSession(password, profile)
 
-        d = self.asyncGetParamA(C.PROFILE_PASS_PATH[1], C.PROFILE_PASS_PATH[0], profile_key=profile)
+        d = self.asyncGetParamA(
+            C.PROFILE_PASS_PATH[1], C.PROFILE_PASS_PATH[0], profile_key=profile
+        )
         d.addCallback(lambda sat_cipher: PasswordHasher.verify(password, sat_cipher))
         return d.addCallback(check_result)
 
@@ -414,10 +454,13 @@
         @param profile: %(doc_profile)s
         @return: a deferred None value
         """
+
         def gotPersonalKey(personal_key):
             """Create the session for this profile and store the personal key"""
-            self.auth_sessions.newSession({C.MEMORY_CRYPTO_KEY: personal_key}, profile=profile)
-            log.debug(u'auth session created for profile %s' % profile)
+            self.auth_sessions.newSession(
+                {C.MEMORY_CRYPTO_KEY: personal_key}, profile=profile
+            )
+            log.debug(u"auth session created for profile %s" % profile)
 
         d = PersistentDict(C.MEMORY_CRYPTO_NAMESPACE, profile).load()
         d.addCallback(lambda data: BlockCipher.decrypt(key, data[C.MEMORY_CRYPTO_KEY]))
@@ -431,7 +474,12 @@
         try:
             del self._entities_cache[profile]
         except KeyError:
-            log.error(_(u"Trying to purge roster status cache for a profile not in memory: [%s]") % profile)
+            log.error(
+                _(
+                    u"Trying to purge roster status cache for a profile not in memory: [%s]"
+                )
+                % profile
+            )
 
     def getProfilesList(self, clients=True, components=False):
         """retrieve profiles list
@@ -472,7 +520,7 @@
         # we want to be sure that the profile exists
         profile = self.getProfileName(profile)
 
-        self.memory_data['Profile_default'] = profile
+        self.memory_data["Profile_default"] = profile
 
     def createProfile(self, name, password, component=None):
         """Create a new profile
@@ -486,9 +534,9 @@
         """
         if not name:
             raise ValueError(u"Empty profile name")
-        if name[0] == '@':
+        if name[0] == "@":
             raise ValueError(u"A profile name can't start with a '@'")
-        if '\n' in name:
+        if "\n" in name:
             raise ValueError(u"A profile name can't contain line feed ('\\n')")
 
         if name in self._entities_cache:
@@ -496,19 +544,28 @@
 
         if component:
             if not component in self.host.plugins:
-                raise exceptions.NotFound(_(u"Can't find component {component} entry point".format(
-                    component = component)))
+                raise exceptions.NotFound(
+                    _(
+                        u"Can't find component {component} entry point".format(
+                            component=component
+                        )
+                    )
+                )
             # FIXME: PLUGIN_INFO is not currently accessible after import, but type shoul be tested here
-            # if self.host.plugins[component].PLUGIN_INFO[u"type"] != C.PLUG_TYPE_ENTRY_POINT:
-            #     raise ValueError(_(u"Plugin {component} is not an entry point !".format(
-            #         component = component)))
+            #  if self.host.plugins[component].PLUGIN_INFO[u"type"] != C.PLUG_TYPE_ENTRY_POINT:
+            #      raise ValueError(_(u"Plugin {component} is not an entry point !".format(
+            #          component = component)))
 
         d = self.params.createProfile(name, component)
 
         def initPersonalKey(dummy):
             # be sure to call this after checking that the profile doesn't exist yet
-            personal_key = BlockCipher.getRandomKey(base64=True)  # generated once for all and saved in a PersistentDict
-            self.auth_sessions.newSession({C.MEMORY_CRYPTO_KEY: personal_key}, profile=name)  # will be encrypted by setParam
+            personal_key = BlockCipher.getRandomKey(
+                base64=True
+            )  # generated once for all and saved in a PersistentDict
+            self.auth_sessions.newSession(
+                {C.MEMORY_CRYPTO_KEY: personal_key}, profile=name
+            )  # will be encrypted by setParam
 
         def startFakeSession(dummy):
             # avoid ProfileNotConnected exception in setParam
@@ -521,7 +578,11 @@
 
         d.addCallback(initPersonalKey)
         d.addCallback(startFakeSession)
-        d.addCallback(lambda dummy: self.setParam(C.PROFILE_PASS_PATH[1], password, C.PROFILE_PASS_PATH[0], profile_key=name))
+        d.addCallback(
+            lambda dummy: self.setParam(
+                C.PROFILE_PASS_PATH[1], password, C.PROFILE_PASS_PATH[0], profile_key=name
+            )
+        )
         d.addCallback(stopFakeSession)
         d.addCallback(lambda dummy: self.auth_sessions.profileDelUnique(name))
         return d
@@ -534,12 +595,14 @@
         To be used for direct calls only (not through the bridge).
         @return: a Deferred instance
         """
+
         def cleanMemory(dummy):
             self.auth_sessions.profileDelUnique(name)
             try:
                 del self._entities_cache[name]
             except KeyError:
                 pass
+
         d = self.params.asyncDeleteProfile(name, force)
         d.addCallback(cleanMemory)
         return d
@@ -567,10 +630,28 @@
     def addToHistory(self, client, data):
         return self.storage.addToHistory(data, client.profile)
 
-    def _historyGet(self, from_jid_s, to_jid_s, limit=C.HISTORY_LIMIT_NONE, between=True, filters=None, profile=C.PROF_KEY_NONE):
-        return self.historyGet(jid.JID(from_jid_s), jid.JID(to_jid_s), limit, between, filters, profile)
+    def _historyGet(
+        self,
+        from_jid_s,
+        to_jid_s,
+        limit=C.HISTORY_LIMIT_NONE,
+        between=True,
+        filters=None,
+        profile=C.PROF_KEY_NONE,
+    ):
+        return self.historyGet(
+            jid.JID(from_jid_s), jid.JID(to_jid_s), limit, between, filters, profile
+        )
 
-    def historyGet(self, from_jid, to_jid, limit=C.HISTORY_LIMIT_NONE, between=True, filters=None, profile=C.PROF_KEY_NONE):
+    def historyGet(
+        self,
+        from_jid,
+        to_jid,
+        limit=C.HISTORY_LIMIT_NONE,
+        between=True,
+        filters=None,
+        profile=C.PROF_KEY_NONE,
+    ):
         """Retrieve messages in history
 
         @param from_jid (JID): source JID (full, or bare for catchall)
@@ -586,7 +667,7 @@
         """
         assert profile != C.PROF_KEY_NONE
         if limit == C.HISTORY_LIMIT_DEFAULT:
-            limit = int(self.getParamA(C.HISTORY_LIMIT, 'General', profile_key=profile))
+            limit = int(self.getParamA(C.HISTORY_LIMIT, "General", profile_key=profile))
         elif limit == C.HISTORY_LIMIT_NONE:
             limit = None
         if limit == 0:
@@ -597,7 +678,7 @@
 
     def _getPresenceStatuses(self, profile_key):
         ret = self.getPresenceStatuses(profile_key)
-        return {entity.full():data for entity, data in ret.iteritems()}
+        return {entity.full(): data for entity, data in ret.iteritems()}
 
     def getPresenceStatuses(self, profile_key):
         """Get all the presence statuses of a profile
@@ -617,7 +698,9 @@
                     presence_data = self.getEntityDatum(full_jid, "presence", profile_key)
                 except KeyError:
                     continue
-                entities_presence.setdefault(entity_jid, {})[resource or ''] = presence_data
+                entities_presence.setdefault(entity_jid, {})[
+                    resource or ""
+                ] = presence_data
 
         return entities_presence
 
@@ -631,7 +714,9 @@
         @param profile_key: %(doc_profile_key)s
         """
         presence_data = PresenceTuple(show, priority, statuses)
-        self.updateEntityData(entity_jid, "presence", presence_data, profile_key=profile_key)
+        self.updateEntityData(
+            entity_jid, "presence", presence_data, profile_key=profile_key
+        )
         if entity_jid.resource and show != C.PRESENCE_UNAVAILABLE:
             # If a resource is available, bare jid should not have presence information
             try:
@@ -657,13 +742,17 @@
         """
         # FIXME: is there a need to keep cache data for resources which are not connected anymore?
         if entity_jid.resource:
-            raise ValueError("getAllResources must be used with a bare jid (got {})".format(entity_jid))
+            raise ValueError(
+                "getAllResources must be used with a bare jid (got {})".format(entity_jid)
+            )
         profile_cache = self._getProfileCache(client)
         try:
             entity_data = profile_cache[entity_jid.userhostJID()]
         except KeyError:
-            raise exceptions.UnknownEntityError(u"Entity {} not in cache".format(entity_jid))
-        resources= set(entity_data.keys())
+            raise exceptions.UnknownEntityError(
+                u"Entity {} not in cache".format(entity_jid)
+            )
+        resources = set(entity_data.keys())
         resources.discard(None)
         return resources
 
@@ -701,7 +790,9 @@
         @return (unicode): main resource or None
         """
         if entity_jid.resource:
-            raise ValueError("getMainResource must be used with a bare jid (got {})".format(entity_jid))
+            raise ValueError(
+                "getMainResource must be used with a bare jid (got {})".format(entity_jid)
+            )
         try:
             if self.host.plugins["XEP-0045"].isJoinedRoom(client, entity_jid):
                 return None  # MUC rooms have no main resource
@@ -766,7 +857,9 @@
                 full_jid.resource = resource
                 yield full_jid
 
-    def updateEntityData(self, entity_jid, key, value, silent=False, profile_key=C.PROF_KEY_NONE):
+    def updateEntityData(
+        self, entity_jid, key, value, silent=False, profile_key=C.PROF_KEY_NONE
+    ):
         """Set a misc data for an entity
 
         If key was registered with setSignalOnUpdate, a signal will be sent to frontends
@@ -780,19 +873,27 @@
         client = self.host.getClient(profile_key)
         profile_cache = self._getProfileCache(client)
         if entity_jid in (C.ENTITY_ALL_RESOURCES, C.ENTITY_ALL):
-            entities = self.getAllEntitiesIter(client, entity_jid==C.ENTITY_ALL)
+            entities = self.getAllEntitiesIter(client, entity_jid == C.ENTITY_ALL)
         else:
             entities = (entity_jid,)
 
         for jid_ in entities:
-            entity_data = profile_cache.setdefault(jid_.userhostJID(),{}).setdefault(jid_.resource, {})
+            entity_data = profile_cache.setdefault(jid_.userhostJID(), {}).setdefault(
+                jid_.resource, {}
+            )
 
             entity_data[key] = value
             if key in self._key_signals and not silent:
                 if not isinstance(value, basestring):
-                    log.error(u"Setting a non string value ({}) for a key ({}) which has a signal flag".format(value, key))
+                    log.error(
+                        u"Setting a non string value ({}) for a key ({}) which has a signal flag".format(
+                            value, key
+                        )
+                    )
                 else:
-                    self.host.bridge.entityDataUpdated(jid_.full(), key, value, self.getProfileName(profile_key))
+                    self.host.bridge.entityDataUpdated(
+                        jid_.full(), key, value, self.getProfileName(profile_key)
+                    )
 
     def delEntityDatum(self, entity_jid, key, profile_key):
         """Delete a data for an entity
@@ -808,7 +909,7 @@
         client = self.host.getClient(profile_key)
         profile_cache = self._getProfileCache(client)
         if entity_jid in (C.ENTITY_ALL_RESOURCES, C.ENTITY_ALL):
-            entities = self.getAllEntitiesIter(client, entity_jid==C.ENTITY_ALL)
+            entities = self.getAllEntitiesIter(client, entity_jid == C.ENTITY_ALL)
         else:
             entities = (entity_jid,)
 
@@ -816,17 +917,21 @@
             try:
                 entity_data = profile_cache[jid_.userhostJID()][jid_.resource]
             except KeyError:
-                raise exceptions.UnknownEntityError(u"Entity {} not in cache".format(jid_))
+                raise exceptions.UnknownEntityError(
+                    u"Entity {} not in cache".format(jid_)
+                )
             try:
                 del entity_data[key]
             except KeyError as e:
                 if entity_jid in (C.ENTITY_ALL_RESOURCES, C.ENTITY_ALL):
-                    continue # we ignore KeyError when deleting keys from several entities
+                    continue  # we ignore KeyError when deleting keys from several entities
                 else:
                     raise e
 
     def _getEntitiesData(self, entities_jids, keys_list, profile_key):
-        ret = self.getEntitiesData([jid.JID(jid_) for jid_ in entities_jids], keys_list, profile_key)
+        ret = self.getEntitiesData(
+            [jid.JID(jid_) for jid_ in entities_jids], keys_list, profile_key
+        )
         return {jid_.full(): data for jid_, data in ret.iteritems()}
 
     def getEntitiesData(self, entities_jids, keys_list=None, profile_key=C.PROF_KEY_NONE):
@@ -843,6 +948,7 @@
 
         @raise exceptions.UnknownEntityError: if entity is not in cache
         """
+
         def fillEntityData(entity_cache_data):
             entity_data = {}
             if keys_list is None:
@@ -861,7 +967,9 @@
         if entities_jids:
             for entity in entities_jids:
                 try:
-                    entity_cache_data = profile_cache[entity.userhostJID()][entity.resource]
+                    entity_cache_data = profile_cache[entity.userhostJID()][
+                        entity.resource
+                    ]
                 except KeyError:
                     continue
                 ret_data[entity.full()] = fillEntityData(entity_cache_data, keys_list)
@@ -891,7 +999,11 @@
         try:
             entity_data = profile_cache[entity_jid.userhostJID()][entity_jid.resource]
         except KeyError:
-            raise exceptions.UnknownEntityError(u"Entity {} not in cache (was requesting {})".format(entity_jid, keys_list))
+            raise exceptions.UnknownEntityError(
+                u"Entity {} not in cache (was requesting {})".format(
+                    entity_jid, keys_list
+                )
+            )
         if keys_list is None:
             return entity_data
 
@@ -910,7 +1022,9 @@
         """
         return self.getEntityData(entity_jid, (key,), profile_key)[key]
 
-    def delEntityCache(self, entity_jid, delete_all_resources=True, profile_key=C.PROF_KEY_NONE):
+    def delEntityCache(
+        self, entity_jid, delete_all_resources=True, profile_key=C.PROF_KEY_NONE
+    ):
         """Remove all cached data for entity
 
         @param entity_jid: JID of the entity to delete
@@ -928,12 +1042,16 @@
             try:
                 del profile_cache[entity_jid]
             except KeyError:
-                raise exceptions.UnknownEntityError(u"Entity {} not in cache".format(entity_jid))
+                raise exceptions.UnknownEntityError(
+                    u"Entity {} not in cache".format(entity_jid)
+                )
         else:
             try:
                 del profile_cache[entity_jid.userhostJID()][entity_jid.resource]
             except KeyError:
-                raise exceptions.UnknownEntityError(u"Entity {} not in cache".format(entity_jid))
+                raise exceptions.UnknownEntityError(
+                    u"Entity {} not in cache".format(entity_jid)
+                )
 
     ## Encryption ##
 
@@ -947,9 +1065,14 @@
         @return: the deferred encrypted value
         """
         try:
-            personal_key = self.auth_sessions.profileGetUnique(profile)[C.MEMORY_CRYPTO_KEY]
+            personal_key = self.auth_sessions.profileGetUnique(profile)[
+                C.MEMORY_CRYPTO_KEY
+            ]
         except TypeError:
-            raise exceptions.InternalError(_('Trying to encrypt a value for %s while the personal key is undefined!') % profile)
+            raise exceptions.InternalError(
+                _("Trying to encrypt a value for %s while the personal key is undefined!")
+                % profile
+            )
         return BlockCipher.encrypt(personal_key, value)
 
     def decryptValue(self, value, profile):
@@ -962,9 +1085,14 @@
         @return: the deferred decrypted value
         """
         try:
-            personal_key = self.auth_sessions.profileGetUnique(profile)[C.MEMORY_CRYPTO_KEY]
+            personal_key = self.auth_sessions.profileGetUnique(profile)[
+                C.MEMORY_CRYPTO_KEY
+            ]
         except TypeError:
-            raise exceptions.InternalError(_('Trying to decrypt a value for %s while the personal key is undefined!') % profile)
+            raise exceptions.InternalError(
+                _("Trying to decrypt a value for %s while the personal key is undefined!")
+                % profile
+            )
         return BlockCipher.decrypt(personal_key, value)
 
     def encryptPersonalData(self, data_key, data_value, crypto_key, profile):
@@ -987,8 +1115,10 @@
             return d.addCallback(cb)
 
         def done(dummy):
-            log.debug(_(u'Personal data (%(ns)s, %(key)s) has been successfuly encrypted') %
-                      {'ns': C.MEMORY_CRYPTO_NAMESPACE, 'key': data_key})
+            log.debug(
+                _(u"Personal data (%(ns)s, %(key)s) has been successfuly encrypted")
+                % {"ns": C.MEMORY_CRYPTO_NAMESPACE, "key": data_key}
+            )
 
         d = PersistentDict(C.MEMORY_CRYPTO_NAMESPACE, profile).load()
         return d.addCallback(gotIndMemory).addCallback(done)
@@ -1014,7 +1144,7 @@
         """Called to get a list of currently waiting subscription requests"""
         profile = self.getProfileName(profile_key)
         if not profile:
-            log.error(_('Asking waiting subscriptions for a non-existant profile'))
+            log.error(_("Asking waiting subscriptions for a non-existant profile"))
             return {}
         if profile not in self.subscriptions:
             return {}
@@ -1029,28 +1159,59 @@
     def getParamA(self, name, category, attr="value", profile_key=C.PROF_KEY_NONE):
         return self.params.getParamA(name, category, attr, profile_key=profile_key)
 
-    def asyncGetParamA(self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE):
-        return self.params.asyncGetParamA(name, category, attr, security_limit, profile_key)
+    def asyncGetParamA(
+        self,
+        name,
+        category,
+        attr="value",
+        security_limit=C.NO_SECURITY_LIMIT,
+        profile_key=C.PROF_KEY_NONE,
+    ):
+        return self.params.asyncGetParamA(
+            name, category, attr, security_limit, profile_key
+        )
 
-    def asyncGetParamsValuesFromCategory(self, category, security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE):
-        return self.params.asyncGetParamsValuesFromCategory(category, security_limit, profile_key)
+    def asyncGetParamsValuesFromCategory(
+        self, category, security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE
+    ):
+        return self.params.asyncGetParamsValuesFromCategory(
+            category, security_limit, profile_key
+        )
 
-    def asyncGetStringParamA(self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE):
-        return self.params.asyncGetStringParamA(name, category, attr, security_limit, profile_key)
+    def asyncGetStringParamA(
+        self,
+        name,
+        category,
+        attr="value",
+        security_limit=C.NO_SECURITY_LIMIT,
+        profile_key=C.PROF_KEY_NONE,
+    ):
+        return self.params.asyncGetStringParamA(
+            name, category, attr, security_limit, profile_key
+        )
 
-    def getParamsUI(self, security_limit=C.NO_SECURITY_LIMIT, app='', profile_key=C.PROF_KEY_NONE):
+    def getParamsUI(
+        self, security_limit=C.NO_SECURITY_LIMIT, app="", profile_key=C.PROF_KEY_NONE
+    ):
         return self.params.getParamsUI(security_limit, app, profile_key)
 
     def getParamsCategories(self):
         return self.params.getParamsCategories()
 
-    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,
+    ):
         return self.params.setParam(name, value, category, security_limit, profile_key)
 
     def updateParams(self, xml):
         return self.params.updateParams(xml)
 
-    def paramsRegisterApp(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=''):
+    def paramsRegisterApp(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=""):
         return self.params.paramsRegisterApp(xml, security_limit, app)
 
     def setDefault(self, name, category, callback, errback=None):
@@ -1073,25 +1234,25 @@
         if peer_jid is None and perms_to_check is None:
             return
         peer_jid = peer_jid.userhostJID()
-        if peer_jid == file_data['owner']:
+        if peer_jid == file_data["owner"]:
             # the owner has all rights
             return
         if not C.ACCESS_PERMS.issuperset(perms_to_check):
-            raise exceptions.InternalError(_(u'invalid permission'))
+            raise exceptions.InternalError(_(u"invalid permission"))
 
         for perm in perms_to_check:
             # we check each perm and raise PermissionError as soon as one condition is not valid
             # we must never return here, we only return after the loop if nothing was blocking the access
             try:
-                perm_data = file_data[u'access'][perm]
-                perm_type = perm_data[u'type']
+                perm_data = file_data[u"access"][perm]
+                perm_type = perm_data[u"type"]
             except KeyError:
                 raise failure.Failure(exceptions.PermissionError())
             if perm_type == C.ACCESS_TYPE_PUBLIC:
                 continue
             elif perm_type == C.ACCESS_TYPE_WHITELIST:
                 try:
-                    jids = perm_data[u'jids']
+                    jids = perm_data[u"jids"]
                 except KeyError:
                     raise failure.Failure(exceptions.PermissionError())
                 if peer_jid.full() in jids:
@@ -1099,7 +1260,9 @@
                 else:
                     raise failure.Failure(exceptions.PermissionError())
             else:
-                raise exceptions.InternalError(_(u'unknown access type: {type}').format(type=perm_type))
+                raise exceptions.InternalError(
+                    _(u"unknown access type: {type}").format(type=perm_type)
+                )
 
     @defer.inlineCallbacks
     def checkPermissionToRoot(self, client, file_data, peer_jid, perms_to_check):
@@ -1107,17 +1270,21 @@
         current = file_data
         while True:
             self.checkFilePermission(current, peer_jid, perms_to_check)
-            parent = current[u'parent']
+            parent = current[u"parent"]
             if not parent:
                 break
-            files_data = yield self.getFile(self, client, peer_jid=None, file_id=parent, perms_to_check=None)
+            files_data = yield self.getFile(
+                self, client, peer_jid=None, file_id=parent, perms_to_check=None
+            )
             try:
                 current = files_data[0]
             except IndexError:
-                raise exceptions.DataError(u'Missing parent')
+                raise exceptions.DataError(u"Missing parent")
 
     @defer.inlineCallbacks
-    def _getParentDir(self, client, path, parent, namespace, owner, peer_jid, perms_to_check):
+    def _getParentDir(
+        self, client, path, parent, namespace, owner, peer_jid, perms_to_check
+    ):
         """Retrieve parent node from a path, or last existing directory
 
         each directory of the path will be retrieved, until the last existing one
@@ -1128,32 +1295,59 @@
         """
         # if path is set, we have to retrieve parent directory of the file(s) from it
         if parent is not None:
-            raise exceptions.ConflictError(_(u"You can't use path and parent at the same time"))
-        path_elts = filter(None, path.split(u'/'))
-        if {u'..', u'.'}.intersection(path_elts):
+            raise exceptions.ConflictError(
+                _(u"You can't use path and parent at the same time")
+            )
+        path_elts = filter(None, path.split(u"/"))
+        if {u"..", u"."}.intersection(path_elts):
             raise ValueError(_(u'".." or "." can\'t be used in path'))
 
         # we retrieve all directories from path until we get the parent container
         # non existing directories will be created
-        parent = u''
+        parent = u""
         for idx, path_elt in enumerate(path_elts):
-            directories = yield self.storage.getFiles(client, parent=parent, type_=C.FILE_TYPE_DIRECTORY,
-                                                      name=path_elt, namespace=namespace, owner=owner)
+            directories = yield self.storage.getFiles(
+                client,
+                parent=parent,
+                type_=C.FILE_TYPE_DIRECTORY,
+                name=path_elt,
+                namespace=namespace,
+                owner=owner,
+            )
             if not directories:
                 defer.returnValue((parent, path_elts[idx:]))
                 # from this point, directories don't exist anymore, we have to create them
             elif len(directories) > 1:
-                raise exceptions.InternalError(_(u"Several directories found, this should not happen"))
+                raise exceptions.InternalError(
+                    _(u"Several directories found, this should not happen")
+                )
             else:
                 directory = directories[0]
                 self.checkFilePermission(directory, peer_jid, perms_to_check)
-                parent = directory[u'id']
+                parent = directory[u"id"]
         defer.returnValue((parent, []))
 
     @defer.inlineCallbacks
-    def getFiles(self, client, peer_jid, file_id=None, version=None, parent=None, path=None, type_=None,
-                 file_hash=None, hash_algo=None, name=None, namespace=None, mime_type=None,
-                 owner=None, access=None, projection=None, unique=False, perms_to_check=(C.ACCESS_PERM_READ,)):
+    def getFiles(
+        self,
+        client,
+        peer_jid,
+        file_id=None,
+        version=None,
+        parent=None,
+        path=None,
+        type_=None,
+        file_hash=None,
+        hash_algo=None,
+        name=None,
+        namespace=None,
+        mime_type=None,
+        owner=None,
+        access=None,
+        projection=None,
+        unique=False,
+        perms_to_check=(C.ACCESS_PERM_READ,),
+    ):
         """retrieve files with with given filters
 
         @param peer_jid(jid.JID, None): jid trying to access the file
@@ -1180,12 +1374,16 @@
             on the path
         """
         if peer_jid is None and perms_to_check or perms_to_check is None and peer_jid:
-            raise exceptions.InternalError('if you want to disable permission check, both peer_jid and perms_to_check must be None')
+            raise exceptions.InternalError(
+                "if you want to disable permission check, both peer_jid and perms_to_check must be None"
+            )
         if owner is not None:
             owner = owner.userhostJID()
         if path is not None:
             # permission are checked by _getParentDir
-            parent, remaining_path_elts = yield self._getParentDir(client, path, parent, namespace, owner, peer_jid, perms_to_check)
+            parent, remaining_path_elts = yield self._getParentDir(
+                client, path, parent, namespace, owner, peer_jid, perms_to_check
+            )
             if remaining_path_elts:
                 # if we have remaining path elements,
                 # the parent directory is not found
@@ -1197,16 +1395,30 @@
             try:
                 parent_data = parent_data[0]
             except IndexError:
-                raise exceptions.DataError(u'mising parent')
-            yield self.checkPermissionToRoot(client, parent_data, peer_jid, perms_to_check)
+                raise exceptions.DataError(u"mising parent")
+            yield self.checkPermissionToRoot(
+                client, parent_data, peer_jid, perms_to_check
+            )
 
-        files = yield self.storage.getFiles(client, file_id=file_id, version=version, parent=parent, type_=type_,
-                                            file_hash=file_hash, hash_algo=hash_algo, name=name, namespace=namespace,
-                                            mime_type=mime_type, owner=owner, access=access,
-                                            projection=projection, unique=unique)
+        files = yield self.storage.getFiles(
+            client,
+            file_id=file_id,
+            version=version,
+            parent=parent,
+            type_=type_,
+            file_hash=file_hash,
+            hash_algo=hash_algo,
+            name=name,
+            namespace=namespace,
+            mime_type=mime_type,
+            owner=owner,
+            access=access,
+            projection=projection,
+            unique=unique,
+        )
 
         if peer_jid:
-            # if permission are checked, we must remove all file tha use can't access
+            #  if permission are checked, we must remove all file tha use can't access
             to_remove = []
             for file_data in files:
                 try:
@@ -1218,10 +1430,28 @@
         defer.returnValue(files)
 
     @defer.inlineCallbacks
-    def setFile(self, client, name, file_id=None, version=u'', parent=None, path=None,
-                type_=C.FILE_TYPE_FILE, file_hash=None, hash_algo=None, size=None, namespace=None,
-                mime_type=None, created=None, modified=None, owner=None, access=None, extra=None,
-                peer_jid = None, perms_to_check=(C.ACCESS_PERM_WRITE,)):
+    def setFile(
+        self,
+        client,
+        name,
+        file_id=None,
+        version=u"",
+        parent=None,
+        path=None,
+        type_=C.FILE_TYPE_FILE,
+        file_hash=None,
+        hash_algo=None,
+        size=None,
+        namespace=None,
+        mime_type=None,
+        created=None,
+        modified=None,
+        owner=None,
+        access=None,
+        extra=None,
+        peer_jid=None,
+        perms_to_check=(C.ACCESS_PERM_WRITE,),
+    ):
         """set a file metadata
 
         @param name(unicode): basename of the file
@@ -1258,12 +1488,17 @@
             if None, permission will no be checked (peer_jid must be None too in this case)
         @param profile(unicode): profile owning the file
         """
-        if '/' in name:
+        if "/" in name:
             raise ValueError('name must not contain a slash ("/")')
         if file_id is None:
             file_id = shortuuid.uuid()
-        if file_hash is not None and hash_algo is None or hash_algo is not None and file_hash is None:
-            raise ValueError('file_hash and hash_algo must be set at the same time')
+        if (
+            file_hash is not None
+            and hash_algo is None
+            or hash_algo is not None
+            and file_hash is None
+        ):
+            raise ValueError("file_hash and hash_algo must be set at the same time")
         if mime_type is None:
             mime_type, file_encoding = mimetypes.guess_type(name)
         if created is None:
@@ -1271,31 +1506,56 @@
         if namespace is not None:
             namespace = namespace.strip() or None
         if type_ == C.FILE_TYPE_DIRECTORY:
-            if any(version, file_hash, size,  mime_type):
-                raise ValueError(u"version, file_hash, size and mime_type can't be set for a directory")
+            if any(version, file_hash, size, mime_type):
+                raise ValueError(
+                    u"version, file_hash, size and mime_type can't be set for a directory"
+                )
         if owner is not None:
             owner = owner.userhostJID()
 
         if path is not None:
             # _getParentDir will check permissions if peer_jid is set, so we use owner
-            parent, remaining_path_elts = yield self._getParentDir(client, path, parent, namespace, owner, owner, perms_to_check)
+            parent, remaining_path_elts = yield self._getParentDir(
+                client, path, parent, namespace, owner, owner, perms_to_check
+            )
             # if remaining directories don't exist, we have to create them
             for new_dir in remaining_path_elts:
                 new_dir_id = shortuuid.uuid()
-                yield self.storage.setFile(client, name=new_dir, file_id=new_dir_id, version=u'', parent=parent,
-                                           type_=C.FILE_TYPE_DIRECTORY, namespace=namespace,
-                                           created=time.time(),
-                                           owner=owner,
-                                           access=access, extra={})
+                yield self.storage.setFile(
+                    client,
+                    name=new_dir,
+                    file_id=new_dir_id,
+                    version=u"",
+                    parent=parent,
+                    type_=C.FILE_TYPE_DIRECTORY,
+                    namespace=namespace,
+                    created=time.time(),
+                    owner=owner,
+                    access=access,
+                    extra={},
+                )
                 parent = new_dir_id
         elif parent is None:
-            parent = u''
+            parent = u""
 
-        yield self.storage.setFile(client, file_id=file_id, version=version, parent=parent, type_=type_,
-                                   file_hash=file_hash, hash_algo=hash_algo, name=name, size=size,
-                                   namespace=namespace, mime_type=mime_type, created=created, modified=modified,
-                                   owner=owner,
-                                   access=access, extra=extra)
+        yield self.storage.setFile(
+            client,
+            file_id=file_id,
+            version=version,
+            parent=parent,
+            type_=type_,
+            file_hash=file_hash,
+            hash_algo=hash_algo,
+            name=name,
+            size=size,
+            namespace=namespace,
+            mime_type=mime_type,
+            created=created,
+            modified=modified,
+            owner=owner,
+            access=access,
+            extra=extra,
+        )
 
     def fileUpdate(self, file_id, column, update_cb):
         """update a file column taking care of race condition
@@ -1318,7 +1578,9 @@
         @return (bool): True if entity is available
         """
         if not entity_jid.resource:
-            return bool(self.getAvailableResources(client, entity_jid)) # is any resource is available, entity is available
+            return bool(
+                self.getAvailableResources(client, entity_jid)
+            )  # is any resource is available, entity is available
         try:
             presence_data = self.getEntityDatum(entity_jid, "presence", client.profile)
         except KeyError: