Bug 22429 - Python bindings don't support DBus overloaded methods
Summary: Python bindings don't support DBus overloaded methods
Status: RESOLVED WONTFIX
Alias: None
Product: dbus
Classification: Unclassified
Component: python (show other bugs)
Version: unspecified
Hardware: Other All
: medium normal
Assignee: Simon McVittie
QA Contact: John (J5) Palmieri
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-06-23 00:51 UTC by Samat Jain
Modified: 2009-06-26 05:31 UTC (History)
0 users

See Also:
i915 platform:
i915 features:


Attachments
Python program demonstrating missing overloaded methods (496 bytes, text/x-python)
2009-06-23 00:51 UTC, Samat Jain
Details
KMail introspection results, from dbus-send (6.42 KB, text/plain)
2009-06-23 00:55 UTC, Samat Jain
Details

Description Samat Jain 2009-06-23 00:51:27 UTC
Created attachment 27027 [details]
Python program demonstrating missing overloaded methods

If a DBus object exports multiple methods with the same name (but different arguments), python-dbus seems to make only the first callable.

Overloaded methods occur frequently throughout KDE; the one in particular I am running into is the openComposer method of org.kde.kmail/KMail (there probably exist others that would make a better test case, if so, let me know).

Via the command-line, running:

$ dbus-send --session --type=method_call --print-reply --dest=org.kde.kmail /KMail org.freedesktop.DBus.Introspectable.Introspect | grep openComposer
    <method name="openComposer" >
    <method name="openComposer" >
    <method name="openComposer" >

There are three openComposer methods with three different sets of arguments. However, running the attached Python introspection script:

$ python kmail-introspection.py | grep openComposer
 u'org.kde.kmail.kmail.openComposer': u'sssssb',

Only one method is available (the first one), when all three should be available. I'm using python-dbus 0.83.0 on Debian unstable.
Comment 1 Samat Jain 2009-06-23 00:54:41 UTC
(In reply to comment #0)
> $ dbus-send --session --type=method_call --print-reply --dest=org.kde.kmail
> /KMail org.freedesktop.DBus.Introspectable.Introspect | grep openComposer
>     <method name="openComposer" >
>     <method name="openComposer" >
>     <method name="openComposer" >

I attached the contents of this command (without the grep) for those without KDE, showing the overloaded definitions of openComposer.

> $ python kmail-introspection.py | grep openComposer
>  u'org.kde.kmail.kmail.openComposer': u'sssssb',
> 
> Only one method is available (the first one), when all three should be
> available. I'm using python-dbus 0.83.0 on Debian unstable.

Correction: only the last one is available.
Comment 2 Samat Jain 2009-06-23 00:55:13 UTC
Created attachment 27028 [details]
KMail introspection results, from dbus-send
Comment 3 Simon McVittie 2009-06-23 03:32:55 UTC
I have no plans to change this: Python doesn't support method overloading, and it's not at all clear to me that overloaded methods are part of the D-Bus object model (which is considerably simpler than the C++ object model).

If there was a single ProxyObject method that wrapped several overloaded D-Bus methods, we'd have to guess from the arguments which one you wanted to call, and dbus-python already does far too much guesswork (if I had time to redesign it, the type-guessing would be the first thing killed off). Unlike C++, Python does not have well-defined rules for type coercion (and the fact that it's dynamically typed would make this rather difficult); dbus-python attempts to "do the right thing", but is not psychic.

So, if you overload methods, in practice you lose the convenient high-level dbus.proxies.ProxyObject functionality for those methods. There are two ways to work around this:

1) "don't do that, then": introduce D-Bus methods whose names change depending on the arguments (perhaps OpenComposer and OpenComposerWithMessage, or perhaps mirror CPython and use OpenComposerN where N is the number of arguments)

2) drop down a level of abstraction and call those methods using dbus.connection.Connection.call_async() or dbus.connection.Connection.call_blocking(), which take the D-Bus signature as a parameter (Connection is the superclass of BusConnection, Bus, SessionBus etc.). 
Comment 4 Samat Jain 2009-06-25 17:02:41 UTC
(In reply to comment #3)
> I have no plans to change this: Python doesn't support method overloading, and
> it's not at all clear to me that overloaded methods are part of the D-Bus
> object model (which is considerably simpler than the C++ object model).

> 1) "don't do that, then": introduce D-Bus methods whose names change depending
> on the arguments (perhaps OpenComposer and OpenComposerWithMessage, or perhaps
> mirror CPython and use OpenComposerN where N is the number of arguments)

I've not been able to find a reference saying overloaded methods are disallowed in DBus, would you happen to have one?

I'll look into submitting patches to the KDE project to get these methods renamed, but after talking to a few people the consensus is that this is something that should be addressed in the binding (which is understandable---isn't the point of an external interface that it *not* be changed?)

> 2) drop down a level of abstraction and call those methods using
> dbus.connection.Connection.call_async() or
> dbus.connection.Connection.call_blocking(), which take the D-Bus signature as a
> parameter (Connection is the superclass of BusConnection, Bus, SessionBus
> etc.). 

Thanks, I'll look into it!
Comment 5 Simon McVittie 2009-06-26 05:31:58 UTC
(In reply to comment #4)
> I've not been able to find a reference saying overloaded methods are disallowed
> in DBus, would you happen to have one?

I'm not aware of any specification that says that, no. I'm not aware of any specification that says they *are* allowed either, so I'm mostly appealing to the principle of least astonishment.

D-Bus is secretly at least three specifications: an object model that has never been adequately defined (except perhaps as "what the bindings do"), built on a message-passing model that is reasonably well defined in the spec, built on a message serialization that is properly defined in the spec.

I think it's fair to say that if you go beyond what a particular binding expects to be able to support, you'll have to drop down into the message-passing layer. Some other examples of things that the message-passing layer allows, but that I wouldn't necessarily expect object-based bindings to cope well with:

* methods that sometimes have different "in" parameters (this is effectively how method overloading would have to work)
* methods with variadic arguments (just an extension of overloading, really)
* methods that sometimes return different "out" parameters (HAL used to have some of these)
* signals that sometimes have different type signatures
* methods, signals or properties whose names collide
* method calls that will never get a reply
* replying to a method more than once
* unsolicited method replies (i.e. not actually replying to a method call)
* unsolicited errors (i.e. not actually replying to a method call)
* sending a reply to something that isn't a method call
* sending a method call or a signal that, according to its header, is a reply to a method call
* properties that don't always exist, don't always work, or don't always have the same type

dbus-python's solution to all of these is "use the message-passing API instead" (so would dbus-glib's, but dbus-glib's message-passing API is just libdbus).

> I'll look into submitting patches to the KDE project to get these methods
> renamed, but after talking to a few people the consensus is that this is
> something that should be addressed in the binding (which is
> understandable---isn't the point of an external interface that it *not* be
> changed?)

Fair enough; it would certainly be better to add different names (and perhaps deprecate the overloaded ones) than to rename the methods.


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.