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
This commit is contained in:
parent
aa8ca0772c
commit
069a250b04
1 changed files with 151 additions and 78 deletions
|
|
@ -42,6 +42,7 @@ from sat.memory.memory import Memory
|
|||
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 @@ class SAT(service.Service):
|
|||
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 @@ class SAT(service.Service):
|
|||
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 @@ class SAT(service.Service):
|
|||
|
||||
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 @@ class SAT(service.Service):
|
|||
{"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 @@ class SAT(service.Service):
|
|||
@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 @@ class SAT(service.Service):
|
|||
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 @@ class SAT(service.Service):
|
|||
@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 @@ class SAT(service.Service):
|
|||
#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 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'))
|
||||
|
||||
def callGeneralCB(self, name, *args, **kwargs):
|
||||
"""Call general function back"""
|
||||
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 @@ class SAT(service.Service):
|
|||
@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
|
||||
|
|
|
|||
Loading…
Reference in a new issue