diff --git a/sat/bridge/bridge_constructor/constructors/dbus/constructor.py b/sat/bridge/bridge_constructor/constructors/dbus/constructor.py
index a6623f49..1b3780da 100644
--- a/sat/bridge/bridge_constructor/constructors/dbus/constructor.py
+++ b/sat/bridge/bridge_constructor/constructors/dbus/constructor.py
@@ -25,20 +25,19 @@ class DbusConstructor(base_constructor.Constructor):
CORE_TEMPLATE = "dbus_core_template.py"
CORE_DEST = "dbus_bridge.py"
CORE_FORMATS = {
- "signals": """\
- @dbus.service.signal(const_INT_PREFIX+const_{category}_SUFFIX,
- signature='{sig_in}')
- def {name}(self, {args}):
- {body}\n""",
+ "methods_declarations": """\
+ Method('{name}', arguments='{sig_in}', returns='{sig_out}'),""",
+
"methods": """\
- @dbus.service.method(const_INT_PREFIX+const_{category}_SUFFIX,
- in_signature='{sig_in}', out_signature='{sig_out}',
- async_callbacks={async_callbacks})
- def {name}(self, {args}{async_comma}{async_args_def}):
- {debug}return self._callback("{name}", {args_result}{async_comma}{async_args_call})\n""",
- "signal_direct_calls": """\
+ def dbus_{name}(self, {args}):
+ {debug}return self._callback("{name}", {args_no_default})\n""",
+
+ "signals_declarations": """\
+ Signal('{name}', '{sig_in}'),""",
+
+ "signals": """\
def {name}(self, {args}):
- self.dbus_bridge.{name}({args})\n""",
+ self._obj.emitSignal("{name}", {args})\n""",
}
FRONTEND_TEMPLATE = "dbus_frontend_template.py"
@@ -68,17 +67,10 @@ class DbusConstructor(base_constructor.Constructor):
def core_completion_method(self, completion, function, default, arg_doc, async_):
completion.update(
{
- "debug": ""
- if not self.args.debug
- else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " "),
- "args_result": self.getArguments(
- function["sig_in"], name=arg_doc, unicode_protect=self.args.unicode
- ),
- "async_comma": ", " if async_ and function["sig_in"] else "",
- "async_args_def": "callback=None, errback=None" if async_ else "",
- "async_args_call": "callback=callback, errback=errback" if async_ else "",
- "async_callbacks": "('callback', 'errback')" if async_ else "None",
- "category": completion["category"].upper(),
+ "debug": (
+ "" if not self.args.debug
+ else f'log.debug ("{completion["name"]}")\n{8 * " "}'
+ )
}
)
diff --git a/sat/bridge/bridge_constructor/constructors/dbus/dbus_core_template.py b/sat/bridge/bridge_constructor/constructors/dbus/dbus_core_template.py
index d7469167..d39985d6 100644
--- a/sat/bridge/bridge_constructor/constructors/dbus/dbus_core_template.py
+++ b/sat/bridge/bridge_constructor/constructors/dbus/dbus_core_template.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# SàT communication bridge
+# Libervia communication bridge
# Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
# This program is free software: you can redistribute it and/or modify
@@ -16,15 +16,15 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+from types import MethodType
+from functools import partialmethod
+from twisted.internet import defer, reactor
from sat.core.i18n import _
-import dbus
-import dbus.service
-import dbus.mainloop.glib
-import inspect
from sat.core.log import getLogger
-from sat.tools import config
-from twisted.internet.defer import Deferred
from sat.core.exceptions import BridgeInitError
+from sat.tools import config
+from txdbus import client, objects, error
+from txdbus.interface import DBusInterface, Method, Signal
log = getLogger(__name__)
@@ -45,251 +45,127 @@ class ParseError(Exception):
pass
-class MethodNotRegistered(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".MethodNotRegistered"
+class DBusException(Exception):
+ pass
-class InternalError(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".InternalError"
+class MethodNotRegistered(DBusException):
+ dbusErrorName = const_ERROR_PREFIX + ".MethodNotRegistered"
-class AsyncNotDeferred(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".AsyncNotDeferred"
-
-
-class DeferredNotAsync(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".DeferredNotAsync"
-
-
-class GenericException(dbus.DBusException):
+class GenericException(DBusException):
def __init__(self, twisted_error):
"""
@param twisted_error (Failure): instance of twisted Failure
- @return: DBusException
+ error message is used to store a repr of message and condition in a tuple,
+ so it can be evaluated by the frontend bridge.
"""
- super(GenericException, self).__init__()
try:
# twisted_error.value is a class
class_ = twisted_error.value().__class__
except TypeError:
# twisted_error.value is an instance
class_ = twisted_error.value.__class__
- message = twisted_error.getErrorMessage()
+ data = twisted_error.getErrorMessage()
try:
- self.args = (message, twisted_error.value.condition)
+ data = (data, twisted_error.value.condition)
except AttributeError:
- self.args = (message,)
- self._dbus_error_name = ".".join(
- [const_ERROR_PREFIX, class_.__module__, class_.__name__]
+ data = (data,)
+ else:
+ data = (str(twisted_error),)
+ self.dbusErrorName = ".".join(
+ (const_ERROR_PREFIX, class_.__module__, class_.__name__)
)
+ super(GenericException, self).__init__(repr(data))
+
+ @classmethod
+ def create_and_raise(cls, exc):
+ raise cls(exc)
-class DbusObject(dbus.service.Object):
- def __init__(self, bus, path):
- dbus.service.Object.__init__(self, bus, path)
- log.debug("Init DbusObject...")
+class DBusObject(objects.DBusObject):
+
+ core_iface = DBusInterface(
+ const_INT_PREFIX + const_CORE_SUFFIX,
+##METHODS_DECLARATIONS_PART##
+##SIGNALS_DECLARATIONS_PART##
+ )
+ plugin_iface = DBusInterface(
+ const_INT_PREFIX + const_PLUGIN_SUFFIX
+ )
+
+ dbusInterfaces = [core_iface, plugin_iface]
+
+ def __init__(self, path):
+ super().__init__(path)
+ log.debug("Init DBusObject...")
self.cb = {}
def register_method(self, name, cb):
self.cb[name] = cb
def _callback(self, name, *args, **kwargs):
- """call the callback if it exists, raise an exception else
- if the callback return a deferred, use async methods"""
- if not name in self.cb:
+ """Call the callback if it exists, raise an exception else"""
+ try:
+ cb = self.cb[name]
+ except KeyError:
raise MethodNotRegistered
-
- if "callback" in kwargs:
- # we must have errback too
- if not "errback" in kwargs:
- log.error("errback is missing in method call [%s]" % name)
- raise InternalError
- callback = kwargs.pop("callback")
- errback = kwargs.pop("errback")
- async_ = True
else:
- async_ = False
- result = self.cb[name](*args, **kwargs)
- if async_:
- if not isinstance(result, Deferred):
- log.error("Asynchronous method [%s] does not return a Deferred." % name)
- raise AsyncNotDeferred
- result.addCallback(
- lambda result: callback() if result is None else callback(result)
- )
- result.addErrback(lambda err: errback(GenericException(err)))
- else:
- if isinstance(result, Deferred):
- log.error("Synchronous method [%s] return a Deferred." % name)
- raise DeferredNotAsync
- return result
-
- ### signals ###
-
- @dbus.service.signal(const_INT_PREFIX + const_PLUGIN_SUFFIX, signature="")
- def dummySignal(self):
- # FIXME: workaround for addSignal (doesn't work if one method doensn't
- # already exist for plugins), probably missing some initialisation, need
- # further investigations
- pass
-
-##SIGNALS_PART##
- ### methods ###
+ d = defer.maybeDeferred(cb, *args, **kwargs)
+ d.addErrback(GenericException.create_and_raise)
+ return d
##METHODS_PART##
- def __attributes(self, in_sign):
- """Return arguments to user given a in_sign
- @param in_sign: in_sign in the short form (using s,a,i,b etc)
- @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")"""
- i = 0
- idx = 0
- attr = []
- while i < len(in_sign):
- if in_sign[i] not in ["b", "y", "n", "i", "x", "q", "u", "t", "d", "s", "a"]:
- raise ParseError("Unmanaged attribute type [%c]" % in_sign[i])
- attr.append("arg_%i" % idx)
- idx += 1
+class Bridge:
- if in_sign[i] == "a":
- i += 1
- if (
- in_sign[i] != "{" and in_sign[i] != "("
- ): # FIXME: must manage tuples out of arrays
- i += 1
- continue # we have a simple type for the array
- opening_car = in_sign[i]
- assert opening_car in ["{", "("]
- closing_car = "}" if opening_car == "{" else ")"
- opening_count = 1
- while True: # we have a dict or a list of tuples
- i += 1
- if i >= len(in_sign):
- raise ParseError("missing }")
- if in_sign[i] == opening_car:
- opening_count += 1
- if in_sign[i] == closing_car:
- opening_count -= 1
- if opening_count == 0:
- break
- i += 1
- return attr
-
- def addMethod(self, name, int_suffix, in_sign, out_sign, method, async_=False):
- """Dynamically add a method to Dbus Bridge"""
- inspect_args = inspect.getfullargspec(method)
-
- _arguments = inspect_args.args
- _defaults = list(inspect_args.defaults or [])
-
- if inspect.ismethod(method):
- # if we have a method, we don't want the first argument (usually 'self')
- del (_arguments[0])
-
- # first arguments are for the _callback method
- arguments_callback = ", ".join(
- [repr(name)]
- + (
- (_arguments + ["callback=callback", "errback=errback"])
- if async_
- else _arguments
- )
- )
-
- if async_:
- _arguments.extend(["callback", "errback"])
- _defaults.extend([None, None])
-
- # now we create a second list with default values
- for i in range(1, len(_defaults) + 1):
- _arguments[-i] = "%s = %s" % (_arguments[-i], repr(_defaults[-i]))
-
- arguments_defaults = ", ".join(_arguments)
-
- code = compile(
- "def %(name)s (self,%(arguments_defaults)s): return self._callback(%(arguments_callback)s)"
- % {
- "name": name,
- "arguments_defaults": arguments_defaults,
- "arguments_callback": arguments_callback,
- },
- "",
- "exec",
- )
- exec(code) # FIXME: to the same thing in a cleaner way, without compile/exec
- method = locals()[name]
- async_callbacks = ("callback", "errback") if async_ else None
- setattr(
- DbusObject,
- name,
- dbus.service.method(
- const_INT_PREFIX + int_suffix,
- in_signature=in_sign,
- out_signature=out_sign,
- async_callbacks=async_callbacks,
- )(method),
- )
- function = getattr(self, name)
- func_table = self._dbus_class_table[
- self.__class__.__module__ + "." + self.__class__.__name__
- ][function._dbus_interface]
- func_table[function.__name__] = function # Needed for introspection
-
- def addSignal(self, name, int_suffix, signature, doc={}):
- """Dynamically add a signal to Dbus Bridge"""
- attributes = ", ".join(self.__attributes(signature))
- # TODO: use doc parameter to name attributes
-
- # code = compile ('def '+name+' (self,'+attributes+'): log.debug ("'+name+' signal")', '','exec') #XXX: the log.debug is too annoying with xmllog
- code = compile(
- "def " + name + " (self," + attributes + "): pass", "", "exec"
- )
- exec(code)
- signal = locals()[name]
- setattr(
- DbusObject,
- name,
- dbus.service.signal(const_INT_PREFIX + int_suffix, signature=signature)(
- signal
- ),
- )
- function = getattr(self, name)
- func_table = self._dbus_class_table[
- self.__class__.__module__ + "." + self.__class__.__name__
- ][function._dbus_interface]
- func_table[function.__name__] = function # Needed for introspection
-
-
-class Bridge(object):
def __init__(self):
- dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
log.info("Init DBus...")
+ self._obj = DBusObject(const_OBJ_PATH)
+
+ async def postInit(self):
try:
- self.session_bus = dbus.SessionBus()
- except dbus.DBusException as e:
- if e._dbus_error_name == "org.freedesktop.DBus.Error.NotSupported":
+ conn = await client.connect(reactor)
+ except error.DBusException as e:
+ if e.errName == "org.freedesktop.DBus.Error.NotSupported":
log.error(
_(
- "D-Bus is not launched, please see README to see instructions on how to launch it"
+ "D-Bus is not launched, please see README to see instructions on "
+ "how to launch it"
)
)
- raise BridgeInitError
- self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus)
- self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH)
+ raise BridgeInitError(str(e))
-##SIGNAL_DIRECT_CALLS_PART##
+ conn.exportObject(self._obj)
+ await conn.requestBusName(const_INT_PREFIX)
+
+##SIGNALS_PART##
def register_method(self, name, callback):
- log.debug("registering DBus bridge method [%s]" % name)
- self.dbus_bridge.register_method(name, callback)
+ log.debug(f"registering DBus bridge method [{name}]")
+ self._obj.register_method(name, callback)
- def addMethod(self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}):
- """Dynamically add a method to Dbus Bridge"""
+ def emitSignal(self, name, *args):
+ self._obj.emitSignal(name, *args)
+
+ def addMethod(
+ self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
+ ):
+ """Dynamically add a method to D-Bus Bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
- log.debug("Adding method [%s] to DBus bridge" % name)
- self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, method, async_)
+ log.debug(f"Adding method {name!r} to D-Bus bridge")
+ self._obj.plugin_iface.addMethod(
+ Method(name, arguments=in_sign, returns=out_sign)
+ )
+ # we have to create a method here instead of using partialmethod, because txdbus
+ # uses __func__ which doesn't work with partialmethod
+ def caller(self_, *args, **kwargs):
+ return self_._callback(name, *args, **kwargs)
+ setattr(self._obj, f"dbus_{name}", MethodType(caller, self._obj))
self.register_method(name, method)
def addSignal(self, name, int_suffix, signature, doc={}):
- self.dbus_bridge.addSignal(name, int_suffix, signature, doc)
- setattr(Bridge, name, getattr(self.dbus_bridge, name))
+ """Dynamically add a signal to D-Bus Bridge"""
+ log.debug(f"Adding signal {name!r} to D-Bus bridge")
+ self._obj.plugin_iface.addSignal(Signal(name, signature))
+ setattr(Bridge, name, partialmethod(Bridge.emitSignal, name))
diff --git a/sat/bridge/dbus_bridge.py b/sat/bridge/dbus_bridge.py
index 223c2ac5..b9268390 100644
--- a/sat/bridge/dbus_bridge.py
+++ b/sat/bridge/dbus_bridge.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# SàT communication bridge
+# Libervia communication bridge
# Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
# This program is free software: you can redistribute it and/or modify
@@ -16,15 +16,15 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+from types import MethodType
+from functools import partialmethod
+from twisted.internet import defer, reactor
from sat.core.i18n import _
-import dbus
-import dbus.service
-import dbus.mainloop.glib
-import inspect
from sat.core.log import getLogger
-from sat.tools import config
-from twisted.internet.defer import Deferred
from sat.core.exceptions import BridgeInitError
+from sat.tools import config
+from txdbus import client, objects, error
+from txdbus.interface import DBusInterface, Method, Signal
log = getLogger(__name__)
@@ -45,772 +45,451 @@ class ParseError(Exception):
pass
-class MethodNotRegistered(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".MethodNotRegistered"
+class DBusException(Exception):
+ pass
-class InternalError(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".InternalError"
+class MethodNotRegistered(DBusException):
+ dbusErrorName = const_ERROR_PREFIX + ".MethodNotRegistered"
-class AsyncNotDeferred(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".AsyncNotDeferred"
-
-
-class DeferredNotAsync(dbus.DBusException):
- _dbus_error_name = const_ERROR_PREFIX + ".DeferredNotAsync"
-
-
-class GenericException(dbus.DBusException):
+class GenericException(DBusException):
def __init__(self, twisted_error):
"""
@param twisted_error (Failure): instance of twisted Failure
- @return: DBusException
+ error message is used to store a repr of message and condition in a tuple,
+ so it can be evaluated by the frontend bridge.
"""
- super(GenericException, self).__init__()
try:
# twisted_error.value is a class
class_ = twisted_error.value().__class__
except TypeError:
# twisted_error.value is an instance
class_ = twisted_error.value.__class__
- message = twisted_error.getErrorMessage()
+ data = twisted_error.getErrorMessage()
try:
- self.args = (message, twisted_error.value.condition)
+ data = (data, twisted_error.value.condition)
except AttributeError:
- self.args = (message,)
- self._dbus_error_name = ".".join(
- [const_ERROR_PREFIX, class_.__module__, class_.__name__]
+ data = (data,)
+ else:
+ data = (str(twisted_error),)
+ self.dbusErrorName = ".".join(
+ (const_ERROR_PREFIX, class_.__module__, class_.__name__)
)
+ super(GenericException, self).__init__(repr(data))
+
+ @classmethod
+ def create_and_raise(cls, exc):
+ raise cls(exc)
-class DbusObject(dbus.service.Object):
- def __init__(self, bus, path):
- dbus.service.Object.__init__(self, bus, path)
- log.debug("Init DbusObject...")
+class DBusObject(objects.DBusObject):
+
+ core_iface = DBusInterface(
+ const_INT_PREFIX + const_CORE_SUFFIX,
+ Method('actionsGet', arguments='s', returns='a(a{ss}si)'),
+ Method('addContact', arguments='ss', returns=''),
+ Method('asyncDeleteProfile', arguments='s', returns=''),
+ Method('asyncGetParamA', arguments='sssis', returns='s'),
+ Method('asyncGetParamsValuesFromCategory', arguments='sisss', returns='a{ss}'),
+ Method('connect', arguments='ssa{ss}', returns='b'),
+ Method('contactGet', arguments='ss', returns='(a{ss}as)'),
+ Method('delContact', arguments='ss', returns=''),
+ Method('devicesInfosGet', arguments='ss', returns='s'),
+ Method('discoFindByFeatures', arguments='asa(ss)bbbbbs', returns='(a{sa(sss)}a{sa(sss)}a{sa(sss)})'),
+ Method('discoInfos', arguments='ssbs', returns='(asa(sss)a{sa(a{ss}as)})'),
+ Method('discoItems', arguments='ssbs', returns='a(sss)'),
+ Method('disconnect', arguments='s', returns=''),
+ Method('encryptionNamespaceGet', arguments='s', returns='s'),
+ Method('encryptionPluginsGet', arguments='', returns='s'),
+ Method('encryptionTrustUIGet', arguments='sss', returns='s'),
+ Method('getConfig', arguments='ss', returns='s'),
+ Method('getContacts', arguments='s', returns='a(sa{ss}as)'),
+ Method('getContactsFromGroup', arguments='ss', returns='as'),
+ Method('getEntitiesData', arguments='asass', returns='a{sa{ss}}'),
+ Method('getEntityData', arguments='sass', returns='a{ss}'),
+ Method('getFeatures', arguments='s', returns='a{sa{ss}}'),
+ Method('getMainResource', arguments='ss', returns='s'),
+ Method('getParamA', arguments='ssss', returns='s'),
+ Method('getParamsCategories', arguments='', returns='as'),
+ Method('getParamsUI', arguments='isss', returns='s'),
+ Method('getPresenceStatuses', arguments='s', returns='a{sa{s(sia{ss})}}'),
+ Method('getReady', arguments='', returns=''),
+ Method('getVersion', arguments='', returns='s'),
+ Method('getWaitingSub', arguments='s', returns='a{ss}'),
+ Method('historyGet', arguments='ssiba{ss}s', returns='a(sdssa{ss}a{ss}ss)'),
+ Method('imageCheck', arguments='s', returns='s'),
+ Method('imageConvert', arguments='ssss', returns='s'),
+ Method('imageGeneratePreview', arguments='ss', returns='s'),
+ Method('imageResize', arguments='sii', returns='s'),
+ Method('isConnected', arguments='s', returns='b'),
+ Method('launchAction', arguments='sa{ss}s', returns='a{ss}'),
+ Method('loadParamsTemplate', arguments='s', returns='b'),
+ Method('menuHelpGet', arguments='ss', returns='s'),
+ Method('menuLaunch', arguments='sasa{ss}is', returns='a{ss}'),
+ Method('menusGet', arguments='si', returns='a(ssasasa{ss})'),
+ Method('messageEncryptionGet', arguments='ss', returns='s'),
+ Method('messageEncryptionStart', arguments='ssbs', returns=''),
+ Method('messageEncryptionStop', arguments='ss', returns=''),
+ Method('messageSend', arguments='sa{ss}a{ss}sss', returns=''),
+ Method('namespacesGet', arguments='', returns='a{ss}'),
+ Method('paramsRegisterApp', arguments='sis', returns=''),
+ Method('privateDataDelete', arguments='sss', returns=''),
+ Method('privateDataGet', arguments='sss', returns='s'),
+ Method('privateDataSet', arguments='ssss', returns=''),
+ Method('profileCreate', arguments='sss', returns=''),
+ Method('profileIsSessionStarted', arguments='s', returns='b'),
+ Method('profileNameGet', arguments='s', returns='s'),
+ Method('profileSetDefault', arguments='s', returns=''),
+ Method('profileStartSession', arguments='ss', returns='b'),
+ Method('profilesListGet', arguments='bb', returns='as'),
+ Method('progressGet', arguments='ss', returns='a{ss}'),
+ Method('progressGetAll', arguments='s', returns='a{sa{sa{ss}}}'),
+ Method('progressGetAllMetadata', arguments='s', returns='a{sa{sa{ss}}}'),
+ Method('rosterResync', arguments='s', returns=''),
+ Method('saveParamsTemplate', arguments='s', returns='b'),
+ Method('sessionInfosGet', arguments='s', returns='a{ss}'),
+ Method('setParam', arguments='sssis', returns=''),
+ Method('setPresence', arguments='ssa{ss}s', returns=''),
+ Method('subscription', arguments='sss', returns=''),
+ Method('updateContact', arguments='ssass', returns=''),
+ Signal('_debug', 'sa{ss}s'),
+ Signal('actionNew', 'a{ss}sis'),
+ Signal('connected', 'ss'),
+ Signal('contactDeleted', 'ss'),
+ Signal('disconnected', 's'),
+ Signal('entityDataUpdated', 'ssss'),
+ Signal('messageEncryptionStarted', 'sss'),
+ Signal('messageEncryptionStopped', 'sa{ss}s'),
+ Signal('messageNew', 'sdssa{ss}a{ss}sss'),
+ Signal('newContact', 'sa{ss}ass'),
+ Signal('paramUpdate', 'ssss'),
+ Signal('presenceUpdate', 'ssia{ss}s'),
+ Signal('progressError', 'sss'),
+ Signal('progressFinished', 'sa{ss}s'),
+ Signal('progressStarted', 'sa{ss}s'),
+ Signal('subscribe', 'sss'),
+ )
+ plugin_iface = DBusInterface(
+ const_INT_PREFIX + const_PLUGIN_SUFFIX
+ )
+
+ dbusInterfaces = [core_iface, plugin_iface]
+
+ def __init__(self, path):
+ super().__init__(path)
+ log.debug("Init DBusObject...")
self.cb = {}
def register_method(self, name, cb):
self.cb[name] = cb
def _callback(self, name, *args, **kwargs):
- """call the callback if it exists, raise an exception else
- if the callback return a deferred, use async methods"""
- if not name in self.cb:
+ """Call the callback if it exists, raise an exception else"""
+ try:
+ cb = self.cb[name]
+ except KeyError:
raise MethodNotRegistered
-
- if "callback" in kwargs:
- # we must have errback too
- if not "errback" in kwargs:
- log.error("errback is missing in method call [%s]" % name)
- raise InternalError
- callback = kwargs.pop("callback")
- errback = kwargs.pop("errback")
- async_ = True
else:
- async_ = False
- result = self.cb[name](*args, **kwargs)
- if async_:
- if not isinstance(result, Deferred):
- log.error("Asynchronous method [%s] does not return a Deferred." % name)
- raise AsyncNotDeferred
- result.addCallback(
- lambda result: callback() if result is None else callback(result)
- )
- result.addErrback(lambda err: errback(GenericException(err)))
- else:
- if isinstance(result, Deferred):
- log.error("Synchronous method [%s] return a Deferred." % name)
- raise DeferredNotAsync
- return result
+ d = defer.maybeDeferred(cb, *args, **kwargs)
+ d.addErrback(GenericException.create_and_raise)
+ return d
- ### signals ###
+ def dbus_actionsGet(self, profile_key="@DEFAULT@"):
+ return self._callback("actionsGet", profile_key)
- @dbus.service.signal(const_INT_PREFIX + const_PLUGIN_SUFFIX, signature="")
- def dummySignal(self):
- # FIXME: workaround for addSignal (doesn't work if one method doensn't
- # already exist for plugins), probably missing some initialisation, need
- # further investigations
- pass
+ def dbus_addContact(self, entity_jid, profile_key="@DEFAULT@"):
+ return self._callback("addContact", entity_jid, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sa{ss}s')
- def _debug(self, action, params, profile):
- pass
+ def dbus_asyncDeleteProfile(self, profile):
+ return self._callback("asyncDeleteProfile", profile)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='a{ss}sis')
- def actionNew(self, action_data, id, security_limit, profile):
- pass
+ def dbus_asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@"):
+ return self._callback("asyncGetParamA", name, category, attribute, security_limit, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='ss')
- def connected(self, jid_s, profile):
- pass
+ def dbus_asyncGetParamsValuesFromCategory(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@"):
+ return self._callback("asyncGetParamsValuesFromCategory", category, security_limit, app, extra, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='ss')
- def contactDeleted(self, entity_jid, profile):
- pass
+ def dbus_connect(self, profile_key="@DEFAULT@", password='', options={}):
+ return self._callback("connect", profile_key, password, options)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='s')
- def disconnected(self, profile):
- pass
+ def dbus_contactGet(self, arg_0, profile_key="@DEFAULT@"):
+ return self._callback("contactGet", arg_0, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='ssss')
- def entityDataUpdated(self, jid, name, value, profile):
- pass
+ def dbus_delContact(self, entity_jid, profile_key="@DEFAULT@"):
+ return self._callback("delContact", entity_jid, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sss')
- def messageEncryptionStarted(self, to_jid, encryption_data, profile_key):
- pass
+ def dbus_devicesInfosGet(self, bare_jid, profile_key):
+ return self._callback("devicesInfosGet", bare_jid, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sa{ss}s')
- def messageEncryptionStopped(self, to_jid, encryption_data, profile_key):
- pass
+ def dbus_discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@"):
+ return self._callback("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sdssa{ss}a{ss}sss')
- def messageNew(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
- pass
+ def dbus_discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
+ return self._callback("discoInfos", entity_jid, node, use_cache, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sa{ss}ass')
- def newContact(self, contact_jid, attributes, groups, profile):
- pass
+ def dbus_discoItems(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
+ return self._callback("discoItems", entity_jid, node, use_cache, profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='ssss')
- def paramUpdate(self, name, value, category, profile):
- pass
+ def dbus_disconnect(self, profile_key="@DEFAULT@"):
+ return self._callback("disconnect", profile_key)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='ssia{ss}s')
- def presenceUpdate(self, entity_jid, show, priority, statuses, profile):
- pass
+ def dbus_encryptionNamespaceGet(self, arg_0):
+ return self._callback("encryptionNamespaceGet", arg_0)
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sss')
- def progressError(self, id, error, profile):
- pass
-
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sa{ss}s')
- def progressFinished(self, id, metadata, profile):
- pass
-
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sa{ss}s')
- def progressStarted(self, id, metadata, profile):
- pass
-
- @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
- signature='sss')
- def subscribe(self, sub_type, entity_jid, profile):
- pass
-
- ### methods ###
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a(a{ss}si)',
- async_callbacks=None)
- def actionsGet(self, profile_key="@DEFAULT@"):
- return self._callback("actionsGet", str(profile_key))
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='',
- async_callbacks=None)
- def addContact(self, entity_jid, profile_key="@DEFAULT@"):
- return self._callback("addContact", str(entity_jid), str(profile_key))
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='',
- async_callbacks=('callback', 'errback'))
- def asyncDeleteProfile(self, profile, callback=None, errback=None):
- return self._callback("asyncDeleteProfile", str(profile), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sssis', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("asyncGetParamA", str(name), str(category), str(attribute), security_limit, str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sisss', out_signature='a{ss}',
- async_callbacks=('callback', 'errback'))
- def asyncGetParamsValuesFromCategory(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("asyncGetParamsValuesFromCategory", str(category), security_limit, str(app), str(extra), str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssa{ss}', out_signature='b',
- async_callbacks=('callback', 'errback'))
- def connect(self, profile_key="@DEFAULT@", password='', options={}, callback=None, errback=None):
- return self._callback("connect", str(profile_key), str(password), options, callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='(a{ss}as)',
- async_callbacks=('callback', 'errback'))
- def contactGet(self, arg_0, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("contactGet", str(arg_0), str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='',
- async_callbacks=('callback', 'errback'))
- def delContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("delContact", str(entity_jid), str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def devicesInfosGet(self, bare_jid, profile_key, callback=None, errback=None):
- return self._callback("devicesInfosGet", str(bare_jid), str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='asa(ss)bbbbbs', out_signature='(a{sa(sss)}a{sa(sss)}a{sa(sss)})',
- async_callbacks=('callback', 'errback'))
- def discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssbs', out_signature='(asa(sss)a{sa(a{ss}as)})',
- async_callbacks=('callback', 'errback'))
- def discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("discoInfos", str(entity_jid), str(node), use_cache, str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssbs', out_signature='a(sss)',
- async_callbacks=('callback', 'errback'))
- def discoItems(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("discoItems", str(entity_jid), str(node), use_cache, str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='',
- async_callbacks=('callback', 'errback'))
- def disconnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("disconnect", str(profile_key), callback=callback, errback=errback)
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='s',
- async_callbacks=None)
- def encryptionNamespaceGet(self, arg_0):
- return self._callback("encryptionNamespaceGet", str(arg_0))
-
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='', out_signature='s',
- async_callbacks=None)
- def encryptionPluginsGet(self, ):
+ def dbus_encryptionPluginsGet(self, ):
return self._callback("encryptionPluginsGet", )
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sss', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def encryptionTrustUIGet(self, to_jid, namespace, profile_key, callback=None, errback=None):
- return self._callback("encryptionTrustUIGet", str(to_jid), str(namespace), str(profile_key), callback=callback, errback=errback)
+ def dbus_encryptionTrustUIGet(self, to_jid, namespace, profile_key):
+ return self._callback("encryptionTrustUIGet", to_jid, namespace, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='s',
- async_callbacks=None)
- def getConfig(self, section, name):
- return self._callback("getConfig", str(section), str(name))
+ def dbus_getConfig(self, section, name):
+ return self._callback("getConfig", section, name)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a(sa{ss}as)',
- async_callbacks=('callback', 'errback'))
- def getContacts(self, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("getContacts", str(profile_key), callback=callback, errback=errback)
+ def dbus_getContacts(self, profile_key="@DEFAULT@"):
+ return self._callback("getContacts", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='as',
- async_callbacks=None)
- def getContactsFromGroup(self, group, profile_key="@DEFAULT@"):
- return self._callback("getContactsFromGroup", str(group), str(profile_key))
+ def dbus_getContactsFromGroup(self, group, profile_key="@DEFAULT@"):
+ return self._callback("getContactsFromGroup", group, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='asass', out_signature='a{sa{ss}}',
- async_callbacks=None)
- def getEntitiesData(self, jids, keys, profile):
- return self._callback("getEntitiesData", jids, keys, str(profile))
+ def dbus_getEntitiesData(self, jids, keys, profile):
+ return self._callback("getEntitiesData", jids, keys, profile)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sass', out_signature='a{ss}',
- async_callbacks=None)
- def getEntityData(self, jid, keys, profile):
- return self._callback("getEntityData", str(jid), keys, str(profile))
+ def dbus_getEntityData(self, jid, keys, profile):
+ return self._callback("getEntityData", jid, keys, profile)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a{sa{ss}}',
- async_callbacks=('callback', 'errback'))
- def getFeatures(self, profile_key, callback=None, errback=None):
- return self._callback("getFeatures", str(profile_key), callback=callback, errback=errback)
+ def dbus_getFeatures(self, profile_key):
+ return self._callback("getFeatures", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='s',
- async_callbacks=None)
- def getMainResource(self, contact_jid, profile_key="@DEFAULT@"):
- return self._callback("getMainResource", str(contact_jid), str(profile_key))
+ def dbus_getMainResource(self, contact_jid, profile_key="@DEFAULT@"):
+ return self._callback("getMainResource", contact_jid, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssss', out_signature='s',
- async_callbacks=None)
- def getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
- return self._callback("getParamA", str(name), str(category), str(attribute), str(profile_key))
+ def dbus_getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
+ return self._callback("getParamA", name, category, attribute, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='', out_signature='as',
- async_callbacks=None)
- def getParamsCategories(self, ):
+ def dbus_getParamsCategories(self, ):
return self._callback("getParamsCategories", )
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='isss', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def getParamsUI(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("getParamsUI", security_limit, str(app), str(extra), str(profile_key), callback=callback, errback=errback)
+ def dbus_getParamsUI(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@"):
+ return self._callback("getParamsUI", security_limit, app, extra, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a{sa{s(sia{ss})}}',
- async_callbacks=None)
- def getPresenceStatuses(self, profile_key="@DEFAULT@"):
- return self._callback("getPresenceStatuses", str(profile_key))
+ def dbus_getPresenceStatuses(self, profile_key="@DEFAULT@"):
+ return self._callback("getPresenceStatuses", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='', out_signature='',
- async_callbacks=('callback', 'errback'))
- def getReady(self, callback=None, errback=None):
- return self._callback("getReady", callback=callback, errback=errback)
+ def dbus_getReady(self, ):
+ return self._callback("getReady", )
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='', out_signature='s',
- async_callbacks=None)
- def getVersion(self, ):
+ def dbus_getVersion(self, ):
return self._callback("getVersion", )
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a{ss}',
- async_callbacks=None)
- def getWaitingSub(self, profile_key="@DEFAULT@"):
- return self._callback("getWaitingSub", str(profile_key))
+ def dbus_getWaitingSub(self, profile_key="@DEFAULT@"):
+ return self._callback("getWaitingSub", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssiba{ss}s', out_signature='a(sdssa{ss}a{ss}ss)',
- async_callbacks=('callback', 'errback'))
- def historyGet(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@", callback=None, errback=None):
- return self._callback("historyGet", str(from_jid), str(to_jid), limit, between, filters, str(profile), callback=callback, errback=errback)
+ def dbus_historyGet(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@"):
+ return self._callback("historyGet", from_jid, to_jid, limit, between, filters, profile)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='s',
- async_callbacks=None)
- def imageCheck(self, arg_0):
- return self._callback("imageCheck", str(arg_0))
+ def dbus_imageCheck(self, arg_0):
+ return self._callback("imageCheck", arg_0)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssss', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def imageConvert(self, source, dest, arg_2, extra, callback=None, errback=None):
- return self._callback("imageConvert", str(source), str(dest), str(arg_2), str(extra), callback=callback, errback=errback)
+ def dbus_imageConvert(self, source, dest, arg_2, extra):
+ return self._callback("imageConvert", source, dest, arg_2, extra)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def imageGeneratePreview(self, image_path, profile_key, callback=None, errback=None):
- return self._callback("imageGeneratePreview", str(image_path), str(profile_key), callback=callback, errback=errback)
+ def dbus_imageGeneratePreview(self, image_path, profile_key):
+ return self._callback("imageGeneratePreview", image_path, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sii', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def imageResize(self, image_path, width, height, callback=None, errback=None):
- return self._callback("imageResize", str(image_path), width, height, callback=callback, errback=errback)
+ def dbus_imageResize(self, image_path, width, height):
+ return self._callback("imageResize", image_path, width, height)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='b',
- async_callbacks=None)
- def isConnected(self, profile_key="@DEFAULT@"):
- return self._callback("isConnected", str(profile_key))
+ def dbus_isConnected(self, profile_key="@DEFAULT@"):
+ return self._callback("isConnected", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sa{ss}s', out_signature='a{ss}',
- async_callbacks=('callback', 'errback'))
- def launchAction(self, callback_id, data, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("launchAction", str(callback_id), data, str(profile_key), callback=callback, errback=errback)
+ def dbus_launchAction(self, callback_id, data, profile_key="@DEFAULT@"):
+ return self._callback("launchAction", callback_id, data, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='b',
- async_callbacks=None)
- def loadParamsTemplate(self, filename):
- return self._callback("loadParamsTemplate", str(filename))
+ def dbus_loadParamsTemplate(self, filename):
+ return self._callback("loadParamsTemplate", filename)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='s',
- async_callbacks=None)
- def menuHelpGet(self, menu_id, language):
- return self._callback("menuHelpGet", str(menu_id), str(language))
+ def dbus_menuHelpGet(self, menu_id, language):
+ return self._callback("menuHelpGet", menu_id, language)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sasa{ss}is', out_signature='a{ss}',
- async_callbacks=('callback', 'errback'))
- def menuLaunch(self, menu_type, path, data, security_limit, profile_key, callback=None, errback=None):
- return self._callback("menuLaunch", str(menu_type), path, data, security_limit, str(profile_key), callback=callback, errback=errback)
+ def dbus_menuLaunch(self, menu_type, path, data, security_limit, profile_key):
+ return self._callback("menuLaunch", menu_type, path, data, security_limit, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='si', out_signature='a(ssasasa{ss})',
- async_callbacks=None)
- def menusGet(self, language, security_limit):
- return self._callback("menusGet", str(language), security_limit)
+ def dbus_menusGet(self, language, security_limit):
+ return self._callback("menusGet", language, security_limit)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='s',
- async_callbacks=None)
- def messageEncryptionGet(self, to_jid, profile_key):
- return self._callback("messageEncryptionGet", str(to_jid), str(profile_key))
+ def dbus_messageEncryptionGet(self, to_jid, profile_key):
+ return self._callback("messageEncryptionGet", to_jid, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssbs', out_signature='',
- async_callbacks=('callback', 'errback'))
- def messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@", callback=None, errback=None):
- return self._callback("messageEncryptionStart", str(to_jid), str(namespace), replace, str(profile_key), callback=callback, errback=errback)
+ def dbus_messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@"):
+ return self._callback("messageEncryptionStart", to_jid, namespace, replace, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='',
- async_callbacks=('callback', 'errback'))
- def messageEncryptionStop(self, to_jid, profile_key, callback=None, errback=None):
- return self._callback("messageEncryptionStop", str(to_jid), str(profile_key), callback=callback, errback=errback)
+ def dbus_messageEncryptionStop(self, to_jid, profile_key):
+ return self._callback("messageEncryptionStop", to_jid, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sa{ss}a{ss}sss', out_signature='',
- async_callbacks=('callback', 'errback'))
- def messageSend(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@", callback=None, errback=None):
- return self._callback("messageSend", str(to_jid), message, subject, str(mess_type), str(extra), str(profile_key), callback=callback, errback=errback)
+ def dbus_messageSend(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@"):
+ return self._callback("messageSend", to_jid, message, subject, mess_type, extra, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='', out_signature='a{ss}',
- async_callbacks=None)
- def namespacesGet(self, ):
+ def dbus_namespacesGet(self, ):
return self._callback("namespacesGet", )
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sis', out_signature='',
- async_callbacks=None)
- def paramsRegisterApp(self, xml, security_limit=-1, app=''):
- return self._callback("paramsRegisterApp", str(xml), security_limit, str(app))
+ def dbus_paramsRegisterApp(self, xml, security_limit=-1, app=''):
+ return self._callback("paramsRegisterApp", xml, security_limit, app)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sss', out_signature='',
- async_callbacks=('callback', 'errback'))
- def privateDataDelete(self, namespace, key, arg_2, callback=None, errback=None):
- return self._callback("privateDataDelete", str(namespace), str(key), str(arg_2), callback=callback, errback=errback)
+ def dbus_privateDataDelete(self, namespace, key, arg_2):
+ return self._callback("privateDataDelete", namespace, key, arg_2)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sss', out_signature='s',
- async_callbacks=('callback', 'errback'))
- def privateDataGet(self, namespace, key, profile_key, callback=None, errback=None):
- return self._callback("privateDataGet", str(namespace), str(key), str(profile_key), callback=callback, errback=errback)
+ def dbus_privateDataGet(self, namespace, key, profile_key):
+ return self._callback("privateDataGet", namespace, key, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssss', out_signature='',
- async_callbacks=('callback', 'errback'))
- def privateDataSet(self, namespace, key, data, profile_key, callback=None, errback=None):
- return self._callback("privateDataSet", str(namespace), str(key), str(data), str(profile_key), callback=callback, errback=errback)
+ def dbus_privateDataSet(self, namespace, key, data, profile_key):
+ return self._callback("privateDataSet", namespace, key, data, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sss', out_signature='',
- async_callbacks=('callback', 'errback'))
- def profileCreate(self, profile, password='', component='', callback=None, errback=None):
- return self._callback("profileCreate", str(profile), str(password), str(component), callback=callback, errback=errback)
+ def dbus_profileCreate(self, profile, password='', component=''):
+ return self._callback("profileCreate", profile, password, component)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='b',
- async_callbacks=None)
- def profileIsSessionStarted(self, profile_key="@DEFAULT@"):
- return self._callback("profileIsSessionStarted", str(profile_key))
+ def dbus_profileIsSessionStarted(self, profile_key="@DEFAULT@"):
+ return self._callback("profileIsSessionStarted", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='s',
- async_callbacks=None)
- def profileNameGet(self, profile_key="@DEFAULT@"):
- return self._callback("profileNameGet", str(profile_key))
+ def dbus_profileNameGet(self, profile_key="@DEFAULT@"):
+ return self._callback("profileNameGet", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='',
- async_callbacks=None)
- def profileSetDefault(self, profile):
- return self._callback("profileSetDefault", str(profile))
+ def dbus_profileSetDefault(self, profile):
+ return self._callback("profileSetDefault", profile)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='b',
- async_callbacks=('callback', 'errback'))
- def profileStartSession(self, password='', profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("profileStartSession", str(password), str(profile_key), callback=callback, errback=errback)
+ def dbus_profileStartSession(self, password='', profile_key="@DEFAULT@"):
+ return self._callback("profileStartSession", password, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='bb', out_signature='as',
- async_callbacks=None)
- def profilesListGet(self, clients=True, components=False):
+ def dbus_profilesListGet(self, clients=True, components=False):
return self._callback("profilesListGet", clients, components)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ss', out_signature='a{ss}',
- async_callbacks=None)
- def progressGet(self, id, profile):
- return self._callback("progressGet", str(id), str(profile))
+ def dbus_progressGet(self, id, profile):
+ return self._callback("progressGet", id, profile)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a{sa{sa{ss}}}',
- async_callbacks=None)
- def progressGetAll(self, profile):
- return self._callback("progressGetAll", str(profile))
+ def dbus_progressGetAll(self, profile):
+ return self._callback("progressGetAll", profile)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a{sa{sa{ss}}}',
- async_callbacks=None)
- def progressGetAllMetadata(self, profile):
- return self._callback("progressGetAllMetadata", str(profile))
+ def dbus_progressGetAllMetadata(self, profile):
+ return self._callback("progressGetAllMetadata", profile)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='',
- async_callbacks=('callback', 'errback'))
- def rosterResync(self, profile_key="@DEFAULT@", callback=None, errback=None):
- return self._callback("rosterResync", str(profile_key), callback=callback, errback=errback)
+ def dbus_rosterResync(self, profile_key="@DEFAULT@"):
+ return self._callback("rosterResync", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='b',
- async_callbacks=None)
- def saveParamsTemplate(self, filename):
- return self._callback("saveParamsTemplate", str(filename))
+ def dbus_saveParamsTemplate(self, filename):
+ return self._callback("saveParamsTemplate", filename)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='s', out_signature='a{ss}',
- async_callbacks=('callback', 'errback'))
- def sessionInfosGet(self, profile_key, callback=None, errback=None):
- return self._callback("sessionInfosGet", str(profile_key), callback=callback, errback=errback)
+ def dbus_sessionInfosGet(self, profile_key):
+ return self._callback("sessionInfosGet", profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sssis', out_signature='',
- async_callbacks=None)
- def setParam(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"):
- return self._callback("setParam", str(name), str(value), str(category), security_limit, str(profile_key))
+ def dbus_setParam(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"):
+ return self._callback("setParam", name, value, category, security_limit, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssa{ss}s', out_signature='',
- async_callbacks=None)
- def setPresence(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@"):
- return self._callback("setPresence", str(to_jid), str(show), statuses, str(profile_key))
+ def dbus_setPresence(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@"):
+ return self._callback("setPresence", to_jid, show, statuses, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='sss', out_signature='',
- async_callbacks=None)
- def subscription(self, sub_type, entity, profile_key="@DEFAULT@"):
- return self._callback("subscription", str(sub_type), str(entity), str(profile_key))
+ def dbus_subscription(self, sub_type, entity, profile_key="@DEFAULT@"):
+ return self._callback("subscription", sub_type, entity, profile_key)
- @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
- in_signature='ssass', out_signature='',
- async_callbacks=None)
- def updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@"):
- return self._callback("updateContact", str(entity_jid), str(name), groups, str(profile_key))
-
- def __attributes(self, in_sign):
- """Return arguments to user given a in_sign
- @param in_sign: in_sign in the short form (using s,a,i,b etc)
- @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")"""
- i = 0
- idx = 0
- attr = []
- while i < len(in_sign):
- if in_sign[i] not in ["b", "y", "n", "i", "x", "q", "u", "t", "d", "s", "a"]:
- raise ParseError("Unmanaged attribute type [%c]" % in_sign[i])
-
- attr.append("arg_%i" % idx)
- idx += 1
-
- if in_sign[i] == "a":
- i += 1
- if (
- in_sign[i] != "{" and in_sign[i] != "("
- ): # FIXME: must manage tuples out of arrays
- i += 1
- continue # we have a simple type for the array
- opening_car = in_sign[i]
- assert opening_car in ["{", "("]
- closing_car = "}" if opening_car == "{" else ")"
- opening_count = 1
- while True: # we have a dict or a list of tuples
- i += 1
- if i >= len(in_sign):
- raise ParseError("missing }")
- if in_sign[i] == opening_car:
- opening_count += 1
- if in_sign[i] == closing_car:
- opening_count -= 1
- if opening_count == 0:
- break
- i += 1
- return attr
-
- def addMethod(self, name, int_suffix, in_sign, out_sign, method, async_=False):
- """Dynamically add a method to Dbus Bridge"""
- inspect_args = inspect.getfullargspec(method)
-
- _arguments = inspect_args.args
- _defaults = list(inspect_args.defaults or [])
-
- if inspect.ismethod(method):
- # if we have a method, we don't want the first argument (usually 'self')
- del (_arguments[0])
-
- # first arguments are for the _callback method
- arguments_callback = ", ".join(
- [repr(name)]
- + (
- (_arguments + ["callback=callback", "errback=errback"])
- if async_
- else _arguments
- )
- )
-
- if async_:
- _arguments.extend(["callback", "errback"])
- _defaults.extend([None, None])
-
- # now we create a second list with default values
- for i in range(1, len(_defaults) + 1):
- _arguments[-i] = "%s = %s" % (_arguments[-i], repr(_defaults[-i]))
-
- arguments_defaults = ", ".join(_arguments)
-
- code = compile(
- "def %(name)s (self,%(arguments_defaults)s): return self._callback(%(arguments_callback)s)"
- % {
- "name": name,
- "arguments_defaults": arguments_defaults,
- "arguments_callback": arguments_callback,
- },
- "",
- "exec",
- )
- exec(code) # FIXME: to the same thing in a cleaner way, without compile/exec
- method = locals()[name]
- async_callbacks = ("callback", "errback") if async_ else None
- setattr(
- DbusObject,
- name,
- dbus.service.method(
- const_INT_PREFIX + int_suffix,
- in_signature=in_sign,
- out_signature=out_sign,
- async_callbacks=async_callbacks,
- )(method),
- )
- function = getattr(self, name)
- func_table = self._dbus_class_table[
- self.__class__.__module__ + "." + self.__class__.__name__
- ][function._dbus_interface]
- func_table[function.__name__] = function # Needed for introspection
-
- def addSignal(self, name, int_suffix, signature, doc={}):
- """Dynamically add a signal to Dbus Bridge"""
- attributes = ", ".join(self.__attributes(signature))
- # TODO: use doc parameter to name attributes
-
- # code = compile ('def '+name+' (self,'+attributes+'): log.debug ("'+name+' signal")', '','exec') #XXX: the log.debug is too annoying with xmllog
- code = compile(
- "def " + name + " (self," + attributes + "): pass", "", "exec"
- )
- exec(code)
- signal = locals()[name]
- setattr(
- DbusObject,
- name,
- dbus.service.signal(const_INT_PREFIX + int_suffix, signature=signature)(
- signal
- ),
- )
- function = getattr(self, name)
- func_table = self._dbus_class_table[
- self.__class__.__module__ + "." + self.__class__.__name__
- ][function._dbus_interface]
- func_table[function.__name__] = function # Needed for introspection
+ def dbus_updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@"):
+ return self._callback("updateContact", entity_jid, name, groups, profile_key)
-class Bridge(object):
+class Bridge:
+
def __init__(self):
- dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
log.info("Init DBus...")
+ self._obj = DBusObject(const_OBJ_PATH)
+
+ async def postInit(self):
try:
- self.session_bus = dbus.SessionBus()
- except dbus.DBusException as e:
- if e._dbus_error_name == "org.freedesktop.DBus.Error.NotSupported":
+ conn = await client.connect(reactor)
+ except error.DBusException as e:
+ if e.errName == "org.freedesktop.DBus.Error.NotSupported":
log.error(
_(
- "D-Bus is not launched, please see README to see instructions on how to launch it"
+ "D-Bus is not launched, please see README to see instructions on "
+ "how to launch it"
)
)
- raise BridgeInitError
- self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus)
- self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH)
+ raise BridgeInitError(str(e))
+
+ conn.exportObject(self._obj)
+ await conn.requestBusName(const_INT_PREFIX)
def _debug(self, action, params, profile):
- self.dbus_bridge._debug(action, params, profile)
+ self._obj.emitSignal("_debug", action, params, profile)
def actionNew(self, action_data, id, security_limit, profile):
- self.dbus_bridge.actionNew(action_data, id, security_limit, profile)
+ self._obj.emitSignal("actionNew", action_data, id, security_limit, profile)
def connected(self, jid_s, profile):
- self.dbus_bridge.connected(jid_s, profile)
+ self._obj.emitSignal("connected", jid_s, profile)
def contactDeleted(self, entity_jid, profile):
- self.dbus_bridge.contactDeleted(entity_jid, profile)
+ self._obj.emitSignal("contactDeleted", entity_jid, profile)
def disconnected(self, profile):
- self.dbus_bridge.disconnected(profile)
+ self._obj.emitSignal("disconnected", profile)
def entityDataUpdated(self, jid, name, value, profile):
- self.dbus_bridge.entityDataUpdated(jid, name, value, profile)
+ self._obj.emitSignal("entityDataUpdated", jid, name, value, profile)
def messageEncryptionStarted(self, to_jid, encryption_data, profile_key):
- self.dbus_bridge.messageEncryptionStarted(to_jid, encryption_data, profile_key)
+ self._obj.emitSignal("messageEncryptionStarted", to_jid, encryption_data, profile_key)
def messageEncryptionStopped(self, to_jid, encryption_data, profile_key):
- self.dbus_bridge.messageEncryptionStopped(to_jid, encryption_data, profile_key)
+ self._obj.emitSignal("messageEncryptionStopped", to_jid, encryption_data, profile_key)
def messageNew(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
- self.dbus_bridge.messageNew(uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
+ self._obj.emitSignal("messageNew", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
def newContact(self, contact_jid, attributes, groups, profile):
- self.dbus_bridge.newContact(contact_jid, attributes, groups, profile)
+ self._obj.emitSignal("newContact", contact_jid, attributes, groups, profile)
def paramUpdate(self, name, value, category, profile):
- self.dbus_bridge.paramUpdate(name, value, category, profile)
+ self._obj.emitSignal("paramUpdate", name, value, category, profile)
def presenceUpdate(self, entity_jid, show, priority, statuses, profile):
- self.dbus_bridge.presenceUpdate(entity_jid, show, priority, statuses, profile)
+ self._obj.emitSignal("presenceUpdate", entity_jid, show, priority, statuses, profile)
def progressError(self, id, error, profile):
- self.dbus_bridge.progressError(id, error, profile)
+ self._obj.emitSignal("progressError", id, error, profile)
def progressFinished(self, id, metadata, profile):
- self.dbus_bridge.progressFinished(id, metadata, profile)
+ self._obj.emitSignal("progressFinished", id, metadata, profile)
def progressStarted(self, id, metadata, profile):
- self.dbus_bridge.progressStarted(id, metadata, profile)
+ self._obj.emitSignal("progressStarted", id, metadata, profile)
def subscribe(self, sub_type, entity_jid, profile):
- self.dbus_bridge.subscribe(sub_type, entity_jid, profile)
+ self._obj.emitSignal("subscribe", sub_type, entity_jid, profile)
def register_method(self, name, callback):
- log.debug("registering DBus bridge method [%s]" % name)
- self.dbus_bridge.register_method(name, callback)
+ log.debug(f"registering DBus bridge method [{name}]")
+ self._obj.register_method(name, callback)
- def addMethod(self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}):
- """Dynamically add a method to Dbus Bridge"""
+ def emitSignal(self, name, *args):
+ self._obj.emitSignal(name, *args)
+
+ def addMethod(
+ self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
+ ):
+ """Dynamically add a method to D-Bus Bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
- log.debug("Adding method [%s] to DBus bridge" % name)
- self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, method, async_)
+ log.debug(f"Adding method {name!r} to D-Bus bridge")
+ self._obj.plugin_iface.addMethod(
+ Method(name, arguments=in_sign, returns=out_sign)
+ )
+ # we have to create a method here instead of using partialmethod, because txdbus
+ # uses __func__ which doesn't work with partialmethod
+ def caller(self_, *args, **kwargs):
+ return self_._callback(name, *args, **kwargs)
+ setattr(self._obj, f"dbus_{name}", MethodType(caller, self._obj))
self.register_method(name, method)
def addSignal(self, name, int_suffix, signature, doc={}):
- self.dbus_bridge.addSignal(name, int_suffix, signature, doc)
- setattr(Bridge, name, getattr(self.dbus_bridge, name))
\ No newline at end of file
+ """Dynamically add a signal to D-Bus Bridge"""
+ log.debug(f"Adding signal {name!r} to D-Bus bridge")
+ self._obj.plugin_iface.addSignal(Signal(name, signature))
+ setattr(Bridge, name, partialmethod(Bridge.emitSignal, name))
\ No newline at end of file
diff --git a/sat/core/sat_main.py b/sat/core/sat_main.py
index 92ec02ef..309a0d49 100644
--- a/sat/core/sat_main.py
+++ b/sat/core/sat_main.py
@@ -81,7 +81,7 @@ class SAT(service.Service):
self.memory = memory.Memory(self)
- # trigger are used to change SàT behaviour
+ # trigger are used to change Libervia behaviour
self.trigger = (
trigger.TriggerManager()
)
@@ -90,14 +90,53 @@ class SAT(service.Service):
bridge_module = dynamic_import.bridge(bridge_name)
if bridge_module is None:
- log.error("Can't find bridge module of name {}".format(bridge_name))
+ log.error(f"Can't find bridge module of name {bridge_name}")
sys.exit(1)
- log.info("using {} bridge".format(bridge_name))
+ log.info(f"using {bridge_name} bridge")
try:
self.bridge = bridge_module.Bridge()
except exceptions.BridgeInitError:
- log.error("Bridge can't be initialised, can't start SàT core")
+ log.error("Bridge can't be initialised, can't start Libervia Backend")
sys.exit(1)
+
+ defer.ensureDeferred(self._postInit())
+
+ @property
+ def version(self):
+ """Return the short version of Libervia"""
+ return C.APP_VERSION
+
+ @property
+ def full_version(self):
+ """Return the full version of Libervia
+
+ In developement mode, release name and extra data are returned too
+ """
+ version = self.version
+ if version[-1] == "D":
+ # we are in debug version, we add extra data
+ try:
+ return self._version_cache
+ except AttributeError:
+ self._version_cache = "{} « {} » ({})".format(
+ version, C.APP_RELEASE_NAME, utils.getRepositoryData(sat)
+ )
+ return self._version_cache
+ else:
+ return version
+
+ @property
+ def bridge_name(self):
+ return os.path.splitext(os.path.basename(self.bridge.__file__))[0]
+
+ async def _postInit(self):
+ try:
+ bridge_pi = self.bridge.postInit
+ except AttributeError:
+ pass
+ else:
+ await bridge_pi()
+
self.bridge.register_method("getReady", lambda: self.initialised)
self.bridge.register_method("getVersion", lambda: self.full_version)
self.bridge.register_method("getFeatures", self.getFeatures)
@@ -176,37 +215,8 @@ class SAT(service.Service):
self.bridge.register_method("imageResize", self._imageResize)
self.bridge.register_method("imageGeneratePreview", self._imageGeneratePreview)
self.bridge.register_method("imageConvert", self._imageConvert)
- defer.ensureDeferred(self._postInit())
- @property
- def version(self):
- """Return the short version of SàT"""
- return C.APP_VERSION
- @property
- def full_version(self):
- """Return the full version of SàT
-
- In developement mode, release name and extra data are returned too
- """
- version = self.version
- if version[-1] == "D":
- # we are in debug version, we add extra data
- try:
- return self._version_cache
- except AttributeError:
- self._version_cache = "{} « {} » ({})".format(
- version, C.APP_RELEASE_NAME, utils.getRepositoryData(sat)
- )
- return self._version_cache
- else:
- return version
-
- @property
- def bridge_name(self):
- return os.path.splitext(os.path.basename(self.bridge.__file__))[0]
-
- async def _postInit(self):
await self.memory.initialise()
self.common_cache = cache.Cache(self, None)
log.info(_("Memory initialised"))
diff --git a/sat_frontends/bridge/bridge_frontend.py b/sat_frontends/bridge/bridge_frontend.py
index fe78946a..d75a10d8 100644
--- a/sat_frontends/bridge/bridge_frontend.py
+++ b/sat_frontends/bridge/bridge_frontend.py
@@ -28,15 +28,14 @@ class BridgeException(Exception):
@param message (str): error message
@param condition (str) : error condition
"""
- Exception.__init__(self)
+ super().__init__()
self.fullname = str(name)
self.message = str(message)
self.condition = str(condition) if condition else ""
self.module, __, self.classname = str(self.fullname).rpartition(".")
def __str__(self):
- message = (": %s" % self.message) if self.message else ""
- return self.classname + message
+ return self.classname + (f": {self.message}" if self.message else "")
def __eq__(self, other):
return self.classname == other
diff --git a/setup.py b/setup.py
index bdd68ba3..2c979e9f 100644
--- a/setup.py
+++ b/setup.py
@@ -54,6 +54,7 @@ install_requires = [
'pyyaml',
'sqlalchemy >= 1.4',
'aiosqlite',
+ 'txdbus'
]
extras_require = {