Bug 25125

Summary: one object, two method names, different interfaces: impossible
Product: dbus Reporter: chrysn <chrysn>
Component: pythonAssignee: Simon McVittie <smcv>
Status: RESOLVED MOVED QA Contact: John (J5) Palmieri <johnp>
Severity: normal    
Priority: medium    
Version: unspecified   
Hardware: All   
OS: All   
Whiteboard:
i915 platform: i915 features:

Description chrysn 2009-11-16 07:13:19 UTC
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)

[1] http://christian.amsuess.com/tools/nautilus-remote/
Comment 1 GitLab Migration User 2018-08-22 22:03:16 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/dbus/dbus-python/issues/2.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.