# HG changeset patch # User Goffi # Date 1440169706 -7200 # Node ID 80cd55dd5b0484934b9927365415f9584d623971 # Parent 621b045cd2842e5d83dc9822a7aedf4b8e06778c 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. diff -r 621b045cd284 -r 80cd55dd5b04 frontends/src/bridge/DBus.py --- 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 diff -r 621b045cd284 -r 80cd55dd5b04 src/bridge/DBus.py --- 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): diff -r 621b045cd284 -r 80cd55dd5b04 src/bridge/bridge_constructor/bridge_template.ini --- 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 diff -r 621b045cd284 -r 80cd55dd5b04 src/core/sat_main.py --- 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):