1From 39a7d79ee6c548902fbac8b95c934af7e4c69260 Mon Sep 17 00:00:00 2001
2From: Vendula Poncova <vponcova@redhat.com>
3Date: Thu, 2 Aug 2018 15:30:45 +0800
4Subject: [PATCH 1/2] Support asynchronous calls (#58)
5
6Added support for asynchronous calls of methods. A method is called
7synchronously unless its callback parameter is specified. A callback
8is a function f(*args, returned=None, error=None), where args is
9callback_args specified in the method call, returned is a return
10value of the method and error is an exception raised by the method.
11
12Example of an asynchronous call:
13
14def func(x, y, returned=None, error=None):
15  pass
16
17proxy.Method(a, b, callback=func, callback_args=(x, y))
18
19Upstream-Status: Cherry-pick [https://src.fedoraproject.org/cgit/rpms/python-pydbus.git/]
20
21Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
22---
23 pydbus/proxy_method.py | 44 ++++++++++++++++++++++++++++++++++++++------
24 1 file changed, 38 insertions(+), 6 deletions(-)
25
26diff --git a/pydbus/proxy_method.py b/pydbus/proxy_method.py
27index 8798edd..4ea4304 100644
28--- a/pydbus/proxy_method.py
29+++ b/pydbus/proxy_method.py
30@@ -65,15 +65,34 @@ class ProxyMethod(object):
31
32 		# Python 2 sux
33 		for kwarg in kwargs:
34-			if kwarg not in ("timeout",):
35+			if kwarg not in ("timeout", "callback", "callback_args"):
36 				raise TypeError(self.__qualname__ + " got an unexpected keyword argument '{}'".format(kwarg))
37 		timeout = kwargs.get("timeout", None)
38+		callback = kwargs.get("callback", None)
39+		callback_args = kwargs.get("callback_args", tuple())
40+
41+		call_args = (
42+			instance._bus_name,
43+			instance._path,
44+			self._iface_name,
45+			self.__name__,
46+			GLib.Variant(self._sinargs, args),
47+			GLib.VariantType.new(self._soutargs),
48+			0,
49+			timeout_to_glib(timeout),
50+			None
51+		)
52+
53+		if callback:
54+			call_args += (self._finish_async_call, (callback, callback_args))
55+			instance._bus.con.call(*call_args)
56+			return None
57+		else:
58+			ret = instance._bus.con.call_sync(*call_args)
59+			return self._unpack_return(ret)
60
61-		ret = instance._bus.con.call_sync(
62-			instance._bus_name, instance._path,
63-			self._iface_name, self.__name__, GLib.Variant(self._sinargs, args), GLib.VariantType.new(self._soutargs),
64-			0, timeout_to_glib(timeout), None).unpack()
65-
66+	def _unpack_return(self, values):
67+		ret = values.unpack()
68 		if len(self._outargs) == 0:
69 			return None
70 		elif len(self._outargs) == 1:
71@@ -81,6 +100,19 @@ class ProxyMethod(object):
72 		else:
73 			return ret
74
75+	def _finish_async_call(self, source, result, user_data):
76+		error = None
77+		return_args = None
78+
79+		try:
80+			ret = source.call_finish(result)
81+			return_args = self._unpack_return(ret)
82+		except Exception as err:
83+			error = err
84+
85+		callback, callback_args = user_data
86+		callback(*callback_args, returned=return_args, error=error)
87+
88 	def __get__(self, instance, owner):
89 		if instance is None:
90 			return self
91--
922.7.4
93
94