bridge, quick_frontend: preparation for async bridge
bridge can currently have sync and async methods. This commit prepare the transition to fully async bridges:
- a new bridgeConnect method must be called to prepare the bridge
- quick app, quick profile manager: changed sync calls to async ones
- quick app: bridgeConnect can be called automatically or manually depending on connect_bridge parameter of QuickApp
This commit is contained in:
parent
58795c675c
commit
34cec8fe14
6 changed files with 82 additions and 37 deletions
|
|
@ -60,7 +60,8 @@ def dbus_to_bridge_exception(dbus_e):
|
|||
|
||||
|
||||
class Bridge(BridgeFrontend):
|
||||
def __init__(self):
|
||||
|
||||
def bridgeConnect(self, callback, errback):
|
||||
try:
|
||||
self.sessions_bus = dbus.SessionBus()
|
||||
self.db_object = self.sessions_bus.get_object(const_INT_PREFIX,
|
||||
|
|
@ -72,12 +73,13 @@ class Bridge(BridgeFrontend):
|
|||
except dbus.exceptions.DBusException, e:
|
||||
if e._dbus_error_name in ('org.freedesktop.DBus.Error.ServiceUnknown',
|
||||
'org.freedesktop.DBus.Error.Spawn.ExecFailed'):
|
||||
raise BridgeExceptionNoService
|
||||
errback(BridgeExceptionNoService())
|
||||
elif e._dbus_error_name == 'org.freedesktop.DBus.Error.NotSupported':
|
||||
log.error(_(u"D-Bus is not launched, please see README to see instructions on how to launch it"))
|
||||
raise BridgeInitError
|
||||
errback(BridgeInitError)
|
||||
else:
|
||||
raise e
|
||||
errback(e)
|
||||
callback()
|
||||
#props = self.db_core_iface.getProperties()
|
||||
|
||||
def register_signal(self, functionName, handler, iface="core"):
|
||||
|
|
|
|||
|
|
@ -54,9 +54,18 @@ class ProfileManager(object):
|
|||
|
||||
def __init__(self, profile):
|
||||
self.profile = profile
|
||||
self.connected = False
|
||||
self.whoami = None
|
||||
self.notifications = {} # key: bare jid or '' for general, value: notif data
|
||||
|
||||
@property
|
||||
def autodisconnect(self):
|
||||
try:
|
||||
autodisconnect = self._autodisconnect
|
||||
except AttributeError:
|
||||
autodisconnect = False
|
||||
return autodisconnect
|
||||
|
||||
def plug(self):
|
||||
"""Plug the profile to the host"""
|
||||
# we get the essential params
|
||||
|
|
@ -65,12 +74,22 @@ class ProfileManager(object):
|
|||
|
||||
def _plug_profile_jid(self, jid_s):
|
||||
self.whoami = jid.JID(jid_s) # resource might change after the connection
|
||||
self.bridge.isConnected(self.profile, callback=self._plug_profile_isconnected)
|
||||
|
||||
def _plug_profile_isconnected(self, connected):
|
||||
self.connected = connected
|
||||
self.bridge.asyncGetParamA("autodisconnect", "Connection", profile_key=self.profile,
|
||||
callback=self._plug_profile_autodisconnect, errback=self._getParamError)
|
||||
|
||||
def _plug_profile_autodisconnect(self, autodisconnect):
|
||||
if C.bool(autodisconnect):
|
||||
self._autodisconnect = True
|
||||
self.bridge.asyncGetParamA("autoconnect", "Connection", profile_key=self.profile,
|
||||
callback=self._plug_profile_autoconnect, errback=self._getParamError)
|
||||
|
||||
def _plug_profile_autoconnect(self, value_str):
|
||||
autoconnect = C.bool(value_str)
|
||||
if autoconnect and not self.bridge.isConnected(self.profile):
|
||||
if autoconnect and not self.connected:
|
||||
self.host.asyncConnect(self.profile, callback=lambda dummy: self._plug_profile_afterconnect())
|
||||
else:
|
||||
self._plug_profile_afterconnect()
|
||||
|
|
@ -78,6 +97,7 @@ class ProfileManager(object):
|
|||
def _plug_profile_afterconnect(self):
|
||||
# Profile can be connected or not
|
||||
# we get cached data
|
||||
self.connected = True
|
||||
self.host.bridge.getFeatures(profile_key=self.profile, callback=self._plug_profile_getFeaturesCb, errback=self._plug_profile_getFeaturesEb)
|
||||
|
||||
def _plug_profile_getFeaturesEb(self, failure):
|
||||
|
|
@ -100,7 +120,7 @@ class ProfileManager(object):
|
|||
for key, value in data.iteritems():
|
||||
self.host.entityDataUpdatedHandler(entity_s, key, value, self.profile)
|
||||
|
||||
if not self.bridge.isConnected(self.profile):
|
||||
if not self.connected:
|
||||
self.host.setPresenceStatus(C.PRESENCE_UNAVAILABLE, '', profile=self.profile)
|
||||
else:
|
||||
|
||||
|
|
@ -142,8 +162,8 @@ class ProfileManager(object):
|
|||
# and we launch frontend specific method
|
||||
self.host.profilePlugged(self.profile)
|
||||
|
||||
def _getParamError(self, ignore):
|
||||
log.error(_("Can't get profile parameter"))
|
||||
def _getParamError(self, failure):
|
||||
log.error(_("Can't get profile parameter: {msg}").format(msg=failure))
|
||||
|
||||
|
||||
class ProfilesManager(object):
|
||||
|
|
@ -164,6 +184,9 @@ class ProfilesManager(object):
|
|||
def __len__(self):
|
||||
return len(self._profiles)
|
||||
|
||||
def iteritems(self):
|
||||
return self._profiles.iteritems()
|
||||
|
||||
def plug(self, profile):
|
||||
if profile in self._profiles:
|
||||
raise exceptions.ConflictError('A profile of the name [{}] is already plugged'.format(profile))
|
||||
|
|
@ -189,10 +212,10 @@ class QuickApp(object):
|
|||
MB_HANDLER = True # Set to False if the frontend doesn't manage microblog
|
||||
AVATARS_HANDLER = True # set to False if avatars are not used
|
||||
|
||||
def __init__(self, create_bridge, xmlui, check_options=None):
|
||||
def __init__(self, bridge_factory, xmlui, check_options=None, connect_bridge=True):
|
||||
"""Create a frontend application
|
||||
|
||||
@param create_bridge: method to use to create the Bridge
|
||||
@param bridge_factory: method to use to create the Bridge
|
||||
@param xmlui: xmlui module
|
||||
@param check_options: method to call to check options (usually command line arguments)
|
||||
"""
|
||||
|
|
@ -220,15 +243,19 @@ class QuickApp(object):
|
|||
self.trigger = trigger.TriggerManager() # trigger are used to change the default behaviour
|
||||
|
||||
## bridge ##
|
||||
try:
|
||||
self.bridge = create_bridge()
|
||||
except exceptions.BridgeExceptionNoService:
|
||||
print(_(u"Can't connect to SàT backend, are you sure it's launched ?"))
|
||||
sys.exit(1)
|
||||
except exceptions.BridgeInitError:
|
||||
print(_(u"Can't init bridge"))
|
||||
sys.exit(1)
|
||||
self.bridge = bridge_factory()
|
||||
ProfileManager.bridge = self.bridge
|
||||
if connect_bridge:
|
||||
self.connectBridge()
|
||||
|
||||
self._notif_id = 0
|
||||
self._notifications = OrderedDict()
|
||||
self.features = None
|
||||
|
||||
def connectBridge(self):
|
||||
self.bridge.bridgeConnect(callback=self._bridgeCb, errback=self._bridgeEb)
|
||||
|
||||
def _bridgeCb(self):
|
||||
self.registerSignal("connected")
|
||||
self.registerSignal("disconnected")
|
||||
self.registerSignal("actionNew")
|
||||
|
|
@ -255,10 +282,15 @@ class QuickApp(object):
|
|||
quick_games.Quiz.registerSignals(self)
|
||||
quick_games.Radiocol.registerSignals(self)
|
||||
|
||||
self._notif_id = 0
|
||||
self._notifications = OrderedDict()
|
||||
self.media_dir = self.bridge.getConfig('', 'media_dir')
|
||||
self.features = None
|
||||
def _bridgeEb(self, failure):
|
||||
if isinstance(failure, exceptions.BridgeExceptionNoService):
|
||||
print(_(u"Can't connect to SàT backend, are you sure it's launched ?"))
|
||||
sys.exit(1)
|
||||
elif isinstance(failure, exceptions.BridgeInitError):
|
||||
print(_(u"Can't init bridge"))
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(_(u"Error while initialising bridge: {}".format(failure)))
|
||||
|
||||
@property
|
||||
def current_profile(self):
|
||||
|
|
@ -871,11 +903,10 @@ class QuickApp(object):
|
|||
def onExit(self):
|
||||
"""Must be called when the frontend is terminating"""
|
||||
to_unplug = []
|
||||
for profile in self.profiles:
|
||||
if self.bridge.isConnected(profile):
|
||||
if C.bool(self.bridge.getParamA("autodisconnect", "Connection", profile_key=profile)):
|
||||
#The user wants autodisconnection
|
||||
self.disconnect(profile)
|
||||
for profile, profile_manager in self.profiles.iteritems():
|
||||
if profile_manager.connected(profile) and profile_manager.autodisconnect:
|
||||
#The user wants autodisconnection
|
||||
self.disconnect(profile)
|
||||
to_unplug.append(profile)
|
||||
for profile in to_unplug:
|
||||
self.unplug_profile(profile)
|
||||
|
|
|
|||
|
|
@ -108,15 +108,22 @@ class QuickProfileManager(object):
|
|||
self._autoconnect=False
|
||||
self.host.actionManager(data, callback=authenticate_cb, profile=profile)
|
||||
|
||||
for profile_key in profile_keys:
|
||||
profile = self.host.bridge.getProfileName(profile_key)
|
||||
def getProfileNameCb(profile):
|
||||
if not profile:
|
||||
# FIXME: this method is not handling manual mode correclty anymore
|
||||
# must be thought to be handled asynchronously
|
||||
self._autoconnect = False # manual mode
|
||||
msg = _("Trying to plug an unknown profile key ({})".format(profile_key))
|
||||
log.warning(msg)
|
||||
self.showDialog(_("Profile plugging in error"), msg, 'error')
|
||||
break
|
||||
self.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=profile)
|
||||
self.host.showDialog(_("Profile plugging in error"), msg, 'error')
|
||||
else:
|
||||
self.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=profile)
|
||||
|
||||
def getProfileNameEb(failure):
|
||||
log.error(u"Can't retrieve profile name: {}".format(failure))
|
||||
|
||||
for profile_key in profile_keys:
|
||||
self.host.bridge.getProfileName(profile_key, callback=getProfileNameCb, errback=getProfileNameEb)
|
||||
|
||||
|
||||
def getParamError(self, dummy):
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ class Constructor(object):
|
|||
@param name: dictionary of arguments name like given by getArgumentsDoc
|
||||
@param default: dictionary of default values, like given by getDefault
|
||||
@param unicode_protect: activate unicode protection on strings (return strings as unicode(str))
|
||||
@return: list of arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")
|
||||
@return (str): arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")
|
||||
"""
|
||||
idx = 0
|
||||
attr_string = []
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ def dbus_to_bridge_exception(dbus_e):
|
|||
|
||||
|
||||
class Bridge(BridgeFrontend):
|
||||
def __init__(self):
|
||||
|
||||
def bridgeConnect(self, callback, errback):
|
||||
try:
|
||||
self.sessions_bus = dbus.SessionBus()
|
||||
self.db_object = self.sessions_bus.get_object(const_INT_PREFIX,
|
||||
|
|
@ -72,12 +73,13 @@ class Bridge(BridgeFrontend):
|
|||
except dbus.exceptions.DBusException, e:
|
||||
if e._dbus_error_name in ('org.freedesktop.DBus.Error.ServiceUnknown',
|
||||
'org.freedesktop.DBus.Error.Spawn.ExecFailed'):
|
||||
raise BridgeExceptionNoService
|
||||
errback(BridgeExceptionNoService())
|
||||
elif e._dbus_error_name == 'org.freedesktop.DBus.Error.NotSupported':
|
||||
log.error(_(u"D-Bus is not launched, please see README to see instructions on how to launch it"))
|
||||
raise BridgeInitError
|
||||
errback(BridgeInitError)
|
||||
else:
|
||||
raise e
|
||||
errback(e)
|
||||
callback()
|
||||
#props = self.db_core_iface.getProperties()
|
||||
|
||||
def register_signal(self, functionName, handler, iface="core"):
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ class _Bridge(object):
|
|||
"plugin": {}
|
||||
}
|
||||
|
||||
def bridgeConnect(self, callback, errback):
|
||||
callback()
|
||||
|
||||
def register_method(self, name, callback):
|
||||
log.debug(u"registering embedded bridge method [{}]".format(name))
|
||||
if name in self._methods_cbs:
|
||||
|
|
|
|||
Loading…
Reference in a new issue