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 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 __all__
= ('method', 'signal')
27 __docformat__
= 'restructuredtext'
34 def method(dbus_interface
, in_signature
=None, out_signature
=None, async_callbacks
=None, sender_keyword
=None, utf8_strings
=False, byte_arrays
=False):
35 """Factory for decorators used to mark methods of a `dbus.service.Object`
36 to be exported on the D-Bus.
38 The decorated method will be exported over D-Bus as the method of the
39 same name on the given D-Bus interface.
42 `dbus_interface` : str
43 Name of a D-Bus interface
44 `in_signature` : str or None
45 If not None, the signature of the method parameters in the usual
47 `out_signature` : str or None
48 If not None, the signature of the return value in the usual
50 `async_callbacks` : tuple containing (str,str), or None
51 If None (default) the decorated method is expected to return
52 values matching the `out_signature` as usual, or raise
53 an exception on error. If not None, the following applies:
55 `async_callbacks` contains the names of two keyword arguments to
56 the decorated function, which will be used to provide a success
57 callback and an error callback (in that order).
59 When the decorated method is called via the D-Bus, its normal
60 return value will be ignored; instead, a pair of callbacks are
61 passed as keyword arguments, and the decorated method is
62 expected to arrange for one of them to be called.
64 On success the success callback must be called, passing the
65 results of this method as positional parameters in the format
66 given by the `out_signature`.
68 On error the decorated method may either raise an exception
69 before it returns, or arrange for the error callback to be
70 called with an Exception instance as parameter.
72 `sender_keyword` : str or None
73 If not None, contains the name of a keyword argument to the
74 decorated function, conventionally ``'sender'``. When the
75 method is called, the sender's unique name will be passed as
76 this keyword argument.
79 If False (default), D-Bus strings are passed to the decorated
80 method as objects of class dbus.String, a unicode subclass.
82 If True, D-Bus strings are passed to the decorated method
83 as objects of class dbus.UTF8String, a str subclass guaranteed
84 to be encoded in UTF-8.
86 This option does not affect object-paths and signatures, which
87 are always 8-bit strings (str subclass) encoded in ASCII.
90 If False (default), a byte array will be passed to the decorated
91 method as an `Array` (a list subclass) of `Byte` objects.
93 If True, a byte array will be passed to the decorated method as
94 a `ByteArray`, a str subclass. This is usually what you want,
95 but is switched off by default to keep dbus-python's API
98 _dbus_bindings
.validate_interface_name(dbus_interface
)
101 args
= inspect
.getargspec(func
)[0]
105 if type(async_callbacks
) != tuple:
106 raise TypeError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
107 if len(async_callbacks
) != 2:
108 raise ValueError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
109 args
.remove(async_callbacks
[0])
110 args
.remove(async_callbacks
[1])
113 args
.remove(sender_keyword
)
116 in_sig
= tuple(_dbus_bindings
.Signature(in_signature
))
118 if len(in_sig
) > len(args
):
119 raise ValueError, 'input signature is longer than the number of arguments taken'
120 elif len(in_sig
) < len(args
):
121 raise ValueError, 'input signature is shorter than the number of arguments taken'
123 func
._dbus
_is
_method
= True
124 func
._dbus
_async
_callbacks
= async_callbacks
125 func
._dbus
_interface
= dbus_interface
126 func
._dbus
_in
_signature
= in_signature
127 func
._dbus
_out
_signature
= out_signature
128 func
._dbus
_sender
_keyword
= sender_keyword
129 func
._dbus
_args
= args
130 func
._dbus
_get
_args
_options
= {'byte_arrays': byte_arrays
,
131 'utf8_strings': utf8_strings
}
137 def signal(dbus_interface
, signature
=None):
138 """Factory for decorators used to mark methods of a `dbus.service.Object`
139 to emit signals on the D-Bus.
141 Whenever the decorated method is called in Python, after the method
142 body is executed, a signal with the same name as the decorated method,
143 from the given D-Bus interface, will be emitted.
146 `dbus_interface` : str
147 The D-Bus interface whose signal is emitted
149 The signature of the signal in the usual D-Bus notation
151 _dbus_bindings
.validate_interface_name(dbus_interface
)
153 def emit_signal(self
, *args
, **keywords
):
154 func(self
, *args
, **keywords
)
155 message
= _dbus_bindings
.SignalMessage(self
._object
_path
, dbus_interface
, func
.__name
__)
157 if emit_signal
._dbus
_signature
:
158 message
.append(signature
=emit_signal
._dbus
_signature
,
161 message
.append(*args
)
163 self
._connection
.send_message(message
)
165 args
= inspect
.getargspec(func
)[0]
169 sig
= tuple(_dbus_bindings
.Signature(signature
))
171 if len(sig
) > len(args
):
172 raise ValueError, 'signal signature is longer than the number of arguments provided'
173 elif len(sig
) < len(args
):
174 raise ValueError, 'signal signature is shorter than the number of arguments provided'
176 emit_signal
.__name
__ = func
.__name
__
177 emit_signal
.__doc
__ = func
.__doc
__
178 emit_signal
._dbus
_is
_signal
= True
179 emit_signal
._dbus
_interface
= dbus_interface
180 emit_signal
._dbus
_signature
= signature
181 emit_signal
._dbus
_args
= args