1 # Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
3 # Licensed under the Academic Free License version 2.1
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as published
7 # by the Free Software Foundation; either version 2.1 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 __all__
= ('Connection',)
20 __docformat__
= 'reStructuredText'
24 from _dbus_bindings
import Connection
as _Connection
, ErrorMessage
, \
25 MethodCallMessage
, MethodReturnMessage
, \
26 DBusException
, LOCAL_PATH
, LOCAL_IFACE
27 from dbus
.proxies
import ProxyObject
30 _logger
= logging
.getLogger('dbus.methods')
33 def _noop(*args
, **kwargs
):
37 class Connection(_Connection
):
38 """A connection to another application. In this base class there is
39 assumed to be no bus daemon.
42 ProxyObjectClass
= ProxyObject
44 def get_object(self
, named_service
, object_path
, introspect
=True):
45 """Return a local proxy for the given remote object.
47 Method calls on the proxy are translated into method calls on the
52 A bus name (either the unique name or a well-known name)
53 of the application owning the object
55 The object path of the desired object
57 If true (default), attempt to introspect the remote
58 object to find out supported methods and their signatures
60 :Returns: a `dbus.proxies.ProxyObject`
62 return self
.ProxyObjectClass(self
, named_service
, object_path
,
63 introspect
=introspect
)
65 def activate_name_owner(self
, bus_name
):
66 """Return the unique name for the given bus name, activating it
67 if necessary and possible.
69 If the name is already unique or this connection is not to a
70 bus daemon, just return it.
72 :Returns: a bus name. If the given `bus_name` exists, the returned
73 name identifies its current owner; otherwise the returned name
75 :Raises DBusException: if the implementation has failed
76 to activate the given bus name.
80 def call_async(self
, bus_name
, object_path
, dbus_interface
, method
,
81 signature
, args
, reply_handler
, error_handler
,
82 timeout
=-1.0, utf8_strings
=False, byte_arrays
=False,
83 require_main_loop
=True):
84 """Call the given method, asynchronously.
86 If the reply_handler is None, successful replies will be ignored.
87 If the error_handler is None, failures will be ignored. If both
88 are None, the implementation may request that no reply is sent.
90 :Returns: The dbus.lowlevel.PendingCall.
92 if object_path
== LOCAL_PATH
:
93 raise DBusException('Methods may not be called on the reserved '
94 'path %s' % LOCAL_PATH
)
95 if dbus_interface
== LOCAL_IFACE
:
96 raise DBusException('Methods may not be called on the reserved '
97 'interface %s' % LOCAL_IFACE
)
98 # no need to validate other args - MethodCallMessage ctor will do
100 get_args_opts
= {'utf8_strings': utf8_strings
,
101 'byte_arrays': byte_arrays
}
103 message
= MethodCallMessage(destination
=bus_name
,
105 interface
=dbus_interface
,
107 # Add the arguments to the function
109 message
.append(signature
=signature
, *args
)
111 _logger
.error('Unable to set arguments %r according to '
112 'signature %r: %s: %s',
113 args
, signature
, e
.__class
__, e
)
116 if reply_handler
is None and error_handler
is None:
117 # we don't care what happens, so just send it
118 self
.send_message(message
)
121 if reply_handler
is None:
122 reply_handler
= _noop
123 if error_handler
is None:
124 error_handler
= _noop
126 def msg_reply_handler(message
):
127 if isinstance(message
, MethodReturnMessage
):
128 reply_handler(*message
.get_args_list(**get_args_opts
))
129 elif isinstance(message
, ErrorMessage
):
130 args
= message
.get_args_list()
131 # FIXME: should we do something with the rest?
133 error_handler(DBusException(args
[0]))
135 error_handler(DBusException())
137 error_handler(TypeError('Unexpected type for reply '
138 'message: %r' % message
))
139 return self
.send_message_with_reply(message
, msg_reply_handler
,
141 require_main_loop
=require_main_loop
)
143 def call_blocking(self
, bus_name
, object_path
, dbus_interface
, method
,
144 signature
, args
, timeout
=-1.0, utf8_strings
=False,
146 """Call the given method, synchronously.
148 if object_path
== LOCAL_PATH
:
149 raise DBusException('Methods may not be called on the reserved '
150 'path %s' % LOCAL_PATH
)
151 if dbus_interface
== LOCAL_IFACE
:
152 raise DBusException('Methods may not be called on the reserved '
153 'interface %s' % LOCAL_IFACE
)
154 # no need to validate other args - MethodCallMessage ctor will do
156 get_args_opts
= {'utf8_strings': utf8_strings
,
157 'byte_arrays': byte_arrays
}
159 message
= MethodCallMessage(destination
=bus_name
,
161 interface
=dbus_interface
,
163 # Add the arguments to the function
165 message
.append(signature
=signature
, *args
)
167 _logger
.error('Unable to set arguments %r according to '
168 'signature %r: %s: %s',
169 args
, signature
, e
.__class
__, e
)
172 # make a blocking call
173 reply_message
= self
.send_message_with_reply_and_block(
175 args_list
= reply_message
.get_args_list(**get_args_opts
)
176 if len(args_list
) == 0:
178 elif len(args_list
) == 1:
181 return tuple(args_list
)