1 """Method-call mixin for use within dbus-python only.
2 See `_MethodCallMixin`.
5 # Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
7 # Licensed under the Academic Free License version 2.1
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU Lesser General Public License as published
11 # by the Free Software Foundation; either version 2.1 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 from _dbus_bindings
import Connection
, ErrorMessage
, \
26 MethodCallMessage
, MethodReturnMessage
, \
27 DBusException
, LOCAL_PATH
, LOCAL_IFACE
30 _logger
= logging
.getLogger('dbus.methods')
33 def _noop(*args
, **kwargs
):
37 class _MethodCallMixin(object):
39 def call_async(self
, bus_name
, object_path
, dbus_interface
, method
,
40 signature
, args
, reply_handler
, error_handler
,
41 timeout
=-1.0, utf8_strings
=False, byte_arrays
=False,
42 require_main_loop
=True):
43 """Call the given method, asynchronously.
45 If the reply_handler is None, successful replies will be ignored.
46 If the error_handler is None, failures will be ignored. If both
47 are None, the implementation may request that no reply is sent.
49 :Returns: The dbus.lowlevel.PendingCall.
51 if object_path
== LOCAL_PATH
:
52 raise DBusException('Methods may not be called on the reserved '
53 'path %s' % LOCAL_PATH
)
54 if dbus_interface
== LOCAL_IFACE
:
55 raise DBusException('Methods may not be called on the reserved '
56 'interface %s' % LOCAL_IFACE
)
57 # no need to validate other args - MethodCallMessage ctor will do
59 get_args_opts
= {'utf8_strings': utf8_strings
,
60 'byte_arrays': byte_arrays
}
62 message
= MethodCallMessage(destination
=bus_name
,
64 interface
=dbus_interface
,
66 # Add the arguments to the function
68 message
.append(signature
=signature
, *args
)
70 _logger
.error('Unable to set arguments %r according to '
71 'signature %r: %s: %s',
72 args
, signature
, e
.__class
__, e
)
75 if reply_handler
is None and error_handler
is None:
76 # we don't care what happens, so just send it
77 self
.send_message(message
)
80 if reply_handler
is None:
82 if error_handler
is None:
85 def msg_reply_handler(message
):
86 if isinstance(message
, MethodReturnMessage
):
87 reply_handler(*message
.get_args_list(**get_args_opts
))
88 elif isinstance(message
, ErrorMessage
):
89 args
= message
.get_args_list()
90 # FIXME: should we do something with the rest?
92 error_handler(DBusException(args
[0]))
94 error_handler(DBusException())
96 error_handler(TypeError('Unexpected type for reply '
97 'message: %r' % message
))
98 return self
.send_message_with_reply(message
, msg_reply_handler
,
100 require_main_loop
=require_main_loop
)
102 def call_blocking(self
, bus_name
, object_path
, dbus_interface
, method
,
103 signature
, args
, timeout
=-1.0, utf8_strings
=False,
105 """Call the given method, synchronously.
107 if object_path
== LOCAL_PATH
:
108 raise DBusException('Methods may not be called on the reserved '
109 'path %s' % LOCAL_PATH
)
110 if dbus_interface
== LOCAL_IFACE
:
111 raise DBusException('Methods may not be called on the reserved '
112 'interface %s' % LOCAL_IFACE
)
113 # no need to validate other args - MethodCallMessage ctor will do
115 get_args_opts
= {'utf8_strings': utf8_strings
,
116 'byte_arrays': byte_arrays
}
118 message
= MethodCallMessage(destination
=bus_name
,
120 interface
=dbus_interface
,
122 # Add the arguments to the function
124 message
.append(signature
=signature
, *args
)
126 _logger
.error('Unable to set arguments %r according to '
127 'signature %r: %s: %s',
128 args
, signature
, e
.__class
__, e
)
131 # make a blocking call
132 reply_message
= self
.send_message_with_reply_and_block(
134 args_list
= reply_message
.get_args_list(**get_args_opts
)
135 if len(args_list
) == 0:
137 elif len(args_list
) == 1:
140 return tuple(args_list
)