diff --git a/pydbus/__init__.py b/pydbus/__init__.py index 5576517..3b79e77 100644 --- a/pydbus/__init__.py +++ b/pydbus/__init__.py @@ -1,4 +1,5 @@ from .bus import SystemBus, SessionBus, connect +from .exceptions import DBusException from gi.repository.GLib import Variant -__all__ = ["SystemBus", "SessionBus", "connect", "Variant"] +__all__ = ["SystemBus", "SessionBus", "connect", "DBusException", "Variant"] diff --git a/pydbus/exceptions.py b/pydbus/exceptions.py new file mode 100644 index 0000000..46d4904 --- /dev/null +++ b/pydbus/exceptions.py @@ -0,0 +1,3 @@ +class DBusException(Exception): + dbus_name = 'org.freedesktop.DBus.Error.Failed' + silent = False diff --git a/pydbus/registration.py b/pydbus/registration.py index f531539..3749d83 100644 --- a/pydbus/registration.py +++ b/pydbus/registration.py @@ -6,6 +6,7 @@ from functools import partial from .method_call_context import MethodCallContext import logging +from .exceptions import DBusException try: from inspect import signature, Parameter @@ -87,15 +88,21 @@ def call_method(self, connection, sender, object_path, interface_name, method_na else: invocation.return_value(GLib.Variant("(" + "".join(outargs) + ")", result)) + # catch DBusExceptions and turn them into dbus_errors + except DBusException as e: + if not e.silent: + logger = logging.getLogger(__name__) + logger.exception("DBusException while handling %s.%s()", interface_name, method_name) + + invocation.return_dbus_error(e.dbus_name, str(e)) + + # catch all other Exceptions report and reraise them except Exception as e: logger = logging.getLogger(__name__) logger.exception("Exception while handling %s.%s()", interface_name, method_name) - #TODO Think of a better way to translate Python exception types to DBus error types. - e_type = type(e).__name__ - if not "." in e_type: - e_type = "unknown." + e_type - invocation.return_dbus_error(e_type, str(e)) + invocation.return_dbus_error(DBusException.dbus_name, "Uncought exception while handling.") + raise e def Get(self, interface_name, property_name): type = self.readable_properties[interface_name + "." + property_name] diff --git a/tests/dbus_exception.py b/tests/dbus_exception.py new file mode 100644 index 0000000..a46582a --- /dev/null +++ b/tests/dbus_exception.py @@ -0,0 +1,77 @@ +from pydbus import SessionBus, DBusException +from gi.repository import GLib +from threading import Thread +import sys + +done = 0 +loop = GLib.MainLoop() + +class CustomDBusException(DBusException): + dbus_name = "net.lew21.pydbus.Test.Error.Custom" + silent = True + +class TestObject(object): + ''' + + + + + + + + + + + ''' + def __init__(self, id): + self.id = id + + def QuitService(self): + loop.quit() + return None + + def RaiseException(self): + raise Exception("sensitive") + return None + + def RaiseDBusException(self): + raise CustomDBusException("insensitive") + return None + + +bus = SessionBus() + +with bus.publish("net.lew21.pydbus.Test", TestObject("Main")): + remoteMain = bus.get("net.lew21.pydbus.Test") + + def t1_func(): + try: + remoteMain.RaiseDBusException() + except Exception as e: + if 'insensitive' not in str(e): + raise e + if CustomDBusException.dbus_name not in str(e): + raise e + try: + remoteMain.RaiseException() + except Exception as e: + if 'sensitive' in str(e): + raise e + if DBusException.dbus_name not in str(e): + raise e + remoteMain.QuitService() + + t1 = Thread(None, t1_func) + t1.daemon = True + + def handle_timeout(): + print("ERROR: Timeout.") + sys.exit(1) + + GLib.timeout_add_seconds(2, handle_timeout) + + t1.start() + + loop.run() + + t1.join() diff --git a/tests/run.sh b/tests/run.sh index 8d93644..49a9352 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -15,4 +15,5 @@ then "$PYTHON" $TESTS_DIR/publish.py "$PYTHON" $TESTS_DIR/publish_properties.py "$PYTHON" $TESTS_DIR/publish_multiface.py + "$PYTHON" $TESTS_DIR/dbus_exception.py fi