Mercurial > libervia-backend
comparison frontends/src/quick_frontend/quick_app.py @ 2091:f413bfc24458
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
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 13 Dec 2016 22:27:48 +0100 |
parents | 0931b5a6213c |
children | 4bc408b549cd |
comparison
equal
deleted
inserted
replaced
2090:52bd463e6fe7 | 2091:f413bfc24458 |
---|---|
52 bridge = None | 52 bridge = None |
53 cache_keys_to_get = ['avatar'] | 53 cache_keys_to_get = ['avatar'] |
54 | 54 |
55 def __init__(self, profile): | 55 def __init__(self, profile): |
56 self.profile = profile | 56 self.profile = profile |
57 self.connected = False | |
57 self.whoami = None | 58 self.whoami = None |
58 self.notifications = {} # key: bare jid or '' for general, value: notif data | 59 self.notifications = {} # key: bare jid or '' for general, value: notif data |
60 | |
61 @property | |
62 def autodisconnect(self): | |
63 try: | |
64 autodisconnect = self._autodisconnect | |
65 except AttributeError: | |
66 autodisconnect = False | |
67 return autodisconnect | |
59 | 68 |
60 def plug(self): | 69 def plug(self): |
61 """Plug the profile to the host""" | 70 """Plug the profile to the host""" |
62 # we get the essential params | 71 # we get the essential params |
63 self.bridge.asyncGetParamA("JabberID", "Connection", profile_key=self.profile, | 72 self.bridge.asyncGetParamA("JabberID", "Connection", profile_key=self.profile, |
64 callback=self._plug_profile_jid, errback=self._getParamError) | 73 callback=self._plug_profile_jid, errback=self._getParamError) |
65 | 74 |
66 def _plug_profile_jid(self, jid_s): | 75 def _plug_profile_jid(self, jid_s): |
67 self.whoami = jid.JID(jid_s) # resource might change after the connection | 76 self.whoami = jid.JID(jid_s) # resource might change after the connection |
77 self.bridge.isConnected(self.profile, callback=self._plug_profile_isconnected) | |
78 | |
79 def _plug_profile_isconnected(self, connected): | |
80 self.connected = connected | |
81 self.bridge.asyncGetParamA("autodisconnect", "Connection", profile_key=self.profile, | |
82 callback=self._plug_profile_autodisconnect, errback=self._getParamError) | |
83 | |
84 def _plug_profile_autodisconnect(self, autodisconnect): | |
85 if C.bool(autodisconnect): | |
86 self._autodisconnect = True | |
68 self.bridge.asyncGetParamA("autoconnect", "Connection", profile_key=self.profile, | 87 self.bridge.asyncGetParamA("autoconnect", "Connection", profile_key=self.profile, |
69 callback=self._plug_profile_autoconnect, errback=self._getParamError) | 88 callback=self._plug_profile_autoconnect, errback=self._getParamError) |
70 | 89 |
71 def _plug_profile_autoconnect(self, value_str): | 90 def _plug_profile_autoconnect(self, value_str): |
72 autoconnect = C.bool(value_str) | 91 autoconnect = C.bool(value_str) |
73 if autoconnect and not self.bridge.isConnected(self.profile): | 92 if autoconnect and not self.connected: |
74 self.host.asyncConnect(self.profile, callback=lambda dummy: self._plug_profile_afterconnect()) | 93 self.host.asyncConnect(self.profile, callback=lambda dummy: self._plug_profile_afterconnect()) |
75 else: | 94 else: |
76 self._plug_profile_afterconnect() | 95 self._plug_profile_afterconnect() |
77 | 96 |
78 def _plug_profile_afterconnect(self): | 97 def _plug_profile_afterconnect(self): |
79 # Profile can be connected or not | 98 # Profile can be connected or not |
80 # we get cached data | 99 # we get cached data |
100 self.connected = True | |
81 self.host.bridge.getFeatures(profile_key=self.profile, callback=self._plug_profile_getFeaturesCb, errback=self._plug_profile_getFeaturesEb) | 101 self.host.bridge.getFeatures(profile_key=self.profile, callback=self._plug_profile_getFeaturesCb, errback=self._plug_profile_getFeaturesEb) |
82 | 102 |
83 def _plug_profile_getFeaturesEb(self, failure): | 103 def _plug_profile_getFeaturesEb(self, failure): |
84 log.error(u"Couldn't get features: {}".format(failure)) | 104 log.error(u"Couldn't get features: {}".format(failure)) |
85 self._plug_profile_getFeaturesCb({}) | 105 self._plug_profile_getFeaturesCb({}) |
98 | 118 |
99 for entity_s, data in cached_values.iteritems(): | 119 for entity_s, data in cached_values.iteritems(): |
100 for key, value in data.iteritems(): | 120 for key, value in data.iteritems(): |
101 self.host.entityDataUpdatedHandler(entity_s, key, value, self.profile) | 121 self.host.entityDataUpdatedHandler(entity_s, key, value, self.profile) |
102 | 122 |
103 if not self.bridge.isConnected(self.profile): | 123 if not self.connected: |
104 self.host.setPresenceStatus(C.PRESENCE_UNAVAILABLE, '', profile=self.profile) | 124 self.host.setPresenceStatus(C.PRESENCE_UNAVAILABLE, '', profile=self.profile) |
105 else: | 125 else: |
106 | 126 |
107 contact_list.fill() | 127 contact_list.fill() |
108 self.host.setPresenceStatus(profile=self.profile) | 128 self.host.setPresenceStatus(profile=self.profile) |
140 | 160 |
141 # At this point, profile should be fully plugged | 161 # At this point, profile should be fully plugged |
142 # and we launch frontend specific method | 162 # and we launch frontend specific method |
143 self.host.profilePlugged(self.profile) | 163 self.host.profilePlugged(self.profile) |
144 | 164 |
145 def _getParamError(self, ignore): | 165 def _getParamError(self, failure): |
146 log.error(_("Can't get profile parameter")) | 166 log.error(_("Can't get profile parameter: {msg}").format(msg=failure)) |
147 | 167 |
148 | 168 |
149 class ProfilesManager(object): | 169 class ProfilesManager(object): |
150 """Class managing collection of profiles""" | 170 """Class managing collection of profiles""" |
151 | 171 |
161 def __getitem__(self, profile): | 181 def __getitem__(self, profile): |
162 return self._profiles[profile] | 182 return self._profiles[profile] |
163 | 183 |
164 def __len__(self): | 184 def __len__(self): |
165 return len(self._profiles) | 185 return len(self._profiles) |
186 | |
187 def iteritems(self): | |
188 return self._profiles.iteritems() | |
166 | 189 |
167 def plug(self, profile): | 190 def plug(self, profile): |
168 if profile in self._profiles: | 191 if profile in self._profiles: |
169 raise exceptions.ConflictError('A profile of the name [{}] is already plugged'.format(profile)) | 192 raise exceptions.ConflictError('A profile of the name [{}] is already plugged'.format(profile)) |
170 self._profiles[profile] = ProfileManager(profile) | 193 self._profiles[profile] = ProfileManager(profile) |
187 class QuickApp(object): | 210 class QuickApp(object): |
188 """This class contain the main methods needed for the frontend""" | 211 """This class contain the main methods needed for the frontend""" |
189 MB_HANDLER = True # Set to False if the frontend doesn't manage microblog | 212 MB_HANDLER = True # Set to False if the frontend doesn't manage microblog |
190 AVATARS_HANDLER = True # set to False if avatars are not used | 213 AVATARS_HANDLER = True # set to False if avatars are not used |
191 | 214 |
192 def __init__(self, create_bridge, xmlui, check_options=None): | 215 def __init__(self, bridge_factory, xmlui, check_options=None, connect_bridge=True): |
193 """Create a frontend application | 216 """Create a frontend application |
194 | 217 |
195 @param create_bridge: method to use to create the Bridge | 218 @param bridge_factory: method to use to create the Bridge |
196 @param xmlui: xmlui module | 219 @param xmlui: xmlui module |
197 @param check_options: method to call to check options (usually command line arguments) | 220 @param check_options: method to call to check options (usually command line arguments) |
198 """ | 221 """ |
199 self.xmlui = xmlui | 222 self.xmlui = xmlui |
200 self.menus = quick_menus.QuickMenusManager(self) | 223 self.menus = quick_menus.QuickMenusManager(self) |
218 | 241 |
219 # triggers | 242 # triggers |
220 self.trigger = trigger.TriggerManager() # trigger are used to change the default behaviour | 243 self.trigger = trigger.TriggerManager() # trigger are used to change the default behaviour |
221 | 244 |
222 ## bridge ## | 245 ## bridge ## |
223 try: | 246 self.bridge = bridge_factory() |
224 self.bridge = create_bridge() | |
225 except exceptions.BridgeExceptionNoService: | |
226 print(_(u"Can't connect to SàT backend, are you sure it's launched ?")) | |
227 sys.exit(1) | |
228 except exceptions.BridgeInitError: | |
229 print(_(u"Can't init bridge")) | |
230 sys.exit(1) | |
231 ProfileManager.bridge = self.bridge | 247 ProfileManager.bridge = self.bridge |
248 if connect_bridge: | |
249 self.connectBridge() | |
250 | |
251 self._notif_id = 0 | |
252 self._notifications = OrderedDict() | |
253 self.features = None | |
254 | |
255 def connectBridge(self): | |
256 self.bridge.bridgeConnect(callback=self._bridgeCb, errback=self._bridgeEb) | |
257 | |
258 def _bridgeCb(self): | |
232 self.registerSignal("connected") | 259 self.registerSignal("connected") |
233 self.registerSignal("disconnected") | 260 self.registerSignal("disconnected") |
234 self.registerSignal("actionNew") | 261 self.registerSignal("actionNew") |
235 self.registerSignal("newContact") | 262 self.registerSignal("newContact") |
236 self.registerSignal("messageNew") | 263 self.registerSignal("messageNew") |
253 # FIXME: do it dynamically | 280 # FIXME: do it dynamically |
254 quick_games.Tarot.registerSignals(self) | 281 quick_games.Tarot.registerSignals(self) |
255 quick_games.Quiz.registerSignals(self) | 282 quick_games.Quiz.registerSignals(self) |
256 quick_games.Radiocol.registerSignals(self) | 283 quick_games.Radiocol.registerSignals(self) |
257 | 284 |
258 self._notif_id = 0 | 285 def _bridgeEb(self, failure): |
259 self._notifications = OrderedDict() | 286 if isinstance(failure, exceptions.BridgeExceptionNoService): |
260 self.media_dir = self.bridge.getConfig('', 'media_dir') | 287 print(_(u"Can't connect to SàT backend, are you sure it's launched ?")) |
261 self.features = None | 288 sys.exit(1) |
289 elif isinstance(failure, exceptions.BridgeInitError): | |
290 print(_(u"Can't init bridge")) | |
291 sys.exit(1) | |
292 else: | |
293 print(_(u"Error while initialising bridge: {}".format(failure))) | |
262 | 294 |
263 @property | 295 @property |
264 def current_profile(self): | 296 def current_profile(self): |
265 """Profile that a user would expect to use""" | 297 """Profile that a user would expect to use""" |
266 try: | 298 try: |
869 self.bridge.disconnect(profile) | 901 self.bridge.disconnect(profile) |
870 | 902 |
871 def onExit(self): | 903 def onExit(self): |
872 """Must be called when the frontend is terminating""" | 904 """Must be called when the frontend is terminating""" |
873 to_unplug = [] | 905 to_unplug = [] |
874 for profile in self.profiles: | 906 for profile, profile_manager in self.profiles.iteritems(): |
875 if self.bridge.isConnected(profile): | 907 if profile_manager.connected(profile) and profile_manager.autodisconnect: |
876 if C.bool(self.bridge.getParamA("autodisconnect", "Connection", profile_key=profile)): | 908 #The user wants autodisconnection |
877 #The user wants autodisconnection | 909 self.disconnect(profile) |
878 self.disconnect(profile) | |
879 to_unplug.append(profile) | 910 to_unplug.append(profile) |
880 for profile in to_unplug: | 911 for profile in to_unplug: |
881 self.unplug_profile(profile) | 912 self.unplug_profile(profile) |