one object, two method names, different interfaces: impossible
Submitted by chrysn
Assigned to Simon McVittie
Description
it seems to be impossible to have one python dbus.service.Object present a method on two different interfaces (without ugly tricks; workaround below).
the cause thereof corresponds to the decorator way of exporting methods; the decorators don't have a parameter to export under a different name (even though it's possible to write
what obviously doesn't work, at least if you want to call the methods from regular python as well
class MyObject(dbus.service.Object): @dbus.service.method(dbus_interface=INTERFACE_A) def some_method(): pass
@dbus.service.method(dbus_interface=INTERFACE_B)
def some_method():
fail
, those some_methods would overwrite each other). one could put it like
what would be my preferred way of putting it
class MyObject(dbus.service.Object): @dbus.service.method(dbus_interface=INTERFACE_A, dbus_name='some_method') def a__some_method(): pass
@dbus.service.method(dbus_interface=INTERFACE_B, dbus_name='some_method')
def b__some_method():
fail
(simulating this is already possible using another decorator that changes the name of the function, but never mind).
even with decorator tricks, this does not work yet, because dbus/service.py's _method_lookup looks up the method name in the classes dict property, for all classes in the mro, and if one is found, it checks if it is decorated with the right dbus_interface.
as of now, the workaround i use is to create a class for each interface and take them in as parent classes for the final object. this is total abuse of the idea of inheriting and makes it necessary to disambiguate method calls "c style": instead of my_object.a__some_method(*args), i write MyObjectInterfaceAHelper.some_method(my_object, *args).
i suggest to
- add a parameter to the method decorator that changes the published method's name
- rework decorators and the _method_lookup function: MyObject._dbus_method could be a dictionary mapping (interface, methodname) tuples to a method to call; _method_lookup would look at the mro classes' _dbus_method instead of dict dictionaries.
(in case you wonder how this shows up in an application: for the nautilus/zsh glue code at [1], i expose get_cwd and get_selection methods on a posix and a gvfs interface; one time the methods take and return file system paths, the other time gvfs urls)