ProxyMethod.__call__() does not correctly handle the case of a proxied method that returns a single dbus object. That is, a method that returns a value with a dbus signature of the form "(xyz)".
I found two problems. The first is in the code that builds the proxied method's return type's signature.
Consider the case of a proxied method with self._outargs = ["(dsii)"].
To build self._soutargs, ProxyMethod.__init__() unconditionally adds enclosing parentheses:
This will result in an error being returned from instance._bus.con.call_sync() when called from ProxyMethod.__call__():
gi._glib.GError: Method 'GetOrientation' returned type '(dsii)', but expected '((dsii))'
The second problem is in ProxyMethod.call(), in handling the value returned by call_sync(), which is a tuple, assigned to the variable ret:
if len(self._outargs) == 0:
return None
elif len(self._outargs) == 1:
return ret[0]
else:
return ret
If the proxied method returns a single object, len(self._outargs) will be 1, and only the first element of the tuple will be returned from ProxyMethod.__call__().
To handle this particular case, I added a state variable self._ret_obj, which ProxyMethod.__init__() sets to True iff len(self._outargs) == 1 and self._outargs[0] starts with "(". In other words, if this flag is set, the proxied function will return a single argument, which will be a dbus object.
self._ret_obj = len(self._outargs) == 1 and self._outargs[0].startswith("(")
It then tests self._ret_obj and adds enclosing parentheses if it is False.
ProxyMethod.__call__() tests self._ret_obj when deciding whether to return the entire tuple or only the first element:
if len(self._outargs) == 0:
return None
elif len(self._outargs) == 1 and not self._ret_obj:
return ret[0]
else:
return ret
ProxyMethod.__call__()
does not correctly handle the case of a proxied method that returns a single dbus object. That is, a method that returns a value with a dbus signature of the form"(xyz)"
.I found two problems. The first is in the code that builds the proxied method's return type's signature.
Consider the case of a proxied method with
self._outargs = ["(dsii)"]
. To buildself._soutargs
,ProxyMethod.__init__()
unconditionally adds enclosing parentheses:This will result in an error being returned from
instance._bus.con.call_sync()
when called fromProxyMethod.__call__()
:The second problem is in ProxyMethod.call(), in handling the value returned by call_sync(), which is a tuple, assigned to the variable
ret
:If the proxied method returns a single object,
len(self._outargs)
will be 1, and only the first element of the tuple will be returned fromProxyMethod.__call__()
.To handle this particular case, I added a state variable
self._ret_obj
, whichProxyMethod.__init__()
sets toTrue
ifflen(self._outargs) == 1
andself._outargs[0]
starts with "(". In other words, if this flag is set, the proxied function will return a single argument, which will be a dbus object.It then tests
self._ret_obj
and adds enclosing parentheses if it isFalse
.ProxyMethod.__call__()
testsself._ret_obj
when deciding whether to return the entire tuple or only the first element: