# HG changeset patch # User Goffi # Date 1447792138 -3600 # Node ID 5b24d6bf5d157ecf7fe43572bc97be57d793cc23 # Parent a17a91531fbe77e779c2b8868be2bc63d193df01 core, bridge: actionsGet: - added a new mechanism to keep actions until they are answered (or timeout-ed) - keep_id must be explicitly used on actionNew - actionsGet is used to retrive these actions - the mechanism is used in deferXMLUI diff -r a17a91531fbe -r 5b24d6bf5d15 frontends/src/bridge/DBus.py --- a/frontends/src/bridge/DBus.py Tue Nov 17 20:18:51 2015 +0100 +++ b/frontends/src/bridge/DBus.py Tue Nov 17 21:28:58 2015 +0100 @@ -123,6 +123,20 @@ return getPluginMethod + def actionsGet(self, profile_key="@DEFAULT@", 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)) + kwargs={} + if callback is not None: + kwargs['timeout'] = const_TIMEOUT + kwargs['reply_handler'] = callback + kwargs['error_handler'] = error_handler + return self.db_core_iface.actionsGet(profile_key, **kwargs) + def addContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None): if callback is None: error_handler = None diff -r a17a91531fbe -r 5b24d6bf5d15 src/bridge/DBus.py --- a/src/bridge/DBus.py Tue Nov 17 20:18:51 2015 +0100 +++ b/src/bridge/DBus.py Tue Nov 17 21:28:58 2015 +0100 @@ -213,6 +213,12 @@ ### methods ### @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, + in_signature='s', out_signature='a(a{ss}si)', + async_callbacks=None) + def actionsGet(self, profile_key="@DEFAULT@"): + return self._callback("actionsGet", unicode(profile_key)) + + @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, in_signature='ss', out_signature='', async_callbacks=None) def addContact(self, entity_jid, profile_key="@DEFAULT@"): diff -r a17a91531fbe -r 5b24d6bf5d15 src/bridge/bridge_constructor/bridge_template.ini --- a/src/bridge/bridge_constructor/bridge_template.ini Tue Nov 17 20:18:51 2015 +0100 +++ b/src/bridge/bridge_constructor/bridge_template.ini Tue Nov 17 21:28:58 2015 +0100 @@ -632,6 +632,16 @@ doc_return=dict where key can be: - xmlui: a XMLUI need to be displayed +[actionsGet] +type=method +category=core +sig_in=s +sig_out=a(a{ss}si) +param_0_default="@DEFAULT@" +doc=Get all not yet answered actions +doc_param_0=%(doc_profile_key)s +doc_return=list of data as for [actionNew] (without the profile) + [confirmationAnswer] deprecated= type=method diff -r a17a91531fbe -r 5b24d6bf5d15 src/core/sat_main.py --- a/src/core/sat_main.py Tue Nov 17 20:18:51 2015 +0100 +++ b/src/core/sat_main.py Tue Nov 17 21:28:58 2015 +0100 @@ -102,6 +102,7 @@ self.bridge.register("delContact", self._delContact) self.bridge.register("isConnected", self.isConnected) self.bridge.register("launchAction", self.launchCallback) + self.bridge.register("actionsGet", self.actionsGet) self.bridge.register("confirmationAnswer", self.confirmationAnswer) self.bridge.register("progressGet", self._progressGet) self.bridge.register("progressGetAll", self._progressGetAll) @@ -785,16 +786,36 @@ del client._waiting_conf[conf_id] cb(conf_id, accepted, data, profile) - def actionNew(self, action_data, security_limit=C.NO_SECURITY_LIMIT, profile=C.PROF_KEY_NONE): - """Shortcut to bridge.actionNew which generate and id + def _killAction(self, keep_id, client): + log.debug(u"Killing action {} for timeout".format(keep_id)) + client.actions[keep_id] + + def actionNew(self, action_data, security_limit=C.NO_SECURITY_LIMIT, keep_id=None, profile=C.PROF_KEY_NONE): + """Shortcut to bridge.actionNew which generate and id and keep for retrieval @param action_data(dict): action data (see bridge documentation) @param security_limit: %(doc_security_limit)s + @param keep_id(None, unicode): if not None, used to keep action for differed retrieval + must be set to the callback_id + action will be deleted after 30 min. @param profile: %(doc_profile)s """ id_ = unicode(uuid.uuid4()) + if keep_id is not None: + client = self.getClient(profile) + action_timer = reactor.callLater(60*30, self._killAction) + client.actions[keep_id] = (action_data, id_, security_limit, action_timer) + self.bridge.actionNew(action_data, id_, security_limit, profile) + def actionsGet(self, profile): + """Return current non answered actions + + @param profile: %(doc_profile)s + """ + client = self.getClient(profile) + return [action_tuple[:-1] for action_tuple in client.actions.itervalues()] + def registerProgressCb(self, progress_id, callback, profile): """Register a callback called when progress is requested for id""" client = self.getClient(profile) @@ -904,9 +925,13 @@ - C.BOOL_TRUE - C.BOOL_FALSE """ - profile = self.memory.getProfileName(profile_key) - if not profile: - raise exceptions.ProfileUnknownError(_('trying to launch action with a non-existant profile')) + client = self.getClient(profile_key) + try: + action_tuple = client.actions[callback_id] + except KeyError: + pass + else: + action_tuple[-1].cancel() # the last item is the action timer try: callback, args, kwargs = self._cb_map[callback_id] @@ -918,7 +943,7 @@ raise exceptions.DataError("Required data for this callback is missing") args,kwargs=list(args)[:],kwargs.copy() # we don't want to modify the original (kw)args args.insert(0, data) - kwargs["profile"] = profile + kwargs["profile"] = client.profile del kwargs["with_data"] if kwargs.pop('one_shot', False): diff -r a17a91531fbe -r 5b24d6bf5d15 src/core/xmpp.py --- a/src/core/xmpp.py Tue Nov 17 20:18:51 2015 +0100 +++ b/src/core/xmpp.py Tue Nov 17 21:28:58 2015 +0100 @@ -45,6 +45,7 @@ self.conn_deferred = defer.Deferred() self._waiting_conf = {} # callback called when a confirmation is received self._progress_cb = {} # callback called when a progress is requested (key = progress id) + self.actions = {} # used to keep track of actions for retrieval (key = action_id) def getConnectionDeferred(self): """Return a deferred which fire when the client is connected""" diff -r a17a91531fbe -r 5b24d6bf5d15 src/tools/xml_tools.py --- a/src/tools/xml_tools.py Tue Nov 17 20:18:51 2015 +0100 +++ b/src/tools/xml_tools.py Tue Nov 17 21:28:58 2015 +0100 @@ -1271,7 +1271,7 @@ action_data = {'xmlui': xmlui.toXml()} if action_extra is not None: action_data.update(action_extra) - host.actionNew(action_data, profile=profile) + host.actionNew(action_data, keep_id=xmlui.submit_id, profile=profile) return xmlui_d def deferDialog(host, message, title=u'Please confirm', type_=C.XMLUI_DIALOG_CONFIRM, options=None,