Mercurial > libervia-backend
comparison sat/plugins/plugin_adhoc_dbus.py @ 4037:524856bd7b19
massive refactoring to switch from camelCase to snake_case:
historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a
pre-PEP8 code, to use the same coding style as in Twisted.
However, snake_case is more readable and it's better to follow PEP8 best practices, so it
has been decided to move on full snake_case. Because Libervia has a huge codebase, this
ended with a ugly mix of camelCase and snake_case.
To fix that, this patch does a big refactoring by renaming every function and method
(including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case.
This is a massive change, and may result in some bugs.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 08 Apr 2023 13:54:42 +0200 |
parents | 7550ae9cfbac |
children |
comparison
equal
deleted
inserted
replaced
4036:c4464d7ae97b | 4037:524856bd7b19 |
---|---|
96 | 96 |
97 def __init__(self, host): | 97 def __init__(self, host): |
98 log.info(_("plugin Ad-Hoc D-Bus initialization")) | 98 log.info(_("plugin Ad-Hoc D-Bus initialization")) |
99 self.host = host | 99 self.host = host |
100 if etree is not None: | 100 if etree is not None: |
101 host.bridge.addMethod( | 101 host.bridge.add_method( |
102 "adHocDBusAddAuto", | 102 "ad_hoc_dbus_add_auto", |
103 ".plugin", | 103 ".plugin", |
104 in_sign="sasasasasasass", | 104 in_sign="sasasasasasass", |
105 out_sign="(sa(sss))", | 105 out_sign="(sa(sss))", |
106 method=self._adHocDBusAddAuto, | 106 method=self._ad_hoc_dbus_add_auto, |
107 async_=True, | 107 async_=True, |
108 ) | 108 ) |
109 host.bridge.addMethod( | 109 host.bridge.add_method( |
110 "adHocRemotesGet", | 110 "ad_hoc_remotes_get", |
111 ".plugin", | 111 ".plugin", |
112 in_sign="s", | 112 in_sign="s", |
113 out_sign="a(sss)", | 113 out_sign="a(sss)", |
114 method=self._adHocRemotesGet, | 114 method=self._ad_hoc_remotes_get, |
115 async_=True, | 115 async_=True, |
116 ) | 116 ) |
117 self._c = host.plugins["XEP-0050"] | 117 self._c = host.plugins["XEP-0050"] |
118 host.registerNamespace("mediaplayer", NS_MEDIA_PLAYER) | 118 host.register_namespace("mediaplayer", NS_MEDIA_PLAYER) |
119 if dbus is not None: | 119 if dbus is not None: |
120 self.session_bus = dbus.SessionBus() | 120 self.session_bus = dbus.SessionBus() |
121 self.fd_object = self.session_bus.get_object( | 121 self.fd_object = self.session_bus.get_object( |
122 FD_NAME, FD_PATH, introspect=False) | 122 FD_NAME, FD_PATH, introspect=False) |
123 | 123 |
124 def profileConnected(self, client): | 124 def profile_connected(self, client): |
125 if dbus is not None: | 125 if dbus is not None: |
126 self._c.addAdHocCommand( | 126 self._c.add_ad_hoc_command( |
127 client, self.localMediaCb, D_("Media Players"), | 127 client, self.local_media_cb, D_("Media Players"), |
128 node=NS_MEDIA_PLAYER, | 128 node=NS_MEDIA_PLAYER, |
129 timeout=60*60*6 # 6 hours timeout, to avoid breaking remote | 129 timeout=60*60*6 # 6 hours timeout, to avoid breaking remote |
130 # in the middle of a movie | 130 # in the middle of a movie |
131 ) | 131 ) |
132 | 132 |
133 def _DBusAsyncCall(self, proxy, method, *args, **kwargs): | 133 def _dbus_async_call(self, proxy, method, *args, **kwargs): |
134 """ Call a DBus method asynchronously and return a deferred | 134 """ Call a DBus method asynchronously and return a deferred |
135 | 135 |
136 @param proxy: DBus object proxy, as returner by get_object | 136 @param proxy: DBus object proxy, as returner by get_object |
137 @param method: name of the method to call | 137 @param method: name of the method to call |
138 @param args: will be transmitted to the method | 138 @param args: will be transmitted to the method |
147 kwargs["reply_handler"] = lambda ret=None: d.callback(ret) | 147 kwargs["reply_handler"] = lambda ret=None: d.callback(ret) |
148 kwargs["error_handler"] = d.errback | 148 kwargs["error_handler"] = d.errback |
149 proxy.get_dbus_method(method, dbus_interface=interface)(*args, **kwargs) | 149 proxy.get_dbus_method(method, dbus_interface=interface)(*args, **kwargs) |
150 return d | 150 return d |
151 | 151 |
152 def _DBusGetProperty(self, proxy, interface, name): | 152 def _dbus_get_property(self, proxy, interface, name): |
153 return self._DBusAsyncCall( | 153 return self._dbus_async_call( |
154 proxy, "Get", interface, name, interface="org.freedesktop.DBus.Properties") | 154 proxy, "Get", interface, name, interface="org.freedesktop.DBus.Properties") |
155 | 155 |
156 | 156 |
157 def _DBusListNames(self): | 157 def _dbus_list_names(self): |
158 return self._DBusAsyncCall(self.fd_object, "ListNames") | 158 return self._dbus_async_call(self.fd_object, "ListNames") |
159 | 159 |
160 def _DBusIntrospect(self, proxy): | 160 def _dbus_introspect(self, proxy): |
161 return self._DBusAsyncCall(proxy, INTROSPECT_METHOD, interface=INTROSPECT_IFACE) | 161 return self._dbus_async_call(proxy, INTROSPECT_METHOD, interface=INTROSPECT_IFACE) |
162 | 162 |
163 def _acceptMethod(self, method): | 163 def _accept_method(self, method): |
164 """ Return True if we accept the method for a command | 164 """ Return True if we accept the method for a command |
165 @param method: etree.Element | 165 @param method: etree.Element |
166 @return: True if the method is acceptable | 166 @return: True if the method is acceptable |
167 | 167 |
168 """ | 168 """ |
173 return True | 173 return True |
174 | 174 |
175 @defer.inlineCallbacks | 175 @defer.inlineCallbacks |
176 def _introspect(self, methods, bus_name, proxy): | 176 def _introspect(self, methods, bus_name, proxy): |
177 log.debug("introspecting path [%s]" % proxy.object_path) | 177 log.debug("introspecting path [%s]" % proxy.object_path) |
178 introspect_xml = yield self._DBusIntrospect(proxy) | 178 introspect_xml = yield self._dbus_introspect(proxy) |
179 el = etree.fromstring(introspect_xml) | 179 el = etree.fromstring(introspect_xml) |
180 for node in el.iterchildren("node", "interface"): | 180 for node in el.iterchildren("node", "interface"): |
181 if node.tag == "node": | 181 if node.tag == "node": |
182 new_path = os.path.join(proxy.object_path, node.get("name")) | 182 new_path = os.path.join(proxy.object_path, node.get("name")) |
183 new_proxy = self.session_bus.get_object( | 183 new_proxy = self.session_bus.get_object( |
189 if any(name.startswith(ignored) for ignored in IGNORED_IFACES_START): | 189 if any(name.startswith(ignored) for ignored in IGNORED_IFACES_START): |
190 log.debug("interface [%s] is ignored" % name) | 190 log.debug("interface [%s] is ignored" % name) |
191 continue | 191 continue |
192 log.debug("introspecting interface [%s]" % name) | 192 log.debug("introspecting interface [%s]" % name) |
193 for method in node.iterchildren("method"): | 193 for method in node.iterchildren("method"): |
194 if self._acceptMethod(method): | 194 if self._accept_method(method): |
195 method_name = method.get("name") | 195 method_name = method.get("name") |
196 log.debug("method accepted: [%s]" % method_name) | 196 log.debug("method accepted: [%s]" % method_name) |
197 methods.add((proxy.object_path, name, method_name)) | 197 methods.add((proxy.object_path, name, method_name)) |
198 | 198 |
199 def _adHocDBusAddAuto(self, prog_name, allowed_jids, allowed_groups, allowed_magics, | 199 def _ad_hoc_dbus_add_auto(self, prog_name, allowed_jids, allowed_groups, allowed_magics, |
200 forbidden_jids, forbidden_groups, flags, profile_key): | 200 forbidden_jids, forbidden_groups, flags, profile_key): |
201 client = self.host.getClient(profile_key) | 201 client = self.host.get_client(profile_key) |
202 return self.adHocDBusAddAuto( | 202 return self.ad_hoc_dbus_add_auto( |
203 client, prog_name, allowed_jids, allowed_groups, allowed_magics, | 203 client, prog_name, allowed_jids, allowed_groups, allowed_magics, |
204 forbidden_jids, forbidden_groups, flags) | 204 forbidden_jids, forbidden_groups, flags) |
205 | 205 |
206 @defer.inlineCallbacks | 206 @defer.inlineCallbacks |
207 def adHocDBusAddAuto(self, client, prog_name, allowed_jids=None, allowed_groups=None, | 207 def ad_hoc_dbus_add_auto(self, client, prog_name, allowed_jids=None, allowed_groups=None, |
208 allowed_magics=None, forbidden_jids=None, forbidden_groups=None, | 208 allowed_magics=None, forbidden_jids=None, forbidden_groups=None, |
209 flags=None): | 209 flags=None): |
210 bus_names = yield self._DBusListNames() | 210 bus_names = yield self._dbus_list_names() |
211 bus_names = [bus_name for bus_name in bus_names if "." + prog_name in bus_name] | 211 bus_names = [bus_name for bus_name in bus_names if "." + prog_name in bus_name] |
212 if not bus_names: | 212 if not bus_names: |
213 log.info("Can't find any bus for [%s]" % prog_name) | 213 log.info("Can't find any bus for [%s]" % prog_name) |
214 defer.returnValue(("", [])) | 214 defer.returnValue(("", [])) |
215 bus_names.sort() | 215 bus_names.sort() |
221 methods = set() | 221 methods = set() |
222 | 222 |
223 yield self._introspect(methods, bus_name, proxy) | 223 yield self._introspect(methods, bus_name, proxy) |
224 | 224 |
225 if methods: | 225 if methods: |
226 self._addCommand( | 226 self._add_command( |
227 client, | 227 client, |
228 prog_name, | 228 prog_name, |
229 bus_name, | 229 bus_name, |
230 methods, | 230 methods, |
231 allowed_jids=allowed_jids, | 231 allowed_jids=allowed_jids, |
236 flags=flags, | 236 flags=flags, |
237 ) | 237 ) |
238 | 238 |
239 defer.returnValue((str(bus_name), methods)) | 239 defer.returnValue((str(bus_name), methods)) |
240 | 240 |
241 def _addCommand(self, client, adhoc_name, bus_name, methods, allowed_jids=None, | 241 def _add_command(self, client, adhoc_name, bus_name, methods, allowed_jids=None, |
242 allowed_groups=None, allowed_magics=None, forbidden_jids=None, | 242 allowed_groups=None, allowed_magics=None, forbidden_jids=None, |
243 forbidden_groups=None, flags=None): | 243 forbidden_groups=None, flags=None): |
244 if flags is None: | 244 if flags is None: |
245 flags = set() | 245 flags = set() |
246 | 246 |
247 def DBusCallback(client, command_elt, session_data, action, node): | 247 def d_bus_callback(client, command_elt, session_data, action, node): |
248 actions = session_data.setdefault("actions", []) | 248 actions = session_data.setdefault("actions", []) |
249 names_map = session_data.setdefault("names_map", {}) | 249 names_map = session_data.setdefault("names_map", {}) |
250 actions.append(action) | 250 actions.append(action) |
251 | 251 |
252 if len(actions) == 1: | 252 if len(actions) == 1: |
281 raise self._c.AdHocError(self._c.ERROR.BAD_PAYLOAD) | 281 raise self._c.AdHocError(self._c.ERROR.BAD_PAYLOAD) |
282 | 282 |
283 path, iface, command = names_map[command] | 283 path, iface, command = names_map[command] |
284 proxy = self.session_bus.get_object(bus_name, path) | 284 proxy = self.session_bus.get_object(bus_name, path) |
285 | 285 |
286 self._DBusAsyncCall(proxy, command, interface=iface) | 286 self._dbus_async_call(proxy, command, interface=iface) |
287 | 287 |
288 # job done, we can end the session, except if we have FLAG_LOOP | 288 # job done, we can end the session, except if we have FLAG_LOOP |
289 if FLAG_LOOP in flags: | 289 if FLAG_LOOP in flags: |
290 # We have a loop, so we clear everything and we execute again the | 290 # We have a loop, so we clear everything and we execute again the |
291 # command as we had a first call (command_elt is not used, so None | 291 # command as we had a first call (command_elt is not used, so None |
292 # is OK) | 292 # is OK) |
293 del actions[:] | 293 del actions[:] |
294 names_map.clear() | 294 names_map.clear() |
295 return DBusCallback( | 295 return d_bus_callback( |
296 client, None, session_data, self._c.ACTION.EXECUTE, node | 296 client, None, session_data, self._c.ACTION.EXECUTE, node |
297 ) | 297 ) |
298 form = data_form.Form("form", title=_("Updated")) | 298 form = data_form.Form("form", title=_("Updated")) |
299 form.addField(data_form.Field("fixed", "Command sent")) | 299 form.addField(data_form.Field("fixed", "Command sent")) |
300 status = self._c.STATUS.COMPLETED | 300 status = self._c.STATUS.COMPLETED |
303 else: | 303 else: |
304 raise self._c.AdHocError(self._c.ERROR.INTERNAL) | 304 raise self._c.AdHocError(self._c.ERROR.INTERNAL) |
305 | 305 |
306 return (payload, status, None, note) | 306 return (payload, status, None, note) |
307 | 307 |
308 self._c.addAdHocCommand( | 308 self._c.add_ad_hoc_command( |
309 client, | 309 client, |
310 DBusCallback, | 310 d_bus_callback, |
311 adhoc_name, | 311 adhoc_name, |
312 allowed_jids=allowed_jids, | 312 allowed_jids=allowed_jids, |
313 allowed_groups=allowed_groups, | 313 allowed_groups=allowed_groups, |
314 allowed_magics=allowed_magics, | 314 allowed_magics=allowed_magics, |
315 forbidden_jids=forbidden_jids, | 315 forbidden_jids=forbidden_jids, |
316 forbidden_groups=forbidden_groups, | 316 forbidden_groups=forbidden_groups, |
317 ) | 317 ) |
318 | 318 |
319 ## Local media ## | 319 ## Local media ## |
320 | 320 |
321 def _adHocRemotesGet(self, profile): | 321 def _ad_hoc_remotes_get(self, profile): |
322 return self.adHocRemotesGet(self.host.getClient(profile)) | 322 return self.ad_hoc_remotes_get(self.host.get_client(profile)) |
323 | 323 |
324 @defer.inlineCallbacks | 324 @defer.inlineCallbacks |
325 def adHocRemotesGet(self, client): | 325 def ad_hoc_remotes_get(self, client): |
326 """Retrieve available remote media controlers in our devices | 326 """Retrieve available remote media controlers in our devices |
327 @return (list[tuple[unicode, unicode, unicode]]): list of devices with: | 327 @return (list[tuple[unicode, unicode, unicode]]): list of devices with: |
328 - entity full jid | 328 - entity full jid |
329 - device name | 329 - device name |
330 - device label | 330 - device label |
331 """ | 331 """ |
332 found_data = yield defer.ensureDeferred(self.host.findByFeatures( | 332 found_data = yield defer.ensureDeferred(self.host.find_by_features( |
333 client, [self.host.ns_map['commands']], service=False, roster=False, | 333 client, [self.host.ns_map['commands']], service=False, roster=False, |
334 own_jid=True, local_device=True)) | 334 own_jid=True, local_device=True)) |
335 | 335 |
336 remotes = [] | 336 remotes = [] |
337 | 337 |
342 for cmd in cmd_list: | 342 for cmd in cmd_list: |
343 if cmd.nodeIdentifier == NS_MEDIA_PLAYER: | 343 if cmd.nodeIdentifier == NS_MEDIA_PLAYER: |
344 try: | 344 try: |
345 result_elt = yield self._c.do(client, device_jid, | 345 result_elt = yield self._c.do(client, device_jid, |
346 NS_MEDIA_PLAYER, timeout=5) | 346 NS_MEDIA_PLAYER, timeout=5) |
347 command_elt = self._c.getCommandElt(result_elt) | 347 command_elt = self._c.get_command_elt(result_elt) |
348 form = data_form.findForm(command_elt, NS_MEDIA_PLAYER) | 348 form = data_form.findForm(command_elt, NS_MEDIA_PLAYER) |
349 if form is None: | 349 if form is None: |
350 continue | 350 continue |
351 mp_options = form.fields['media_player'].options | 351 mp_options = form.fields['media_player'].options |
352 session_id = command_elt.getAttribute('sessionid') | 352 session_id = command_elt.getAttribute('sessionid') |
366 "Can't retrieve remote controllers on {device_jid}: " | 366 "Can't retrieve remote controllers on {device_jid}: " |
367 "{reason}".format(device_jid=device_jid, reason=e))) | 367 "{reason}".format(device_jid=device_jid, reason=e))) |
368 break | 368 break |
369 defer.returnValue(remotes) | 369 defer.returnValue(remotes) |
370 | 370 |
371 def doMPRISCommand(self, proxy, command): | 371 def do_mpris_command(self, proxy, command): |
372 iface, command = command.rsplit(".", 1) | 372 iface, command = command.rsplit(".", 1) |
373 if command == CMD_GO_BACK: | 373 if command == CMD_GO_BACK: |
374 command = 'Seek' | 374 command = 'Seek' |
375 args = [-SEEK_OFFSET] | 375 args = [-SEEK_OFFSET] |
376 elif command == CMD_GO_FWD: | 376 elif command == CMD_GO_FWD: |
377 command = 'Seek' | 377 command = 'Seek' |
378 args = [SEEK_OFFSET] | 378 args = [SEEK_OFFSET] |
379 else: | 379 else: |
380 args = [] | 380 args = [] |
381 return self._DBusAsyncCall(proxy, command, *args, interface=iface) | 381 return self._dbus_async_call(proxy, command, *args, interface=iface) |
382 | 382 |
383 def addMPRISMetadata(self, form, metadata): | 383 def add_mpris_metadata(self, form, metadata): |
384 """Serialise MRPIS Metadata according to MPRIS_METADATA_MAP""" | 384 """Serialise MRPIS Metadata according to MPRIS_METADATA_MAP""" |
385 for mpris_key, name in MPRIS_METADATA_MAP.items(): | 385 for mpris_key, name in MPRIS_METADATA_MAP.items(): |
386 if mpris_key in metadata: | 386 if mpris_key in metadata: |
387 value = str(metadata[mpris_key]) | 387 value = str(metadata[mpris_key]) |
388 form.addField(data_form.Field(fieldType="fixed", | 388 form.addField(data_form.Field(fieldType="fixed", |
389 var=name, | 389 var=name, |
390 value=value)) | 390 value=value)) |
391 | 391 |
392 @defer.inlineCallbacks | 392 @defer.inlineCallbacks |
393 def localMediaCb(self, client, command_elt, session_data, action, node): | 393 def local_media_cb(self, client, command_elt, session_data, action, node): |
394 try: | 394 try: |
395 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) | 395 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) |
396 command_form = data_form.Form.fromElement(x_elt) | 396 command_form = data_form.Form.fromElement(x_elt) |
397 except StopIteration: | 397 except StopIteration: |
398 command_form = None | 398 command_form = None |
399 | 399 |
400 if command_form is None or len(command_form.fields) == 0: | 400 if command_form is None or len(command_form.fields) == 0: |
401 # root request, we looks for media players | 401 # root request, we looks for media players |
402 bus_names = yield self._DBusListNames() | 402 bus_names = yield self._dbus_list_names() |
403 bus_names = [b for b in bus_names if b.startswith(MPRIS_PREFIX)] | 403 bus_names = [b for b in bus_names if b.startswith(MPRIS_PREFIX)] |
404 if len(bus_names) == 0: | 404 if len(bus_names) == 0: |
405 note = (self._c.NOTE.INFO, D_("No media player found.")) | 405 note = (self._c.NOTE.INFO, D_("No media player found.")) |
406 defer.returnValue((None, self._c.STATUS.COMPLETED, None, note)) | 406 defer.returnValue((None, self._c.STATUS.COMPLETED, None, note)) |
407 options = [] | 407 options = [] |
443 try: | 443 try: |
444 command = command_form["command"] | 444 command = command_form["command"] |
445 except KeyError: | 445 except KeyError: |
446 pass | 446 pass |
447 else: | 447 else: |
448 yield self.doMPRISCommand(proxy, command) | 448 yield self.do_mpris_command(proxy, command) |
449 | 449 |
450 # we construct the remote control form | 450 # we construct the remote control form |
451 form = data_form.Form("form", title=D_("Media Player Selection")) | 451 form = data_form.Form("form", title=D_("Media Player Selection")) |
452 form.addField(data_form.Field(fieldType="hidden", | 452 form.addField(data_form.Field(fieldType="hidden", |
453 var="media_player", | 453 var="media_player", |
454 value=bus_name)) | 454 value=bus_name)) |
455 for iface, properties_names in MPRIS_PROPERTIES.items(): | 455 for iface, properties_names in MPRIS_PROPERTIES.items(): |
456 for name in properties_names: | 456 for name in properties_names: |
457 try: | 457 try: |
458 value = yield self._DBusGetProperty(proxy, iface, name) | 458 value = yield self._dbus_get_property(proxy, iface, name) |
459 except Exception as e: | 459 except Exception as e: |
460 log.warning(_("Can't retrieve attribute {name}: {reason}") | 460 log.warning(_("Can't retrieve attribute {name}: {reason}") |
461 .format(name=name, reason=e)) | 461 .format(name=name, reason=e)) |
462 continue | 462 continue |
463 if name == MPRIS_METADATA_KEY: | 463 if name == MPRIS_METADATA_KEY: |
464 self.addMPRISMetadata(form, value) | 464 self.add_mpris_metadata(form, value) |
465 else: | 465 else: |
466 form.addField(data_form.Field(fieldType="fixed", | 466 form.addField(data_form.Field(fieldType="fixed", |
467 var=name, | 467 var=name, |
468 value=str(value))) | 468 value=str(value))) |
469 | 469 |