diff sat_frontends/quick_frontend/quick_app.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents fe9888d3fcb6
children 6ef2b4fa90a5
line wrap: on
line diff
--- a/sat_frontends/quick_frontend/quick_app.py	Wed Jun 27 07:51:29 2018 +0200
+++ b/sat_frontends/quick_frontend/quick_app.py	Wed Jun 27 20:14:46 2018 +0200
@@ -18,6 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from sat.core.log import getLogger
+
 log = getLogger(__name__)
 
 from sat.core.i18n import _
@@ -39,13 +40,17 @@
 
 try:
     # FIXME: to be removed when an acceptable solution is here
-    unicode('')  # XXX: unicode doesn't exist in pyjamas
-except (TypeError, AttributeError):  # Error raised is not the same depending on pyjsbuild options
+    unicode("")  # XXX: unicode doesn't exist in pyjamas
+except (
+    TypeError,
+    AttributeError,
+):  # Error raised is not the same depending on pyjsbuild options
     unicode = str
 
 
 class ProfileManager(object):
     """Class managing all data relative to one profile, and plugging in mechanism"""
+
     # TODO: handle waiting XMLUI requests: getWaitingConf doesn't exist anymore
     #       and a way to keep some XMLUI request between sessions is expected in backend
     host = None
@@ -69,8 +74,13 @@
     def plug(self):
         """Plug the profile to the host"""
         # we get the essential params
-        self.bridge.asyncGetParamA("JabberID", "Connection", profile_key=self.profile,
-                                   callback=self._plug_profile_jid, errback=self._getParamError)
+        self.bridge.asyncGetParamA(
+            "JabberID",
+            "Connection",
+            profile_key=self.profile,
+            callback=self._plug_profile_jid,
+            errback=self._getParamError,
+        )
 
     def _plug_profile_jid(self, jid_s):
         self.whoami = jid.JID(jid_s)  # resource might change after the connection
@@ -78,24 +88,40 @@
 
     def _autodisconnectEb(self, failure_):
         # XXX: we ignore error on this parameter, as Libervia can't access it
-        log.warning(_("Error while trying to get autodisconnect param, ignoring: {}").format(failure_))
+        log.warning(
+            _("Error while trying to get autodisconnect param, ignoring: {}").format(
+                failure_
+            )
+        )
         self._plug_profile_autodisconnect("false")
 
     def _plug_profile_isconnected(self, connected):
         self.connected = connected
-        self.bridge.asyncGetParamA("autodisconnect", "Connection", profile_key=self.profile,
-                                   callback=self._plug_profile_autodisconnect, errback=self._autodisconnectEb)
+        self.bridge.asyncGetParamA(
+            "autodisconnect",
+            "Connection",
+            profile_key=self.profile,
+            callback=self._plug_profile_autodisconnect,
+            errback=self._autodisconnectEb,
+        )
 
     def _plug_profile_autodisconnect(self, autodisconnect):
         if C.bool(autodisconnect):
             self._autodisconnect = True
-        self.bridge.asyncGetParamA("autoconnect", "Connection", profile_key=self.profile,
-                                   callback=self._plug_profile_autoconnect, errback=self._getParamError)
+        self.bridge.asyncGetParamA(
+            "autoconnect",
+            "Connection",
+            profile_key=self.profile,
+            callback=self._plug_profile_autoconnect,
+            errback=self._getParamError,
+        )
 
     def _plug_profile_autoconnect(self, value_str):
         autoconnect = C.bool(value_str)
         if autoconnect and not self.connected:
-            self.host.connect(self.profile, callback=lambda dummy: self._plug_profile_afterconnect())
+            self.host.connect(
+                self.profile, callback=lambda dummy: self._plug_profile_afterconnect()
+            )
         else:
             self._plug_profile_afterconnect()
 
@@ -103,7 +129,11 @@
         # Profile can be connected or not
         # we get cached data
         self.connected = True
-        self.host.bridge.getFeatures(profile_key=self.profile, callback=self._plug_profile_getFeaturesCb, errback=self._plug_profile_getFeaturesEb)
+        self.host.bridge.getFeatures(
+            profile_key=self.profile,
+            callback=self._plug_profile_getFeaturesCb,
+            errback=self._plug_profile_getFeaturesEb,
+        )
 
     def _plug_profile_getFeaturesEb(self, failure):
         log.error(u"Couldn't get features: {}".format(failure))
@@ -129,42 +159,60 @@
                 self.host.entityDataUpdatedHandler(entity_s, key, value, self.profile)
 
         if not self.connected:
-            self.host.setPresenceStatus(C.PRESENCE_UNAVAILABLE, '', profile=self.profile)
+            self.host.setPresenceStatus(C.PRESENCE_UNAVAILABLE, "", profile=self.profile)
         else:
 
             contact_list.fill()
             self.host.setPresenceStatus(profile=self.profile)
 
-            #The waiting subscription requests
-            self.bridge.getWaitingSub(self.profile, callback=self._plug_profile_gotWaitingSub)
+            # The waiting subscription requests
+            self.bridge.getWaitingSub(
+                self.profile, callback=self._plug_profile_gotWaitingSub
+            )
 
     def _plug_profile_gotWaitingSub(self, waiting_sub):
         for sub in waiting_sub:
             self.host.subscribeHandler(waiting_sub[sub], sub, self.profile)
 
-        self.bridge.mucGetRoomsJoined(self.profile, callback=self._plug_profile_gotRoomsJoined)
+        self.bridge.mucGetRoomsJoined(
+            self.profile, callback=self._plug_profile_gotRoomsJoined
+        )
 
     def _plug_profile_gotRoomsJoined(self, rooms_args):
-        #Now we open the MUC window where we already are:
+        # Now we open the MUC window where we already are:
         for room_args in rooms_args:
             self.host.mucRoomJoinedHandler(*room_args, profile=self.profile)
-        #Presence must be requested after rooms are filled
-        self.host.bridge.getPresenceStatuses(self.profile, callback=self._plug_profile_gotPresences)
+        # Presence must be requested after rooms are filled
+        self.host.bridge.getPresenceStatuses(
+            self.profile, callback=self._plug_profile_gotPresences
+        )
 
     def _plug_profile_gotPresences(self, presences):
         def gotEntityData(data, contact):
-            for key in ('avatar', 'nick'):
+            for key in ("avatar", "nick"):
                 if key in data:
-                    self.host.entityDataUpdatedHandler(contact, key, data[key], self.profile)
+                    self.host.entityDataUpdatedHandler(
+                        contact, key, data[key], self.profile
+                    )
 
         for contact in presences:
             for res in presences[contact]:
-                jabber_id = (u'%s/%s' % (jid.JID(contact).bare, res)) if res else contact
+                jabber_id = (u"%s/%s" % (jid.JID(contact).bare, res)) if res else contact
                 show = presences[contact][res][0]
                 priority = presences[contact][res][1]
                 statuses = presences[contact][res][2]
-                self.host.presenceUpdateHandler(jabber_id, show, priority, statuses, self.profile)
-            self.host.bridge.getEntityData(contact, ['avatar', 'nick'], self.profile, callback=lambda data, contact=contact: gotEntityData(data, contact), errback=lambda failure, contact=contact: log.debug(u"No cache data for {}".format(contact)))
+                self.host.presenceUpdateHandler(
+                    jabber_id, show, priority, statuses, self.profile
+                )
+            self.host.bridge.getEntityData(
+                contact,
+                ["avatar", "nick"],
+                self.profile,
+                callback=lambda data, contact=contact: gotEntityData(data, contact),
+                errback=lambda failure, contact=contact: log.debug(
+                    u"No cache data for {}".format(contact)
+                ),
+            )
 
         # At this point, profile should be fully plugged
         # and we launch frontend specific method
@@ -200,13 +248,15 @@
 
     def plug(self, profile):
         if profile in self._profiles:
-            raise exceptions.ConflictError('A profile of the name [{}] is already plugged'.format(profile))
+            raise exceptions.ConflictError(
+                "A profile of the name [{}] is already plugged".format(profile)
+            )
         self._profiles[profile] = ProfileManager(profile)
         self._profiles[profile].plug()
 
     def unplug(self, profile):
         if profile not in self._profiles:
-            raise ValueError('The profile [{}] is not plugged'.format(profile))
+            raise ValueError("The profile [{}] is not plugged".format(profile))
 
         # remove the contact list and its listener
         host = self._profiles[profile].host
@@ -220,6 +270,7 @@
 
 class QuickApp(object):
     """This class contain the main methods needed for the frontend"""
+
     MB_HANDLER = True  # Set to False if the frontend doesn't manage microblog
     AVATARS_HANDLER = True  # set to False if avatars are not used
 
@@ -234,9 +285,11 @@
         self.menus = quick_menus.QuickMenusManager(self)
         ProfileManager.host = self
         self.profiles = ProfilesManager()
-        self._plugs_in_progress = set() # profiles currently being plugged, used to (un)lock contact list updates
-        self.ready_profiles = set() # profiles which are connected and ready
-        self.signals_cache = {} # used to keep signal received between start of plug_profile and when the profile is actualy ready
+        self._plugs_in_progress = (
+            set()
+        )  # profiles currently being plugged, used to (un)lock contact list updates
+        self.ready_profiles = set()  # profiles which are connected and ready
+        self.signals_cache = {}  # used to keep signal received between start of plug_profile and when the profile is actualy ready
         self.contact_lists = quick_contact_list.QuickContactListHandler(self)
         self.widgets = quick_widgets.QuickWidgetsManager(self)
         if check_options is not None:
@@ -245,13 +298,17 @@
             self.options = None
 
         # widgets
-        self.selected_widget = None # widget currently selected (must be filled by frontend)
+        self.selected_widget = (
+            None
+        )  # widget currently selected (must be filled by frontend)
 
         # listeners
-        self._listeners = {} # key: listener type ("avatar", "selected", etc), value: list of callbacks
+        self._listeners = {}  # key: listener type ("avatar", "selected", etc), value: list of callbacks
 
         # triggers
-        self.trigger = trigger.TriggerManager()  # trigger are used to change the default behaviour
+        self.trigger = (
+            trigger.TriggerManager()
+        )  # trigger are used to change the default behaviour
 
         ## bridge ##
         self.bridge = bridge_factory()
@@ -274,8 +331,9 @@
         log.error(_(u"Can't get namespaces map: {msg}").format(msg=failure_))
 
     def onBridgeConnected(self):
-        self.bridge.namespacesGet(callback=self._namespacesGetCb,
-                                  errback=self._namespacesGetEb)
+        self.bridge.namespacesGet(
+            callback=self._namespacesGetCb, errback=self._namespacesGetEb
+        )
 
     def _bridgeCb(self):
         self.registerSignal("connected")
@@ -331,7 +389,9 @@
         """
         raise NotImplementedError
 
-    def registerSignal(self, function_name, handler=None, iface="core", with_profile=True):
+    def registerSignal(
+        self, function_name, handler=None, iface="core", with_profile=True
+    ):
         """Register a handler for a signal
 
         @param function_name (str): name of the signal to handle
@@ -339,15 +399,15 @@
         @param iface (str): interface of the bridge to use ('core' or 'plugin')
         @param with_profile (boolean): True if the signal concerns a specific profile, in that case the profile name has to be passed by the caller
         """
-        log.debug(u"registering signal {name}".format(name = function_name))
+        log.debug(u"registering signal {name}".format(name=function_name))
         if handler is None:
-            handler = getattr(self, "{}{}".format(function_name, 'Handler'))
+            handler = getattr(self, "{}{}".format(function_name, "Handler"))
         if not with_profile:
             self.bridge.register_signal(function_name, handler, iface)
             return
 
         def signalReceived(*args, **kwargs):
-            profile = kwargs.get('profile')
+            profile = kwargs.get("profile")
             if profile is None:
                 if not args:
                     raise exceptions.ProfileNotSetError
@@ -356,9 +416,12 @@
                 if not self.check_profile(profile):
                     if profile in self.profiles:
                         # profile is not ready but is in self.profiles, that's mean that it's being connecting and we need to cache the signal
-                        self.signals_cache.setdefault(profile, []).append((function_name, handler, args, kwargs))
+                        self.signals_cache.setdefault(profile, []).append(
+                            (function_name, handler, args, kwargs)
+                        )
                     return  # we ignore signal for profiles we don't manage
             handler(*args, **kwargs)
+
         self.bridge.register_signal(function_name, signalReceived, iface)
 
     def addListener(self, type_, callback, profiles_filter=None):
@@ -449,10 +512,13 @@
         # profile is ready, we can call send signals that where is cache
         cached_signals = self.signals_cache.pop(profile, [])
         for function_name, handler, args, kwargs in cached_signals:
-            log.debug(u"Calling cached signal [%s] with args %s and kwargs %s" % (function_name, args, kwargs))
+            log.debug(
+                u"Calling cached signal [%s] with args %s and kwargs %s"
+                % (function_name, args, kwargs)
+            )
             handler(*args, **kwargs)
 
-        self.callListeners('profilePlugged', profile=profile)
+        self.callListeners("profilePlugged", profile=profile)
         if not self._plugs_in_progress:
             self.contact_lists.lockUpdate(False)
 
@@ -460,24 +526,29 @@
         if not callback:
             callback = lambda dummy: None
         if not errback:
+
             def errback(failure):
                 log.error(_(u"Can't connect profile [%s]") % failure)
                 try:
                     module = failure.module
                 except AttributeError:
-                    module = ''
+                    module = ""
                 try:
                     message = failure.message
                 except AttributeError:
-                    message = 'error'
+                    message = "error"
                 try:
                     fullname = failure.fullname
                 except AttributeError:
-                    fullname = 'error'
-                if module.startswith('twisted.words.protocols.jabber') and failure.condition == "not-authorized":
+                    fullname = "error"
+                if (
+                    module.startswith("twisted.words.protocols.jabber")
+                    and failure.condition == "not-authorized"
+                ):
                     self.launchAction(C.CHANGE_XMPP_PASSWD_ID, {}, profile=profile)
                 else:
-                    self.showDialog(message, fullname, 'error')
+                    self.showDialog(message, fullname, "error")
+
         self.bridge.connect(profile, callback=callback, errback=errback)
 
     def plug_profiles(self, profiles):
@@ -527,7 +598,7 @@
         """called when the connection is closed"""
         log.debug(_("Disconnected"))
         self.contact_lists[profile].disconnect()
-        self.setPresenceStatus(C.PRESENCE_UNAVAILABLE, '', profile=profile)
+        self.setPresenceStatus(C.PRESENCE_UNAVAILABLE, "", profile=profile)
 
     def actionNewHandler(self, action_data, id_, security_limit, profile):
         self.actionManager(action_data, user_action=False, profile=profile)
@@ -537,10 +608,23 @@
         groups = list(groups)
         self.contact_lists[profile].setContact(entity, groups, attributes, in_roster=True)
 
-    def messageNewHandler(self, uid, timestamp, from_jid_s, to_jid_s, msg, subject, type_, extra, profile):
+    def messageNewHandler(
+        self, uid, timestamp, from_jid_s, to_jid_s, msg, subject, type_, extra, profile
+    ):
         from_jid = jid.JID(from_jid_s)
         to_jid = jid.JID(to_jid_s)
-        if not self.trigger.point("messageNewTrigger", uid, timestamp, from_jid, to_jid, msg, subject, type_, extra, profile=profile):
+        if not self.trigger.point(
+            "messageNewTrigger",
+            uid,
+            timestamp,
+            from_jid,
+            to_jid,
+            msg,
+            subject,
+            type_,
+            extra,
+            profile=profile,
+        ):
             return
 
         from_me = from_jid.bare == self.profiles[profile].whoami.bare
@@ -550,66 +634,137 @@
             # we avoid resource locking, but we must keep resource for private MUC messages
             target = target.bare
         # we want to be sure to have at least one QuickChat instance
-        self.widgets.getOrCreateWidget(quick_chat.QuickChat, target, type_=C.CHAT_ONE2ONE, on_new_widget=None, profile=profile)
+        self.widgets.getOrCreateWidget(
+            quick_chat.QuickChat,
+            target,
+            type_=C.CHAT_ONE2ONE,
+            on_new_widget=None,
+            profile=profile,
+        )
 
-        if not from_jid in contact_list and from_jid.bare != self.profiles[profile].whoami.bare:
-            #XXX: needed to show entities which haven't sent any
+        if (
+            not from_jid in contact_list
+            and from_jid.bare != self.profiles[profile].whoami.bare
+        ):
+            # XXX: needed to show entities which haven't sent any
             #     presence information and which are not in roster
             contact_list.setContact(from_jid)
 
         # we dispatch the message in the widgets
-        for widget in self.widgets.getWidgets(quick_chat.QuickChat, target=target, profiles=(profile,)):
-            widget.messageNew(uid, timestamp, from_jid, target, msg, subject, type_, extra, profile)
+        for widget in self.widgets.getWidgets(
+            quick_chat.QuickChat, target=target, profiles=(profile,)
+        ):
+            widget.messageNew(
+                uid, timestamp, from_jid, target, msg, subject, type_, extra, profile
+            )
 
     def messageStateHandler(self, uid, status, profile):
         for widget in self.widgets.getWidgets(quick_chat.QuickChat, profiles=(profile,)):
             widget.onMessageState(uid, status, profile)
 
-    def messageSend(self, to_jid, message, subject=None, mess_type="auto", extra=None, callback=None, errback=None, profile_key=C.PROF_KEY_NONE):
+    def messageSend(
+        self,
+        to_jid,
+        message,
+        subject=None,
+        mess_type="auto",
+        extra=None,
+        callback=None,
+        errback=None,
+        profile_key=C.PROF_KEY_NONE,
+    ):
         if subject is None:
             subject = {}
         if extra is None:
             extra = {}
         if callback is None:
-            callback = lambda dummy=None: None # FIXME: optional argument is here because pyjamas doesn't support callback without arg with json proxy
+            callback = (
+                lambda dummy=None: None
+            )  # FIXME: optional argument is here because pyjamas doesn't support callback without arg with json proxy
         if errback is None:
-            errback = lambda failure: self.showDialog(failure.fullname, failure.message, "error")
+            errback = lambda failure: self.showDialog(
+                failure.fullname, failure.message, "error"
+            )
 
-        if not self.trigger.point("messageSendTrigger", to_jid, message, subject, mess_type, extra, callback, errback, profile_key=profile_key):
+        if not self.trigger.point(
+            "messageSendTrigger",
+            to_jid,
+            message,
+            subject,
+            mess_type,
+            extra,
+            callback,
+            errback,
+            profile_key=profile_key,
+        ):
             return
 
-        self.bridge.messageSend(unicode(to_jid), message, subject, mess_type, extra, profile_key, callback=callback, errback=errback)
+        self.bridge.messageSend(
+            unicode(to_jid),
+            message,
+            subject,
+            mess_type,
+            extra,
+            profile_key,
+            callback=callback,
+            errback=errback,
+        )
 
-    def setPresenceStatus(self, show='', status=None, profile=C.PROF_KEY_NONE):
+    def setPresenceStatus(self, show="", status=None, profile=C.PROF_KEY_NONE):
         raise NotImplementedError
 
     def presenceUpdateHandler(self, entity_s, show, priority, statuses, profile):
-        log.debug(_(u"presence update for %(entity)s (show=%(show)s, priority=%(priority)s, statuses=%(statuses)s) [profile:%(profile)s]")
-                  % {'entity': entity_s, C.PRESENCE_SHOW: show, C.PRESENCE_PRIORITY: priority, C.PRESENCE_STATUSES: statuses, 'profile': profile})
+        log.debug(
+            _(
+                u"presence update for %(entity)s (show=%(show)s, priority=%(priority)s, statuses=%(statuses)s) [profile:%(profile)s]"
+            )
+            % {
+                "entity": entity_s,
+                C.PRESENCE_SHOW: show,
+                C.PRESENCE_PRIORITY: priority,
+                C.PRESENCE_STATUSES: statuses,
+                "profile": profile,
+            }
+        )
         entity = jid.JID(entity_s)
 
         if entity == self.profiles[profile].whoami:
             if show == C.PRESENCE_UNAVAILABLE:
-                self.setPresenceStatus(C.PRESENCE_UNAVAILABLE, '', profile=profile)
+                self.setPresenceStatus(C.PRESENCE_UNAVAILABLE, "", profile=profile)
             else:
                 # FIXME: try to retrieve user language status before fallback to default
                 status = statuses.get(C.PRESENCE_STATUSES_DEFAULT, None)
                 self.setPresenceStatus(show, status, profile=profile)
             return
 
-        self.callListeners('presence', entity, show, priority, statuses, profile=profile)
+        self.callListeners("presence", entity, show, priority, statuses, profile=profile)
 
     def mucRoomJoinedHandler(self, room_jid_s, occupants, user_nick, subject, profile):
         """Called when a MUC room is joined"""
-        log.debug(u"Room [{room_jid}] joined by {profile}, users presents:{users}".format(room_jid=room_jid_s, profile=profile, users=occupants.keys()))
+        log.debug(
+            u"Room [{room_jid}] joined by {profile}, users presents:{users}".format(
+                room_jid=room_jid_s, profile=profile, users=occupants.keys()
+            )
+        )
         room_jid = jid.JID(room_jid_s)
-        self.widgets.getOrCreateWidget(quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, nick=user_nick, occupants=occupants, subject=subject, profile=profile)
+        self.widgets.getOrCreateWidget(
+            quick_chat.QuickChat,
+            room_jid,
+            type_=C.CHAT_GROUP,
+            nick=user_nick,
+            occupants=occupants,
+            subject=subject,
+            profile=profile,
+        )
         self.contact_lists[profile].setSpecial(room_jid, C.CONTACT_SPECIAL_GROUP)
         # chat_widget.update()
 
     def mucRoomLeftHandler(self, room_jid_s, profile):
         """Called when a MUC room is left"""
-        log.debug(u"Room [%(room_jid)s] left by %(profile)s" % {'room_jid': room_jid_s, 'profile': profile})
+        log.debug(
+            u"Room [%(room_jid)s] left by %(profile)s"
+            % {"room_jid": room_jid_s, "profile": profile}
+        )
         room_jid = jid.JID(room_jid_s)
         chat_widget = self.widgets.getWidget(quick_chat.QuickChat, room_jid, profile)
         if chat_widget:
@@ -619,16 +774,26 @@
     def mucRoomUserChangedNickHandler(self, room_jid_s, old_nick, new_nick, profile):
         """Called when an user joined a MUC room"""
         room_jid = jid.JID(room_jid_s)
-        chat_widget = self.widgets.getOrCreateWidget(quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, profile=profile)
+        chat_widget = self.widgets.getOrCreateWidget(
+            quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, profile=profile
+        )
         chat_widget.changeUserNick(old_nick, new_nick)
-        log.debug(u"user [%(old_nick)s] is now known as [%(new_nick)s] in room [%(room_jid)s]" % {'old_nick': old_nick, 'new_nick': new_nick, 'room_jid': room_jid})
+        log.debug(
+            u"user [%(old_nick)s] is now known as [%(new_nick)s] in room [%(room_jid)s]"
+            % {"old_nick": old_nick, "new_nick": new_nick, "room_jid": room_jid}
+        )
 
     def mucRoomNewSubjectHandler(self, room_jid_s, subject, profile):
         """Called when subject of MUC room change"""
         room_jid = jid.JID(room_jid_s)
-        chat_widget = self.widgets.getOrCreateWidget(quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, profile=profile)
+        chat_widget = self.widgets.getOrCreateWidget(
+            quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, profile=profile
+        )
         chat_widget.setSubject(subject)
-        log.debug(u"new subject for room [%(room_jid)s]: %(subject)s" % {'room_jid': room_jid, "subject": subject})
+        log.debug(
+            u"new subject for room [%(room_jid)s]: %(subject)s"
+            % {"room_jid": room_jid, "subject": subject}
+        )
 
     def chatStateReceivedHandler(self, from_jid_s, state, profile):
         """Called when a new chat state (XEP-0085) is received.
@@ -641,7 +806,17 @@
         for widget in self.widgets.getWidgets(quick_chat.QuickChat, profiles=(profile,)):
             widget.onChatState(from_jid, state, profile)
 
-    def notify(self, type_, entity=None, message=None, subject=None, callback=None, cb_args=None, widget=None, profile=C.PROF_KEY_NONE):
+    def notify(
+        self,
+        type_,
+        entity=None,
+        message=None,
+        subject=None,
+        callback=None,
+        cb_args=None,
+        widget=None,
+        profile=C.PROF_KEY_NONE,
+    ):
         """Trigger an event notification
 
         @param type_(unicode): notifation kind,
@@ -656,22 +831,22 @@
         """
         assert type_ in C.NOTIFY_ALL
         notif_dict = self.profiles[profile].notifications
-        key = '' if entity is None else entity.bare
+        key = "" if entity is None else entity.bare
         type_notifs = notif_dict.setdefault(key, {}).setdefault(type_, [])
         notif_data = {
-            'id': self._notif_id,
-            'time': time.time(),
-            'entity': entity,
-            'callback': callback,
-            'cb_args': cb_args,
-            'message': message,
-            'subject': subject,
-            }
+            "id": self._notif_id,
+            "time": time.time(),
+            "entity": entity,
+            "callback": callback,
+            "cb_args": cb_args,
+            "message": message,
+            "subject": subject,
+        }
         if widget is not None:
             notif_data[widget] = widget
         type_notifs.append(notif_data)
         self._notifications[self._notif_id] = notif_data
-        self.callListeners('notification', entity, notif_data, profile=profile)
+        self.callListeners("notification", entity, notif_data, profile=profile)
 
     def getNotifs(self, entity=None, type_=None, exact_jid=None, profile=C.PROF_KEY_NONE):
         """return notifications for given entity
@@ -696,7 +871,7 @@
             exact_jid = False
         else:
             if entity is None:
-                key = ''
+                key = ""
                 exact_jid = False
             else:
                 key = entity.bare
@@ -713,7 +888,7 @@
 
             for notifs in type_notifs:
                 for notif in notifs:
-                    if exact_jid and notif['entity'] != entity:
+                    if exact_jid and notif["entity"] != entity:
                         continue
                     yield notif
 
@@ -727,7 +902,7 @@
         @return (list[dict]): list of notifications
         """
         notif_dict = self.profiles[profile].notifications
-        key = '' if entity is None else entity.bare
+        key = "" if entity is None else entity.bare
         try:
             if type_ is None:
                 del notif_dict[key]
@@ -735,7 +910,7 @@
                 del notif_dict[key][type_]
         except KeyError:
             return
-        self.callListeners('notificationsClear', entity, type_, profile=profile)
+        self.callListeners("notificationsClear", entity, type_, profile=profile)
 
     def psEventHandler(self, category, service_s, node, event_type, data, profile):
         """Called when a PubSub event is received.
@@ -750,23 +925,35 @@
 
         if category == C.PS_MICROBLOG and self.MB_HANDLER:
             if event_type == C.PS_PUBLISH:
-                if not 'content' in data:
+                if not "content" in data:
                     log.warning("No content found in microblog data")
                     return
-                _groups = set(data_format.dict2iter('group', data)) or None  # FIXME: check if [] make sense (instead of None)
+                _groups = (
+                    set(data_format.dict2iter("group", data)) or None
+                )  # FIXME: check if [] make sense (instead of None)
 
                 for wid in self.widgets.getWidgets(quick_blog.QuickBlog):
                     wid.addEntryIfAccepted(service_s, node, data, _groups, profile)
 
                 try:
-                    comments_node, comments_service = data['comments_node'], data['comments_service']
+                    comments_node, comments_service = (
+                        data["comments_node"],
+                        data["comments_service"],
+                    )
                 except KeyError:
                     pass
                 else:
-                    self.bridge.mbGet(comments_service, comments_node, C.NO_LIMIT, [], {"subscribe":C.BOOL_TRUE}, profile=profile)
+                    self.bridge.mbGet(
+                        comments_service,
+                        comments_node,
+                        C.NO_LIMIT,
+                        [],
+                        {"subscribe": C.BOOL_TRUE},
+                        profile=profile,
+                    )
             elif event_type == C.PS_RETRACT:
                 for wid in self.widgets.getWidgets(quick_blog.QuickBlog):
-                    wid.deleteEntryIfPresent(service_s, node, data['id'], profile)
+                    wid.deleteEntryIfPresent(service_s, node, data["id"], profile)
                 pass
             else:
                 log.warning("Unmanaged PubSub event type {}".format(event_type))
@@ -776,11 +963,11 @@
 
     def progressFinishedHandler(self, pid, metadata, profile):
         log.info(u"Progress {} finished".format(pid))
-        self.callListeners('progressFinished', pid, metadata, profile=profile)
+        self.callListeners("progressFinished", pid, metadata, profile=profile)
 
     def progressErrorHandler(self, pid, err_msg, profile):
         log.warning(u"Progress {pid} error: {err_msg}".format(pid=pid, err_msg=err_msg))
-        self.callListeners('progressError', pid, err_msg, profile=profile)
+        self.callListeners("progressError", pid, err_msg, profile=profile)
 
     def _subscribe_cb(self, answer, data):
         entity, profile = data
@@ -793,23 +980,34 @@
         if type == "subscribed":
             # this is a subscription confirmation, we just have to inform user
             # TODO: call self.getEntityMBlog to add the new contact blogs
-            self.showDialog(_(u"The contact {contact} has accepted your subscription")
-                            .format(contact=entity.bare), _(u'Subscription confirmation'))
+            self.showDialog(
+                _(u"The contact {contact} has accepted your subscription").format(
+                    contact=entity.bare
+                ),
+                _(u"Subscription confirmation"),
+            )
         elif type == "unsubscribed":
             # this is a subscription refusal, we just have to inform user
-            self.showDialog(_(u"The contact {contact} has refused your subscription")
-                              .format(contact=entity.bare),
-                            _(u'Subscription refusal'),
-                            'error')
+            self.showDialog(
+                _(u"The contact {contact} has refused your subscription").format(
+                    contact=entity.bare
+                ),
+                _(u"Subscription refusal"),
+                "error",
+            )
         elif type == "subscribe":
             # this is a subscriptionn request, we have to ask for user confirmation
             # TODO: use sat.stdui.ui_contact_list to display the groups selector
-            self.showDialog(_(u"The contact {contact} wants to subscribe to your presence"
-                              u".\nDo you accept ?").format(contact=entity.bare),
-                              _('Subscription confirmation'),
-                              'yes/no',
-                              answer_cb=self._subscribe_cb,
-                              answer_data=(entity, profile))
+            self.showDialog(
+                _(
+                    u"The contact {contact} wants to subscribe to your presence"
+                    u".\nDo you accept ?"
+                ).format(contact=entity.bare),
+                _("Subscription confirmation"),
+                "yes/no",
+                answer_cb=self._subscribe_cb,
+                answer_data=(entity, profile),
+            )
 
     def showDialog(self, message, title, type="info", answer_cb=None, answer_data=None):
         """Show a dialog to user
@@ -832,7 +1030,7 @@
 
     def showAlert(self, message):
         # FIXME: doesn't seems used anymore, to remove?
-        pass  #FIXME
+        pass  # FIXME
 
     def dialogFailure(self, failure):
         log.warning(u"Failure: {}".format(failure))
@@ -849,13 +1047,16 @@
         raise NotImplementedError
 
     def paramUpdateHandler(self, name, value, namespace, profile):
-        log.debug(_(u"param update: [%(namespace)s] %(name)s = %(value)s") % {'namespace': namespace, 'name': name, 'value': value})
+        log.debug(
+            _(u"param update: [%(namespace)s] %(name)s = %(value)s")
+            % {"namespace": namespace, "name": name, "value": value}
+        )
         if (namespace, name) == ("Connection", "JabberID"):
             log.debug(_(u"Changing JID to %s") % value)
             self.profiles[profile].whoami = jid.JID(value)
-        elif (namespace, name) == ('General', C.SHOW_OFFLINE_CONTACTS):
+        elif (namespace, name) == ("General", C.SHOW_OFFLINE_CONTACTS):
             self.contact_lists[profile].showOfflineContacts(C.bool(value))
-        elif (namespace, name) == ('General', C.SHOW_EMPTY_GROUPS):
+        elif (namespace, name) == ("General", C.SHOW_EMPTY_GROUPS):
             self.contact_lists[profile].showEmptyGroups(C.bool(value))
 
     def contactDeletedHandler(self, jid_s, profile):
@@ -866,13 +1067,20 @@
         entity = jid.JID(entity_s)
         if key == "nick":  # this is the roster nick, not the MUC nick
             if entity in self.contact_lists[profile]:
-                self.contact_lists[profile].setCache(entity, 'nick', value)
-                self.callListeners('nick', entity, value, profile=profile)
+                self.contact_lists[profile].setCache(entity, "nick", value)
+                self.callListeners("nick", entity, value, profile=profile)
         elif key == "avatar" and self.AVATARS_HANDLER:
             if value and entity in self.contact_lists[profile]:
                 self.getAvatar(entity, ignore_cache=True, profile=profile)
 
-    def actionManager(self, action_data, callback=None, ui_show_cb=None, user_action=True, profile=C.PROF_KEY_NONE):
+    def actionManager(
+        self,
+        action_data,
+        callback=None,
+        ui_show_cb=None,
+        user_action=True,
+        profile=C.PROF_KEY_NONE,
+    ):
         """Handle backend action
 
         @param action_data(dict): action dict as sent by launchAction or returned by an UI action
@@ -882,29 +1090,40 @@
             else the action come from backend direclty (i.e. actionNew)
         """
         try:
-            xmlui = action_data.pop('xmlui')
+            xmlui = action_data.pop("xmlui")
         except KeyError:
             pass
         else:
-            ui = self.xmlui.create(self, xml_data=xmlui, flags=("FROM_BACKEND",) if not user_action else None, callback=callback, profile=profile)
+            ui = self.xmlui.create(
+                self,
+                xml_data=xmlui,
+                flags=("FROM_BACKEND",) if not user_action else None,
+                callback=callback,
+                profile=profile,
+            )
             if ui_show_cb is None:
                 ui.show()
             else:
                 ui_show_cb(ui)
 
         try:
-            progress_id = action_data.pop('progress')
+            progress_id = action_data.pop("progress")
         except KeyError:
             pass
         else:
             self.progressIdHandler(progress_id, profile)
 
         # we ignore metadata
-        action_data = {k:v for k,v in action_data.iteritems() if not k.startswith("meta_")}
+        action_data = {
+            k: v for k, v in action_data.iteritems() if not k.startswith("meta_")
+        }
 
         if action_data:
-            raise exceptions.DataError(u"Not all keys in action_data are managed ({keys})".format(keys=', '.join(action_data.keys())))
-
+            raise exceptions.DataError(
+                u"Not all keys in action_data are managed ({keys})".format(
+                    keys=", ".join(action_data.keys())
+                )
+            )
 
     def _actionCb(self, data, callback, callback_id, profile):
         if callback is None:
@@ -912,7 +1131,9 @@
         else:
             callback(data=data, cb_id=callback_id, profile=profile)
 
-    def launchAction(self, callback_id, data=None, callback=None, profile=C.PROF_KEY_NONE):
+    def launchAction(
+        self, callback_id, data=None, callback=None, profile=C.PROF_KEY_NONE
+    ):
         """Launch a dynamic action
 
         @param callback_id: id of the action to launch
@@ -929,9 +1150,19 @@
         if data is None:
             data = dict()
         action_cb = lambda data: self._actionCb(data, callback, callback_id, profile)
-        self.bridge.launchAction(callback_id, data, profile, callback=action_cb, errback=self.dialogFailure)
+        self.bridge.launchAction(
+            callback_id, data, profile, callback=action_cb, errback=self.dialogFailure
+        )
 
-    def launchMenu(self, menu_type, path, data=None, callback=None, security_limit=C.SECURITY_LIMIT_MAX, profile=C.PROF_KEY_NONE):
+    def launchMenu(
+        self,
+        menu_type,
+        path,
+        data=None,
+        callback=None,
+        security_limit=C.SECURITY_LIMIT_MAX,
+        profile=C.PROF_KEY_NONE,
+    ):
         """Launch a menu manually
 
         @param menu_type(unicode): type of the menu to launch
@@ -948,19 +1179,36 @@
         """
         if data is None:
             data = dict()
-        action_cb = lambda data: self._actionCb(data, callback, (menu_type, path), profile)
-        self.bridge.menuLaunch(menu_type, path, data, security_limit, profile, callback=action_cb, errback=self.dialogFailure)
+        action_cb = lambda data: self._actionCb(
+            data, callback, (menu_type, path), profile
+        )
+        self.bridge.menuLaunch(
+            menu_type,
+            path,
+            data,
+            security_limit,
+            profile,
+            callback=action_cb,
+            errback=self.dialogFailure,
+        )
 
     def _avatarGetCb(self, avatar_path, entity, contact_list, profile):
         path = avatar_path or self.getDefaultAvatar(entity)
         contact_list.setCache(entity, "avatar", path)
-        self.callListeners('avatar', entity, path, profile=profile)
+        self.callListeners("avatar", entity, path, profile=profile)
 
     def _avatarGetEb(self, failure, entity, contact_list):
         log.warning(u"Can't get avatar: {}".format(failure))
         contact_list.setCache(entity, "avatar", self.getDefaultAvatar(entity))
 
-    def getAvatar(self, entity, cache_only=True, hash_only=False, ignore_cache=False, profile=C.PROF_KEY_NONE):
+    def getAvatar(
+        self,
+        entity,
+        cache_only=True,
+        hash_only=False,
+        ignore_cache=False,
+        profile=C.PROF_KEY_NONE,
+    ):
         """return avatar path for an entity
 
         @param entity(jid.JID): entity to get avatar from
@@ -982,8 +1230,11 @@
                 cache_only,
                 hash_only,
                 profile=profile,
-                callback=lambda path: self._avatarGetCb(path, entity, contact_list, profile),
-                errback=lambda failure: self._avatarGetEb(failure, entity, contact_list))
+                callback=lambda path: self._avatarGetCb(
+                    path, entity, contact_list, profile
+                ),
+                errback=lambda failure: self._avatarGetEb(failure, entity, contact_list),
+            )
             # we set avatar to empty string to avoid requesting several time the same avatar
             # while we are waiting for avatarGet result
             contact_list.setCache(entity, "avatar", "")
@@ -999,7 +1250,7 @@
 
     def disconnect(self, profile):
         log.info("disconnecting")
-        self.callListeners('disconnect', profile=profile)
+        self.callListeners("disconnect", profile=profile)
         self.bridge.disconnect(profile)
 
     def onExit(self):
@@ -1007,7 +1258,7 @@
         to_unplug = []
         for profile, profile_manager in self.profiles.iteritems():
             if profile_manager.connected and profile_manager.autodisconnect:
-                #The user wants autodisconnection
+                # The user wants autodisconnection
                 self.disconnect(profile)
             to_unplug.append(profile)
         for profile in to_unplug: