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