|
Packit |
130fc8 |
"""Service-side D-Bus decorators."""
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
# Copyright (C) 2003, 2004, 2005, 2006 Red Hat Inc. <http://www.redhat.com/>
|
|
Packit |
130fc8 |
# Copyright (C) 2003 David Zeuthen
|
|
Packit |
130fc8 |
# Copyright (C) 2004 Rob Taylor
|
|
Packit |
130fc8 |
# Copyright (C) 2005, 2006 Collabora Ltd. <http://www.collabora.co.uk/>
|
|
Packit |
130fc8 |
#
|
|
Packit |
130fc8 |
# Permission is hereby granted, free of charge, to any person
|
|
Packit |
130fc8 |
# obtaining a copy of this software and associated documentation
|
|
Packit |
130fc8 |
# files (the "Software"), to deal in the Software without
|
|
Packit |
130fc8 |
# restriction, including without limitation the rights to use, copy,
|
|
Packit |
130fc8 |
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
130fc8 |
# of the Software, and to permit persons to whom the Software is
|
|
Packit |
130fc8 |
# furnished to do so, subject to the following conditions:
|
|
Packit |
130fc8 |
#
|
|
Packit |
130fc8 |
# The above copyright notice and this permission notice shall be
|
|
Packit |
130fc8 |
# included in all copies or substantial portions of the Software.
|
|
Packit |
130fc8 |
#
|
|
Packit |
130fc8 |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
130fc8 |
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
130fc8 |
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
130fc8 |
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
130fc8 |
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
Packit |
130fc8 |
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
Packit |
130fc8 |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
Packit |
130fc8 |
# DEALINGS IN THE SOFTWARE.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
__all__ = ('method', 'signal')
|
|
Packit |
130fc8 |
__docformat__ = 'restructuredtext'
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
import inspect
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
from dbus import validate_interface_name, Signature, validate_member_name
|
|
Packit |
130fc8 |
from dbus.lowlevel import SignalMessage
|
|
Packit |
130fc8 |
from dbus.exceptions import DBusException
|
|
Packit |
130fc8 |
from dbus._compat import is_py2
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
def method(dbus_interface, in_signature=None, out_signature=None,
|
|
Packit |
130fc8 |
async_callbacks=None,
|
|
Packit |
130fc8 |
sender_keyword=None, path_keyword=None, destination_keyword=None,
|
|
Packit |
130fc8 |
message_keyword=None, connection_keyword=None,
|
|
Packit |
130fc8 |
byte_arrays=False,
|
|
Packit |
130fc8 |
rel_path_keyword=None, **kwargs):
|
|
Packit |
130fc8 |
"""Factory for decorators used to mark methods of a `dbus.service.Object`
|
|
Packit |
130fc8 |
to be exported on the D-Bus.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
The decorated method will be exported over D-Bus as the method of the
|
|
Packit |
130fc8 |
same name on the given D-Bus interface.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Parameters:
|
|
Packit |
130fc8 |
`dbus_interface` : str
|
|
Packit |
130fc8 |
Name of a D-Bus interface
|
|
Packit |
130fc8 |
`in_signature` : str or None
|
|
Packit |
130fc8 |
If not None, the signature of the method parameters in the usual
|
|
Packit |
130fc8 |
D-Bus notation
|
|
Packit |
130fc8 |
`out_signature` : str or None
|
|
Packit |
130fc8 |
If not None, the signature of the return value in the usual
|
|
Packit |
130fc8 |
D-Bus notation
|
|
Packit |
130fc8 |
`async_callbacks` : tuple containing (str,str), or None
|
|
Packit |
130fc8 |
If None (default) the decorated method is expected to return
|
|
Packit |
130fc8 |
values matching the `out_signature` as usual, or raise
|
|
Packit |
130fc8 |
an exception on error. If not None, the following applies:
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`async_callbacks` contains the names of two keyword arguments to
|
|
Packit |
130fc8 |
the decorated function, which will be used to provide a success
|
|
Packit |
130fc8 |
callback and an error callback (in that order).
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
When the decorated method is called via the D-Bus, its normal
|
|
Packit |
130fc8 |
return value will be ignored; instead, a pair of callbacks are
|
|
Packit |
130fc8 |
passed as keyword arguments, and the decorated method is
|
|
Packit |
130fc8 |
expected to arrange for one of them to be called.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
On success the success callback must be called, passing the
|
|
Packit |
130fc8 |
results of this method as positional parameters in the format
|
|
Packit |
130fc8 |
given by the `out_signature`.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
On error the decorated method may either raise an exception
|
|
Packit |
130fc8 |
before it returns, or arrange for the error callback to be
|
|
Packit |
130fc8 |
called with an Exception instance as parameter.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`sender_keyword` : str or None
|
|
Packit |
130fc8 |
If not None, contains the name of a keyword argument to the
|
|
Packit |
130fc8 |
decorated function, conventionally ``'sender'``. When the
|
|
Packit |
130fc8 |
method is called, the sender's unique name will be passed as
|
|
Packit |
130fc8 |
this keyword argument.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`path_keyword` : str or None
|
|
Packit |
130fc8 |
If not None (the default), the decorated method will receive
|
|
Packit |
130fc8 |
the destination object path as a keyword argument with this
|
|
Packit |
130fc8 |
name. Normally you already know the object path, but in the
|
|
Packit |
130fc8 |
case of "fallback paths" you'll usually want to use the object
|
|
Packit |
130fc8 |
path in the method's implementation.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
For fallback objects, `rel_path_keyword` (new in 0.82.2) is
|
|
Packit |
130fc8 |
likely to be more useful.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.80.0?
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`rel_path_keyword` : str or None
|
|
Packit |
130fc8 |
If not None (the default), the decorated method will receive
|
|
Packit |
130fc8 |
the destination object path, relative to the path at which the
|
|
Packit |
130fc8 |
object was exported, as a keyword argument with this
|
|
Packit |
130fc8 |
name. For non-fallback objects the relative path will always be
|
|
Packit |
130fc8 |
'/'.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.82.2
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`destination_keyword` : str or None
|
|
Packit |
130fc8 |
If not None (the default), the decorated method will receive
|
|
Packit |
130fc8 |
the destination bus name as a keyword argument with this name.
|
|
Packit |
130fc8 |
Included for completeness - you shouldn't need this.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.80.0?
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`message_keyword` : str or None
|
|
Packit |
130fc8 |
If not None (the default), the decorated method will receive
|
|
Packit |
130fc8 |
the `dbus.lowlevel.MethodCallMessage` as a keyword argument
|
|
Packit |
130fc8 |
with this name.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.80.0?
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`connection_keyword` : str or None
|
|
Packit |
130fc8 |
If not None (the default), the decorated method will receive
|
|
Packit |
130fc8 |
the `dbus.connection.Connection` as a keyword argument
|
|
Packit |
130fc8 |
with this name. This is generally only useful for objects
|
|
Packit |
130fc8 |
that are available on more than one connection.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.82.0
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`utf8_strings` : bool
|
|
Packit |
130fc8 |
If False (default), D-Bus strings are passed to the decorated
|
|
Packit |
130fc8 |
method as objects of class dbus.String, a unicode subclass.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
If True, D-Bus strings are passed to the decorated method
|
|
Packit |
130fc8 |
as objects of class dbus.UTF8String, a str subclass guaranteed
|
|
Packit |
130fc8 |
to be encoded in UTF-8.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
This option does not affect object-paths and signatures, which
|
|
Packit |
130fc8 |
are always 8-bit strings (str subclass) encoded in ASCII.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.80.0
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`byte_arrays` : bool
|
|
Packit |
130fc8 |
If False (default), a byte array will be passed to the decorated
|
|
Packit |
130fc8 |
method as an `Array` (a list subclass) of `Byte` objects.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
If True, a byte array will be passed to the decorated method as
|
|
Packit |
130fc8 |
a `ByteArray`, a str subclass. This is usually what you want,
|
|
Packit |
130fc8 |
but is switched off by default to keep dbus-python's API
|
|
Packit |
130fc8 |
consistent.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.80.0
|
|
Packit |
130fc8 |
"""
|
|
Packit |
130fc8 |
validate_interface_name(dbus_interface)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
def decorator(func):
|
|
Packit |
130fc8 |
if hasattr(inspect, 'Signature'):
|
|
Packit |
130fc8 |
args = []
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
for arg in inspect.signature(func).parameters.values():
|
|
Packit |
130fc8 |
if arg.kind in (inspect.Parameter.POSITIONAL_ONLY,
|
|
Packit |
130fc8 |
inspect.Parameter.POSITIONAL_OR_KEYWORD):
|
|
Packit |
130fc8 |
args.append(arg.name)
|
|
Packit |
130fc8 |
else:
|
|
Packit |
130fc8 |
args = inspect.getargspec(func)[0]
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
args.pop(0)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if async_callbacks:
|
|
Packit |
130fc8 |
if type(async_callbacks) != tuple:
|
|
Packit |
130fc8 |
raise TypeError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
|
|
Packit |
130fc8 |
if len(async_callbacks) != 2:
|
|
Packit |
130fc8 |
raise ValueError('async_callbacks must be a tuple of (keyword for return callback, keyword for error callback)')
|
|
Packit |
130fc8 |
args.remove(async_callbacks[0])
|
|
Packit |
130fc8 |
args.remove(async_callbacks[1])
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if sender_keyword:
|
|
Packit |
130fc8 |
args.remove(sender_keyword)
|
|
Packit |
130fc8 |
if rel_path_keyword:
|
|
Packit |
130fc8 |
args.remove(rel_path_keyword)
|
|
Packit |
130fc8 |
if path_keyword:
|
|
Packit |
130fc8 |
args.remove(path_keyword)
|
|
Packit |
130fc8 |
if destination_keyword:
|
|
Packit |
130fc8 |
args.remove(destination_keyword)
|
|
Packit |
130fc8 |
if message_keyword:
|
|
Packit |
130fc8 |
args.remove(message_keyword)
|
|
Packit |
130fc8 |
if connection_keyword:
|
|
Packit |
130fc8 |
args.remove(connection_keyword)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if in_signature:
|
|
Packit |
130fc8 |
in_sig = tuple(Signature(in_signature))
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if len(in_sig) > len(args):
|
|
Packit |
130fc8 |
raise ValueError('input signature is longer than the number of arguments taken')
|
|
Packit |
130fc8 |
elif len(in_sig) < len(args):
|
|
Packit |
130fc8 |
raise ValueError('input signature is shorter than the number of arguments taken')
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
func._dbus_is_method = True
|
|
Packit |
130fc8 |
func._dbus_async_callbacks = async_callbacks
|
|
Packit |
130fc8 |
func._dbus_interface = dbus_interface
|
|
Packit |
130fc8 |
func._dbus_in_signature = in_signature
|
|
Packit |
130fc8 |
func._dbus_out_signature = out_signature
|
|
Packit |
130fc8 |
func._dbus_sender_keyword = sender_keyword
|
|
Packit |
130fc8 |
func._dbus_path_keyword = path_keyword
|
|
Packit |
130fc8 |
func._dbus_rel_path_keyword = rel_path_keyword
|
|
Packit |
130fc8 |
func._dbus_destination_keyword = destination_keyword
|
|
Packit |
130fc8 |
func._dbus_message_keyword = message_keyword
|
|
Packit |
130fc8 |
func._dbus_connection_keyword = connection_keyword
|
|
Packit |
130fc8 |
func._dbus_args = args
|
|
Packit |
130fc8 |
func._dbus_get_args_options = dict(byte_arrays=byte_arrays)
|
|
Packit |
130fc8 |
if is_py2:
|
|
Packit |
130fc8 |
func._dbus_get_args_options['utf8_strings'] = kwargs.get(
|
|
Packit |
130fc8 |
'utf8_strings', False)
|
|
Packit |
130fc8 |
elif 'utf8_strings' in kwargs:
|
|
Packit |
130fc8 |
raise TypeError("unexpected keyword argument 'utf8_strings'")
|
|
Packit |
130fc8 |
return func
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
return decorator
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
def signal(dbus_interface, signature=None, path_keyword=None,
|
|
Packit |
130fc8 |
rel_path_keyword=None):
|
|
Packit |
130fc8 |
"""Factory for decorators used to mark methods of a `dbus.service.Object`
|
|
Packit |
130fc8 |
to emit signals on the D-Bus.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
Whenever the decorated method is called in Python, after the method
|
|
Packit |
130fc8 |
body is executed, a signal with the same name as the decorated method,
|
|
Packit |
130fc8 |
with the given D-Bus interface, will be emitted from this object.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Parameters:
|
|
Packit |
130fc8 |
`dbus_interface` : str
|
|
Packit |
130fc8 |
The D-Bus interface whose signal is emitted
|
|
Packit |
130fc8 |
`signature` : str
|
|
Packit |
130fc8 |
The signature of the signal in the usual D-Bus notation
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`path_keyword` : str or None
|
|
Packit |
130fc8 |
A keyword argument to the decorated method. If not None,
|
|
Packit |
130fc8 |
that argument will not be emitted as an argument of
|
|
Packit |
130fc8 |
the signal, and when the signal is emitted, it will appear
|
|
Packit |
130fc8 |
to come from the object path given by the keyword argument.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
Note that when calling the decorated method, you must always
|
|
Packit |
130fc8 |
pass in the object path as a keyword argument, not as a
|
|
Packit |
130fc8 |
positional argument.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
This keyword argument cannot be used on objects where
|
|
Packit |
130fc8 |
the class attribute ``SUPPORTS_MULTIPLE_OBJECT_PATHS`` is true.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Deprecated: since 0.82.0. Use `rel_path_keyword` instead.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
`rel_path_keyword` : str or None
|
|
Packit |
130fc8 |
A keyword argument to the decorated method. If not None,
|
|
Packit |
130fc8 |
that argument will not be emitted as an argument of
|
|
Packit |
130fc8 |
the signal.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
When the signal is emitted, if the named keyword argument is given,
|
|
Packit |
130fc8 |
the signal will appear to come from the object path obtained by
|
|
Packit |
130fc8 |
appending the keyword argument to the object's object path.
|
|
Packit |
130fc8 |
This is useful to implement "fallback objects" (objects which
|
|
Packit |
130fc8 |
own an entire subtree of the object-path tree).
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
If the object is available at more than one object-path on the
|
|
Packit |
130fc8 |
same or different connections, the signal will be emitted at
|
|
Packit |
130fc8 |
an appropriate object-path on each connection - for instance,
|
|
Packit |
130fc8 |
if the object is exported at /abc on connection 1 and at
|
|
Packit |
130fc8 |
/def and /x/y/z on connection 2, and the keyword argument is
|
|
Packit |
130fc8 |
/foo, then signals will be emitted from /abc/foo and /def/foo
|
|
Packit |
130fc8 |
on connection 1, and /x/y/z/foo on connection 2.
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
:Since: 0.82.0
|
|
Packit |
130fc8 |
"""
|
|
Packit |
130fc8 |
validate_interface_name(dbus_interface)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if path_keyword is not None:
|
|
Packit |
130fc8 |
from warnings import warn
|
|
Packit |
130fc8 |
warn(DeprecationWarning('dbus.service.signal::path_keyword has been '
|
|
Packit |
130fc8 |
'deprecated since dbus-python 0.82.0, and '
|
|
Packit |
130fc8 |
'will not work on objects that support '
|
|
Packit |
130fc8 |
'multiple object paths'),
|
|
Packit |
130fc8 |
DeprecationWarning, stacklevel=2)
|
|
Packit |
130fc8 |
if rel_path_keyword is not None:
|
|
Packit |
130fc8 |
raise TypeError('dbus.service.signal::path_keyword and '
|
|
Packit |
130fc8 |
'rel_path_keyword cannot both be used')
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
def decorator(func):
|
|
Packit |
130fc8 |
member_name = func.__name__
|
|
Packit |
130fc8 |
validate_member_name(member_name)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
def emit_signal(self, *args, **keywords):
|
|
Packit |
130fc8 |
abs_path = None
|
|
Packit |
130fc8 |
if path_keyword is not None:
|
|
Packit |
130fc8 |
if self.SUPPORTS_MULTIPLE_OBJECT_PATHS:
|
|
Packit |
130fc8 |
raise TypeError('path_keyword cannot be used on the '
|
|
Packit |
130fc8 |
'signals of an object that supports '
|
|
Packit |
130fc8 |
'multiple object paths')
|
|
Packit |
130fc8 |
abs_path = keywords.pop(path_keyword, None)
|
|
Packit |
130fc8 |
if (abs_path != self.__dbus_object_path__ and
|
|
Packit |
130fc8 |
not self.__dbus_object_path__.startswith(abs_path + '/')):
|
|
Packit |
130fc8 |
raise ValueError('Path %r is not below %r', abs_path,
|
|
Packit |
130fc8 |
self.__dbus_object_path__)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
rel_path = None
|
|
Packit |
130fc8 |
if rel_path_keyword is not None:
|
|
Packit |
130fc8 |
rel_path = keywords.pop(rel_path_keyword, None)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
func(self, *args, **keywords)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
for location in self.locations:
|
|
Packit |
130fc8 |
if abs_path is None:
|
|
Packit |
130fc8 |
# non-deprecated case
|
|
Packit |
130fc8 |
if rel_path is None or rel_path in ('/', ''):
|
|
Packit |
130fc8 |
object_path = location[1]
|
|
Packit |
130fc8 |
else:
|
|
Packit |
130fc8 |
# will be validated by SignalMessage ctor in a moment
|
|
Packit |
130fc8 |
object_path = location[1] + rel_path
|
|
Packit |
130fc8 |
else:
|
|
Packit |
130fc8 |
object_path = abs_path
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
message = SignalMessage(object_path,
|
|
Packit |
130fc8 |
dbus_interface,
|
|
Packit |
130fc8 |
member_name)
|
|
Packit |
130fc8 |
message.append(signature=signature, *args)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
location[0].send_message(message)
|
|
Packit |
130fc8 |
# end emit_signal
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
args = inspect.getargspec(func)[0]
|
|
Packit |
130fc8 |
args.pop(0)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
for keyword in rel_path_keyword, path_keyword:
|
|
Packit |
130fc8 |
if keyword is not None:
|
|
Packit |
130fc8 |
try:
|
|
Packit |
130fc8 |
args.remove(keyword)
|
|
Packit |
130fc8 |
except ValueError:
|
|
Packit |
130fc8 |
raise ValueError('function has no argument "%s"' % keyword)
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if signature:
|
|
Packit |
130fc8 |
sig = tuple(Signature(signature))
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if len(sig) > len(args):
|
|
Packit |
130fc8 |
raise ValueError('signal signature is longer than the number of arguments provided')
|
|
Packit |
130fc8 |
elif len(sig) < len(args):
|
|
Packit |
130fc8 |
raise ValueError('signal signature is shorter than the number of arguments provided')
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
emit_signal.__name__ = func.__name__
|
|
Packit |
130fc8 |
emit_signal.__doc__ = func.__doc__
|
|
Packit |
130fc8 |
emit_signal._dbus_is_signal = True
|
|
Packit |
130fc8 |
emit_signal._dbus_interface = dbus_interface
|
|
Packit |
130fc8 |
emit_signal._dbus_signature = signature
|
|
Packit |
130fc8 |
emit_signal._dbus_args = args
|
|
Packit |
130fc8 |
return emit_signal
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
return decorator
|