Mercurial > libervia-backend
diff src/core/sat_main.py @ 759:93bd868b8fb6
backend, frontends: callbacks refactoring:
- launchAction is now async, and return a dictionary for its result
- no more action_id, actionResult* are deprecated
- callback system is about to be unified
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 24 Dec 2013 15:19:08 +0100 |
parents | e3ad48a2aab2 |
children | e1c64a5b4588 |
line wrap: on
line diff
--- a/src/core/sat_main.py Tue Dec 24 15:19:08 2013 +0100 +++ b/src/core/sat_main.py Tue Dec 24 15:19:08 2013 +0100 @@ -42,6 +42,7 @@ from sat.tools.xml_tools import tupleList2dataForm from sat.tools.misc import TriggerManager from glob import glob +from uuid import uuid4 try: from twisted.words.protocols.xmlstream import XMPPHandler @@ -103,10 +104,8 @@ CONST[name] = value def __init__(self): - #TODO: standardize callback system - - self.__general_cb_map = {} # callback called for general reasons (key = name) - self.__private_data = {} # used for internal callbacks (key = id) + self._cb_map = {} # map from callback_id to callbacks + self.__private_data = {} # used for internal callbacks (key = id) FIXME: to be removed self.profiles = {} self.plugins = {} self.menus = {} # dynamic menus. key: (type, category, name), value: menu data (dictionnary) @@ -157,7 +156,7 @@ self.bridge.register("updateContact", self.updateContact) self.bridge.register("delContact", self.delContact) self.bridge.register("isConnected", self.isConnected) - self.bridge.register("launchAction", self.launchAction) + self.bridge.register("launchAction", self.launchCallback) self.bridge.register("confirmationAnswer", self.confirmationAnswer) self.bridge.register("getProgress", self.getProgress) self.bridge.register("getMenus", self.getMenus) @@ -388,7 +387,8 @@ return next_id - def registerNewAccountCB(self, id, data, profile): + def registerNewAccountCB(self, data, profile): + # FIXME: to be removed/redone elsewhere user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0] password = self.memory.getParamA("Password", "Connection", profile_key=profile) server = self.memory.getParamA("Server", "Connection", profile_key=profile) @@ -407,8 +407,6 @@ {"message": _("Are you sure to register new account [%(user)s] to server %(server)s ?") % {'user': user, 'server': server, 'profile': profile}}, self.regisConfirmCB, profile) print "===============+++++++++++ REGISTER NEW ACCOUNT++++++++++++++============" - print "id=", id - print "data=", data def regisConfirmCB(self, id, accepted, data, profile): print _("register Confirmation CB ! (%s)") % str(accepted) @@ -428,6 +426,7 @@ @param fields: list of tuples (name, value) @return: tuple: (id, deferred) """ + # FIXME: to be removed profile = self.memory.getProfileName(profile_key) assert(profile) @@ -469,29 +468,6 @@ return False return self.profiles[profile].isConnected() - def launchAction(self, type, data, profile_key): - """Launch a specific action asked by client - @param type: action type (button) - @param data: needed data to launch the action - - @return: action id for result, or empty string in case or error - """ - profile = self.memory.getProfileName(profile_key) - if not profile: - error(_('trying to launch action with a non-existant profile')) - raise Exception # TODO: raise a proper exception - if type == "button": - try: - cb_name = data['callback_id'] - except KeyError: - error(_("Incomplete data")) - return "" - id = sat_next_id() - self.callGeneralCB(cb_name, id, data, profile=profile) - return id - else: - error(_("Unknown action type")) - return "" ## jabber methods ## @@ -808,6 +784,7 @@ @param data: data (depend of confirmation conf_type) @param cb: callback called with the answer """ + # FIXME: use XMLUI and *callback methods for dialog client = self.getClient(profile) if not client: raise exceptions.ProfileUnknownError(_("Asking confirmation a non-existant profile")) @@ -863,24 +840,53 @@ #debug("Requested progress for unknown progress_id") return data - def registerGeneralCB(self, name, CB): - """Register a callback called for general reason""" - self.__general_cb_map[name] = CB - - def removeGeneralCB(self, name): - """Remove a general callback""" - if name not in self.__general_cb_map: - error(_("Trying to remove an unknow general callback")) + def registerCallback(self, callback, *args, **kwargs): + """ Register a callback. + Use with_data=True in kwargs if the callback use the optional data dict + use force_id=id to avoid generated id. Can lead to name conflict, avoid if possible + @param callback: any callable + @return: id of the registered callback + """ + callback_id = kwargs.pop('force_id', None) + if callback_id is None: + callback_id = str(uuid4()) else: - del self.__general_cb_map[name] + if callback_id in self._cb_map: + raise exceptions.ConflictError(_(u"id already registered")) + self._cb_map[callback_id] = (callback, args, kwargs) + return callback_id + + def removeCallback(self, callback_id): + """ Remove a previously registered callback + @param callback_id: id returned by [registerCallback] """ + del self._cb_map[callback_id] - def callGeneralCB(self, name, *args, **kwargs): - """Call general function back""" + def launchCallback(self, callback_id, data=None, profile_key="@NONE@"): + """Launch a specific callback + @param callback_id: id of the action (callback) to launch + @param data: optional data + @profile_key: %(doc_profile_key)s + @return: a deferred which fire a dict where key can be: + - xmlui: a XMLUI need to be displayed + """ + profile = self.memory.getProfileName(profile_key) + if not profile: + raise exceptions.ProfileUnknownError(_('trying to launch action with a non-existant profile')) + try: - return self.__general_cb_map[name](*args, **kwargs) + callback, args, kwargs = self._cb_map[callback_id] except KeyError: - error(_("Trying to call unknown function (%s)") % name) - return None + raise exceptions.DataError("Unknown callback id") + + if kwargs.get("with_data", False): + if data is None: + 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 + del kwargs["with_data"] + + return defer.maybeDeferred(callback, *args, **kwargs) #Menus management @@ -925,6 +931,7 @@ @param profile_key: %(doc_profile_key)s @return: XMLUI or empty string if it's a one shot menu """ + # TODO: menus should use launchCallback profile = self.memory.getProfileName(profile_key) if not profile: raise exceptions.ProfileUnknownError