1 """Service-side D-Bus decorators."""
3 __all__
= ('explicitly_pass_message', 'method', 'signal')
4 __docformat__
= 'restructuredtext'
11 def method(dbus_interface
, in_signature
=None, out_signature
=None, async_callbacks
=None, sender_keyword
=None):
12 """Factory for decorators used to mark methods of a `dbus.service.Object`
13 to be exported on the D-Bus.
15 The decorated method will be exported over D-Bus as the method of the
16 same name on the given D-Bus interface.
19 `dbus_interface` : str
20 Name of a D-Bus interface
21 `in_signature` : str or None
22 If not None, the signature of the method parameters in the usual
24 `out_signature` : str or None
25 If not None, the signature of the return value in the usual
27 `async_callbacks` : tuple containing (str,str), or None
28 If None (default) the decorated method is expected to return
29 values matching the `out_signature` as usual, or raise
30 an exception on error. If not None, the following applies:
32 `async_callbacks` contains the names of two keyword arguments to
33 the decorated function, which will be used to provide a success
34 callback and an error callback (in that order).
36 When the decorated method is called via the D-Bus, its normal
37 return value will be ignored; instead, a pair of callbacks are
38 passed as keyword arguments, and the decorated method is
39 expected to arrange for one of them to be called.
41 On success the success callback must be called, passing the
42 results of this method as positional parameters in the format
43 given by the `out_signature`.
45 On error the decorated method may either raise an exception
46 before it returns, or arrange for the error callback to be
47 called with an Exception instance as parameter.
49 `sender_keyword` : str or None
50 If not None, contains the name of a keyword argument to the
51 decorated function. When the method is called, the sender's
52 unique name will be passed as this keyword argument.
54 _dbus_bindings
.validate_interface_name(dbus_interface
)
57 args
= inspect
.getargspec(func
)[0]
61 if type(async_callbacks
) != tuple:
62 raise TypeError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
63 if len(async_callbacks
) != 2:
64 raise ValueError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
65 args
.remove(async_callbacks
[0])
66 args
.remove(async_callbacks
[1])
69 args
.remove(sender_keyword
)
72 in_sig
= tuple(_dbus_bindings
.Signature(in_signature
))
74 if len(in_sig
) > len(args
):
75 raise ValueError, 'input signature is longer than the number of arguments taken'
76 elif len(in_sig
) < len(args
):
77 raise ValueError, 'input signature is shorter than the number of arguments taken'
79 func
._dbus
_is
_method
= True
80 func
._dbus
_async
_callbacks
= async_callbacks
81 func
._dbus
_interface
= dbus_interface
82 func
._dbus
_in
_signature
= in_signature
83 func
._dbus
_out
_signature
= out_signature
84 func
._dbus
_sender
_keyword
= sender_keyword
85 func
._dbus
_args
= args
91 def signal(dbus_interface
, signature
=None):
92 """Factory for decorators used to mark methods of a `dbus.service.Object`
93 to emit signals on the D-Bus.
95 Whenever the decorated method is called in Python, after the method
96 body is executed, a signal with the same name as the decorated method,
97 from the given D-Bus interface, will be emitted.
100 `dbus_interface` : str
101 The D-Bus interface whose signal is emitted
103 The signature of the signal in the usual D-Bus notation
105 _dbus_bindings
.validate_interface_name(dbus_interface
)
107 def emit_signal(self
, *args
, **keywords
):
108 func(self
, *args
, **keywords
)
109 message
= _dbus_bindings
.SignalMessage(self
._object
_path
, dbus_interface
, func
.__name
__)
111 if emit_signal
._dbus
_signature
:
112 message
.append(signature
=emit_signal
._dbus
_signature
,
115 message
.append(*args
)
117 self
._connection
._send
(message
)
119 args
= inspect
.getargspec(func
)[0]
123 sig
= tuple(_dbus_bindings
.Signature(signature
))
125 if len(sig
) > len(args
):
126 raise ValueError, 'signal signature is longer than the number of arguments provided'
127 elif len(sig
) < len(args
):
128 raise ValueError, 'signal signature is shorter than the number of arguments provided'
130 emit_signal
.__name
__ = func
.__name
__
131 emit_signal
.__doc
__ = func
.__doc
__
132 emit_signal
._dbus
_is
_signal
= True
133 emit_signal
._dbus
_interface
= dbus_interface
134 emit_signal
._dbus
_signature
= signature
135 emit_signal
._dbus
_args
= args
141 def explicitly_pass_message(func
):
142 """Decorator which marks the given function such that, if it is called
143 as a D-Bus signal recipient, then the Signal message will be passed
144 to it as a keyword parameter named ``dbus_message``.
146 Deprecated? Should Messages really be exposed to client code?
148 FIXME: this alters the namespace of the decorated function without
149 using the ``__magic__`` naming convention.
151 func
._dbus
_pass
_message
= True