Summary: | When guessing return signature for a tuple that is not a Struct, produce a multiple-argument reply rather than a single Struct | ||
---|---|---|---|
Product: | dbus | Reporter: | Thomas Wisniewski <wisniewskit> |
Component: | python | Assignee: | Simon McVittie <smcv> |
Status: | RESOLVED FIXED | QA Contact: | Robert McQueen <robert> |
Severity: | normal | ||
Priority: | medium | ||
Version: | unspecified | ||
Hardware: | All | ||
OS: | All | ||
Whiteboard: | |||
i915 platform: | i915 features: | ||
Attachments: | Proposed patch |
Description
Thomas Wisniewski
2007-03-03 17:43:08 UTC
On closer inspection, this is already being done but there is a bug. If no signature is given, _message_cb in service.py incorrectly wraps a retval into another tuple, even if it's already a tuple or list. This is bad, because the signature-guessing function will then proceed to guess the signature incorrectly. When this behaviour is omitted the guesser works properly and things work out. I tried attaching a patch, but Bugzilla insisted it was an empty file I was attaching, so here it is (I hope it's not mangled too badly): --- service.py 2007-01-17 07:25:38.000000000 -0500 +++ service.py 2007-03-03 23:25:05.645547180 -0500 @@ -484,7 +484,7 @@ else: if retval == None: retval = () - else: + elif type(retval)!=type(()) and type(retval)!=type([]): retval = (retval,) _method_reply_return(connection, message, method_name, signature, *retval) t If what you say is true, then the Network Manager D-Bus API is misdesigned (well, we knew that - it was one of the first D-Bus APIs, so there weren't really any conventions yet). We ought to be able to work around that, though. This needs looking at when I have some time - there are more subtleties here than I can deal with quickly. In particular we can't tell whether someone returning a tuple wanted to return multiple values, or whether they wanted to return a struct (which tuples are normally coerced into); ditto lists and arrays. The correct fix is probably to add a subtype of tuple (or list?) called dbus.MultipleArguments (or dbus.lowlevel.MultipleArguments?), which is coerced into multiple values rather than a struct or array. Only people trying to implement unconventional APIs for which signatures don't really work (like the Network Manager API) should ever need it. The summary doesn't describe my current thoughts about this bug, so changing it. If a Python service method with no out_signature returns a tuple, I think dbus-python should default to producing a reply with multiple arguments, rather than a reply with a single struct argument - there's no reason you should ever want the latter when the former is possible, and in any case you can force the latter behaviour by returning a dbus.Struct. So: @method(dbus_interface='...') def Foo(self): return (1, 2) # or equivalently: return 1, 2 should return a message containing integers 1 and 2 (signature ii), rather than a message containing a struct containing those integers (signature (ii)); to return that struct it should be necessary to do @method(dbus_interface='...') def Foo(self): return Struct(1, 2) I'm not sure what should happen in async-implemented service methods: it's clear that, as is currently done, @method(dbus_interface='...', async_callbacks=('reply_cb', 'error_cb')) def Foo(self, reply_cb=None, error_cb=None): reply_cb(1, 2) should produce a reply with signature ii, and that @method(dbus_interface='...', async_callbacks=('reply_cb', 'error_cb')) def Foo(self, reply_cb=None, error_cb=None): reply_cb(Struct(1, 2)) should produce a reply with signature (ii), but what's not clear is what @method(dbus_interface='...', async_callbacks=('reply_cb', 'error_cb') def Foo(self, reply_cb=None, error_cb=None): reply_cb((1, 2)) should return. I think a struct (ii), as is done now, would be least astonishing, despite the fact that that's inconsistent with the synchronous case. I don't think the current behaviour for lists should be changed: @method(dbus_interface='...') def Foo(self): return [1, 2] should continue to produce a reply containing an array of integers (signature ai rather than ii). Created attachment 9721 [details] [review] Proposed patch I think this patch should do what you want. Mailed to the list for review. """ Fix fd.o #10174: make it possible to return multiple values wit h no signature. More specifically: when a service method with no signature synchronously returns a tuple that is not a Struct, interpret it as a multi-valued return, rather than as a structure. This is a common Python idiom, and returning a struct makes little sense anyway when D-Bus lets you return multiple values. Returned lists are still interpreted as arrays - returning an array is entirely sensible, and indeed likely to be common. Async service methods are unaffected (there is no ambiguity), and it's still possible to return a structure by returning a dbus.Struct with appropriate contents. """ Fixed in git. |
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.