1 """Service-side D-Bus decorators."""
3 # Copyright (C) 2003, 2004, 2005, 2006 Red Hat Inc. <http://www.redhat.com/>
4 # Copyright (C) 2003 David Zeuthen
5 # Copyright (C) 2004 Rob Taylor
6 # Copyright (C) 2005, 2006 Collabora Ltd. <http://www.collabora.co.uk/>
8 # Licensed under the Academic Free License version 2.1
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with this program; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 __all__
= ('method', 'signal')
25 __docformat__
= 'restructuredtext'
32 def method(dbus_interface
, in_signature
=None, out_signature
=None,
34 sender_keyword
=None, path_keyword
=None, destination_keyword
=None,
36 utf8_strings
=False, byte_arrays
=False):
37 """Factory for decorators used to mark methods of a `dbus.service.Object`
38 to be exported on the D-Bus.
40 The decorated method will be exported over D-Bus as the method of the
41 same name on the given D-Bus interface.
44 `dbus_interface` : str
45 Name of a D-Bus interface
46 `in_signature` : str or None
47 If not None, the signature of the method parameters in the usual
49 `out_signature` : str or None
50 If not None, the signature of the return value in the usual
52 `async_callbacks` : tuple containing (str,str), or None
53 If None (default) the decorated method is expected to return
54 values matching the `out_signature` as usual, or raise
55 an exception on error. If not None, the following applies:
57 `async_callbacks` contains the names of two keyword arguments to
58 the decorated function, which will be used to provide a success
59 callback and an error callback (in that order).
61 When the decorated method is called via the D-Bus, its normal
62 return value will be ignored; instead, a pair of callbacks are
63 passed as keyword arguments, and the decorated method is
64 expected to arrange for one of them to be called.
66 On success the success callback must be called, passing the
67 results of this method as positional parameters in the format
68 given by the `out_signature`.
70 On error the decorated method may either raise an exception
71 before it returns, or arrange for the error callback to be
72 called with an Exception instance as parameter.
74 `sender_keyword` : str or None
75 If not None, contains the name of a keyword argument to the
76 decorated function, conventionally ``'sender'``. When the
77 method is called, the sender's unique name will be passed as
78 this keyword argument.
80 `path_keyword` : str or None
81 If not None (the default), the decorated method will receive
82 the destination object path as a keyword argument with this
83 name. Normally you already know the object path, but in the
84 case of "fallback paths" you'll usually want to use the object
85 path in the method's implementation.
87 `destination_keyword` : str or None
88 If not None (the default), the decorated method will receive
89 the destination bus name as a keyword argument with this name.
90 Included for completeness - you shouldn't need this.
92 `message_keyword` : str or None
93 If not None (the default), the decorated method will receive
94 the `dbus.lowlevel.MethodCallMessage` as a keyword argument
98 If False (default), D-Bus strings are passed to the decorated
99 method as objects of class dbus.String, a unicode subclass.
101 If True, D-Bus strings are passed to the decorated method
102 as objects of class dbus.UTF8String, a str subclass guaranteed
103 to be encoded in UTF-8.
105 This option does not affect object-paths and signatures, which
106 are always 8-bit strings (str subclass) encoded in ASCII.
109 If False (default), a byte array will be passed to the decorated
110 method as an `Array` (a list subclass) of `Byte` objects.
112 If True, a byte array will be passed to the decorated method as
113 a `ByteArray`, a str subclass. This is usually what you want,
114 but is switched off by default to keep dbus-python's API
117 _dbus_bindings
.validate_interface_name(dbus_interface
)
120 args
= inspect
.getargspec(func
)[0]
124 if type(async_callbacks
) != tuple:
125 raise TypeError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
126 if len(async_callbacks
) != 2:
127 raise ValueError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
128 args
.remove(async_callbacks
[0])
129 args
.remove(async_callbacks
[1])
132 args
.remove(sender_keyword
)
134 args
.remove(path_keyword
)
135 if destination_keyword
:
136 args
.remove(destination_keyword
)
138 args
.remove(message_keyword
)
141 in_sig
= tuple(_dbus_bindings
.Signature(in_signature
))
143 if len(in_sig
) > len(args
):
144 raise ValueError, 'input signature is longer than the number of arguments taken'
145 elif len(in_sig
) < len(args
):
146 raise ValueError, 'input signature is shorter than the number of arguments taken'
148 func
._dbus
_is
_method
= True
149 func
._dbus
_async
_callbacks
= async_callbacks
150 func
._dbus
_interface
= dbus_interface
151 func
._dbus
_in
_signature
= in_signature
152 func
._dbus
_out
_signature
= out_signature
153 func
._dbus
_sender
_keyword
= sender_keyword
154 func
._dbus
_path
_keyword
= path_keyword
155 func
._dbus
_destination
_keyword
= destination_keyword
156 func
._dbus
_message
_keyword
= message_keyword
157 func
._dbus
_args
= args
158 func
._dbus
_get
_args
_options
= {'byte_arrays': byte_arrays
,
159 'utf8_strings': utf8_strings
}
165 def signal(dbus_interface
, signature
=None, path_keyword
=None):
166 """Factory for decorators used to mark methods of a `dbus.service.Object`
167 to emit signals on the D-Bus.
169 Whenever the decorated method is called in Python, after the method
170 body is executed, a signal with the same name as the decorated method,
171 with the given D-Bus interface, will be emitted from this object.
174 `dbus_interface` : str
175 The D-Bus interface whose signal is emitted
177 The signature of the signal in the usual D-Bus notation
179 `path_keyword` : str or None
180 A keyword argument to the decorated method. If not None,
181 that argument will not be emitted as an argument of
182 the signal, and when the signal is emitted, it will appear
183 to come from the object path given by the keyword argument.
185 Note that when calling the decorated method, you must always
186 pass in the object path as a keyword argument, not as a
189 _dbus_bindings
.validate_interface_name(dbus_interface
)
191 member_name
= func
.__name
__
192 _dbus_bindings
.validate_member_name(member_name
)
194 def emit_signal(self
, *args
, **keywords
):
195 func(self
, *args
, **keywords
)
196 object_path
= self
.__dbus
_object
_path
__
198 kw
= keywords
.pop(path_keyword
, None)
200 if not (kw
== object_path
201 or object_path
== '/'
202 or kw
.startswith(object_path
+ '/')):
203 raise DBusException('Object path %s is not in the '
204 'subtree starting at %s'
208 message
= _dbus_bindings
.SignalMessage(object_path
,
212 if signature
is not None:
213 message
.append(signature
=signature
, *args
)
215 message
.append(*args
)
217 self
._connection
.send_message(message
)
219 args
= inspect
.getargspec(func
)[0]
223 sig
= tuple(_dbus_bindings
.Signature(signature
))
225 if len(sig
) > len(args
):
226 raise ValueError, 'signal signature is longer than the number of arguments provided'
227 elif len(sig
) < len(args
):
228 raise ValueError, 'signal signature is shorter than the number of arguments provided'
230 emit_signal
.__name
__ = func
.__name
__
231 emit_signal
.__doc
__ = func
.__doc
__
232 emit_signal
._dbus
_is
_signal
= True
233 emit_signal
._dbus
_interface
= dbus_interface
234 emit_signal
._dbus
_signature
= signature
235 emit_signal
._dbus
_args
= args