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:
Goffi 2016-12-13 22:27:48 +01:00
commit 34cec8fe14

View file

@ -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)