Move the client method-call machinery from dbus.proxies to dbus.connection._MethodCal...
[dbus-python-phuang.git] / dbus / connection.py
blobef6f984f718c220de7e14e6b7631215a31265898
1 """Method-call mixin for use within dbus-python only.
2 See `_MethodCallMixin`.
3 """
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
23 import logging
25 from _dbus_bindings import Connection, ErrorMessage, \
26 MethodCallMessage, MethodReturnMessage, \
27 DBusException
30 # This is special in libdbus - the bus daemon will kick us off if we try to
31 # send any message to it :-/
32 LOCAL_PATH = '/org/freedesktop/DBus/Local'
35 _logger = logging.getLogger('dbus.methods')
38 def _noop(*args, **kwargs):
39 pass
42 class _MethodCallMixin(object):
44 def call_async(self, bus_name, object_path, dbus_interface, method,
45 signature, args, reply_handler, error_handler,
46 timeout=-1.0, utf8_strings=False, byte_arrays=False,
47 require_main_loop=True):
48 """Call the given method, asynchronously.
50 If the reply_handler is None, successful replies will be ignored.
51 If the error_handler is None, failures will be ignored. If both
52 are None, the implementation may request that no reply is sent.
54 :Returns: The dbus.lowlevel.PendingCall.
55 """
56 if object_path == LOCAL_PATH:
57 raise DBusException('Methods may not be called on the reserved '
58 'path %s' % LOCAL_PATH)
59 # no need to validate other args - MethodCallMessage ctor will do
61 get_args_opts = {'utf8_strings': utf8_strings,
62 'byte_arrays': byte_arrays}
64 message = MethodCallMessage(destination=bus_name,
65 path=object_path,
66 interface=dbus_interface,
67 method=method)
68 # Add the arguments to the function
69 try:
70 message.append(signature=signature, *args)
71 except Exception, e:
72 _logger.error('Unable to set arguments %r according to '
73 'signature %r: %s: %s',
74 args, signature, e.__class__, e)
75 raise
77 if reply_handler is None and error_handler is None:
78 # we don't care what happens, so just send it
79 self.send_message(message)
80 return
82 if reply_handler is None:
83 reply_handler = _noop
84 if error_handler is None:
85 error_handler = _noop
87 def msg_reply_handler(message):
88 if isinstance(message, MethodReturnMessage):
89 reply_handler(*message.get_args_list(**get_args_opts))
90 elif isinstance(message, ErrorMessage):
91 args = message.get_args_list()
92 # FIXME: should we do something with the rest?
93 if len(args) > 0:
94 error_handler(DBusException(args[0]))
95 else:
96 error_handler(DBusException())
97 else:
98 error_handler(TypeError('Unexpected type for reply '
99 'message: %r' % message))
100 return self.send_message_with_reply(message, msg_reply_handler,
101 timeout/1000.0,
102 require_main_loop=require_main_loop)
104 def call_blocking(self, bus_name, object_path, dbus_interface, method,
105 signature, args, timeout=-1.0, utf8_strings=False,
106 byte_arrays=False):
107 """Call the given method, synchronously.
109 if object_path == LOCAL_PATH:
110 raise DBusException('Methods may not be called on the reserved '
111 'path %s' % LOCAL_PATH)
112 # no need to validate other args - MethodCallMessage ctor will do
114 get_args_opts = {'utf8_strings': utf8_strings,
115 'byte_arrays': byte_arrays}
117 message = MethodCallMessage(destination=bus_name,
118 path=object_path,
119 interface=dbus_interface,
120 method=method)
121 # Add the arguments to the function
122 try:
123 message.append(signature=signature, *args)
124 except Exception, e:
125 _logger.error('Unable to set arguments %r according to '
126 'signature %r: %s: %s',
127 args, signature, e.__class__, e)
128 raise
130 # make a blocking call
131 reply_message = self.send_message_with_reply_and_block(
132 message, timeout)
133 args_list = reply_message.get_args_list(**get_args_opts)
134 if len(args_list) == 0:
135 return None
136 elif len(args_list) == 1:
137 return args_list[0]
138 else:
139 return tuple(args_list)