changeset 1482:80cd55dd5b04

core, bridge: added getFeatures method: this async method indicate which plugins are activated, and add an additional data dictionary with plugin specific data. The result can be general (if profile==C.PROF_KEY_NONE) or specific to profile.
author Goffi <goffi@goffi.org>
date Fri, 21 Aug 2015 17:08:26 +0200 (2015-08-21)
parents 621b045cd284
children 0f0889028eea
files frontends/src/bridge/DBus.py src/bridge/DBus.py src/bridge/bridge_constructor/bridge_template.ini src/core/sat_main.py
diffstat 4 files changed, 74 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/frontends/src/bridge/DBus.py	Thu Aug 20 18:44:39 2015 +0200
+++ b/frontends/src/bridge/DBus.py	Fri Aug 21 17:08:26 2015 +0200
@@ -293,6 +293,15 @@
             kwargs['error_handler'] = error_handler
         return self.db_core_iface.getEntityData(jid, keys, profile, **kwargs)
 
+    def getFeatures(self, profile_key, callback=None, errback=None):
+        if callback is None:
+            error_handler = None
+        else:
+            if errback is None:
+                errback = log.error
+            error_handler = lambda err:errback(dbus_to_bridge_exception(err))
+        return self.db_core_iface.getFeatures(profile_key, timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler)
+
     def getHistory(self, from_jid, to_jid, limit, between=True, search='', profile="@NONE@", callback=None, errback=None):
         if callback is None:
             error_handler = None
--- a/src/bridge/DBus.py	Thu Aug 20 18:44:39 2015 +0200
+++ b/src/bridge/DBus.py	Fri Aug 21 17:08:26 2015 +0200
@@ -288,6 +288,12 @@
         return self._callback("getEntityData", unicode(jid), keys, unicode(profile))
 
     @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
+                         in_signature='s', out_signature='a{sa{ss}}',
+                         async_callbacks=('callback', 'errback'))
+    def getFeatures(self, profile_key, callback=None, errback=None):
+        return self._callback("getFeatures", unicode(profile_key), callback=callback, errback=errback)
+
+    @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
                          in_signature='ssibss', out_signature='a(dssssa{ss})',
                          async_callbacks=('callback', 'errback'))
     def getHistory(self, from_jid, to_jid, limit, between=True, search='', profile="@NONE@", callback=None, errback=None):
--- a/src/bridge/bridge_constructor/bridge_template.ini	Thu Aug 20 18:44:39 2015 +0200
+++ b/src/bridge/bridge_constructor/bridge_template.ini	Fri Aug 21 17:08:26 2015 +0200
@@ -175,6 +175,18 @@
 sig_out=s
 doc=Get "Salut à Toi" full version
 
+[getFeatures]
+type=method
+category=core
+sig_in=s
+sig_out=a{sa{ss}}
+doc=Get available features and plugins
+ features can changes for differents profiles, e.g. because of differents server capabilities
+doc_param_0=%(doc_profile_key)s
+doc_return=dictionary of available features:
+ plugin import name is used as key, data is an other dict managed by the plugin
+async=
+
 [getProfileName]
 type=method
 category=core
--- a/src/core/sat_main.py	Thu Aug 20 18:44:39 2015 +0200
+++ b/src/core/sat_main.py	Fri Aug 21 17:08:26 2015 +0200
@@ -87,6 +87,7 @@
             sys.exit(1)
         self.bridge.register("getReady", lambda: self._initialised)
         self.bridge.register("getVersion", lambda: self.full_version)
+        self.bridge.register("getFeatures", self.getFeatures)
         self.bridge.register("getProfileName", self.memory.getProfileName)
         self.bridge.register("getProfilesList", self.memory.getProfilesList)
         self.bridge.register("getEntityData", lambda jid_, keys, profile: self.memory.getEntityData(jid.JID(jid_), keys, profile))
@@ -340,6 +341,52 @@
             if disconnected_cb:
                 disconnected_cb(profile)
 
+    def getFeatures(self, profile_key=C.PROF_KEY_NONE):
+        """Get available features
+
+        Return list of activated plugins and plugin specific data
+        @param profile_key: %(doc_profile_key)s
+            C.PROF_KEY_NONE can be used to have general plugins data (i.e. not profile dependent)
+        @return (dict)[Deferred]: features data where:
+            - key is plugin import name, present only for activated plugins
+            - value is a an other dict, when meaning is specifif to each plugin.
+                this dict is return by plugin's getFeature method.
+                If this method doesn't exists, an empty dict is returned.
+        """
+        try:
+            # FIXME: there is no method yet to check profile session
+            #        as soon as one is implemented, it should be used here
+            self.getClient(profile_key)
+        except KeyError:
+            log.warning("Requesting features for a profile outside a session")
+            profile_key = C.PROF_KEY_NONE
+        except exceptions.ProfileNotSetError:
+            pass
+
+        features = []
+        for import_name, plugin in self.plugins.iteritems():
+            try:
+                features_d = defer.maybeDeferred(plugin.getFeatures, profile_key)
+            except AttributeError:
+                features_d = defer.succeed({})
+            features.append(features_d)
+
+        d_list = defer.DeferredList(features)
+        def buildFeatures(result, import_names):
+            assert len(result) == len(import_names)
+            ret = {}
+            for name, (success, data) in zip (import_names, result):
+                if success:
+                    ret[name] = data
+                else:
+                    log.warning(u"Error while getting features for {name}: {failure}".format(
+                        name=name, failure=data))
+                    ret[name] = {}
+            return ret
+
+        d_list.addCallback(buildFeatures, self.plugins.keys())
+        return d_list
+
     def getContacts(self, profile_key):
         client = self.getClient(profile_key)
         def got_roster(dummy):