diff --git a/backport-Raise-TimeoutError-if-a-DBus-call-times-out.patch b/backport-Raise-TimeoutError-if-a-DBus-call-times-out.patch new file mode 100644 index 0000000000000000000000000000000000000000..276126624d667d36a4ec9066594394ec22543012 --- /dev/null +++ b/backport-Raise-TimeoutError-if-a-DBus-call-times-out.patch @@ -0,0 +1,153 @@ +From a76cac78402df7ad01841c93fb64b02af4700b07 Mon Sep 17 00:00:00 2001 +From: Vendula Poncova +Date: Thu, 9 Jun 2022 15:41:08 +0200 +Subject: [PATCH] Raise TimeoutError if a DBus call times out + +* Raise the TimeoutError exception instead of the original GLib.Error. +* Improve the documentation of the timeout and add an example. +--- + dasbus/client/handler.py | 49 ++++++++++++++++++++++++++++------------ + tests/test_client.py | 18 ++++++++++++++- + tests/test_dbus.py | 21 +++++++++++++++++ + 3 files changed, 73 insertions(+), 15 deletions(-) + +diff --git a/dasbus/client/handler.py b/dasbus/client/handler.py +index 839f5a6..43b22f6 100644 +--- a/dasbus/client/handler.py ++++ b/dasbus/client/handler.py +@@ -137,6 +137,12 @@ class GLibClient(object): + """Unsubscribe from a signal.""" + connection.signal_unsubscribe(subscription_id) + ++ @classmethod ++ def is_timeout_error(cls, error): ++ """Is it a timeout error?""" ++ return isinstance(error, GLib.Error) \ ++ and error.matches(Gio.io_error_quark(), Gio.IOErrorEnum.TIMED_OUT) ++ + @classmethod + def is_remote_error(cls, error): + """Is it a remote DBus error?""" +@@ -479,22 +485,37 @@ class ClientObjectHandler(AbstractClientObjectHandler): + def _handle_method_error(self, error): + """Handle an error of a DBus call. + ++ If the call returned a DBus error, it will be mapped ++ to a Python exception based on the rules defined in ++ the available error mapper. It should be a subclass ++ of DBusError. ++ + :param error: an exception raised during the call ++ :raise Exception: if the call unexpectedly failed ++ :raise TimeoutError: if the DBus call timed out ++ :raise DBusError: if the call returned a DBus error + """ +- # Re-raise if it is not a remote DBus error. +- if not self._client.is_remote_error(error): +- raise error +- +- name = self._client.get_remote_error_name(error) +- cls = self._error_mapper.get_exception_type(name) +- message = self._client.get_remote_error_message(error) +- +- # Create a new exception. +- exception = cls(message) +- exception.dbus_name = name +- +- # Raise a new instance of the exception class. +- raise exception from None ++ if self._client.is_remote_error(error): ++ # Handle a remote DBus error. ++ name = self._client.get_remote_error_name(error) ++ cls = self._error_mapper.get_exception_type(name) ++ message = self._client.get_remote_error_message(error) ++ ++ # Create a new exception. ++ exception = cls(message) ++ exception.dbus_name = name ++ ++ # Raise a new instance of the exception class. ++ raise exception from None ++ ++ if self._client.is_timeout_error(error): ++ # Handle a timeout error. ++ raise TimeoutError( ++ "The DBus call timeout was reached." ++ ) from None ++ ++ # Or re-raise the original error. ++ raise error + + def _handle_method_result(self, result): + """Handle a result of a DBus call. +diff --git a/tests/test_client.py b/tests/test_client.py +index 03890ea..dcbdbb9 100644 +--- a/tests/test_client.py ++++ b/tests/test_client.py +@@ -30,7 +30,8 @@ from dasbus.typing import get_variant, get_variant_type, VariantType + + import gi + gi.require_version("Gio", "2.0") +-from gi.repository import Gio ++gi.require_version("GLib", "2.0") ++from gi.repository import Gio, GLib + + + class FakeException(Exception): +@@ -230,6 +231,21 @@ class DBusClientTestCase(unittest.TestCase): + + self.assertEqual(str(cm.exception), "My message.") + ++ # Handle timeout exception. ++ self._set_reply(GLib.Error.new_literal( ++ Gio.io_error_quark(), ++ "Timeout was reached", ++ Gio.IOErrorEnum.TIMED_OUT ++ )) ++ ++ with self.assertRaises(TimeoutError) as cm: ++ self.proxy.Method1() ++ ++ self.assertEqual( ++ str(cm.exception), ++ "The DBus call timeout was reached." ++ ) ++ + # Handle local exception. + self._set_reply(Exception("My message.")) + +diff --git a/tests/test_dbus.py b/tests/test_dbus.py +index d62e25c..4e372dc 100644 +--- a/tests/test_dbus.py ++++ b/tests/test_dbus.py +@@ -283,6 +283,27 @@ class DBusTestCase(unittest.TestCase): + + self.assertEqual(sorted(self.service._names), ["Bar", "Foo"]) + ++ def test_timeout(self): ++ """Call a DBus method with a timeout.""" ++ self._set_service(ExampleInterface()) ++ self.assertEqual(self.service._names, []) ++ ++ def test1(): ++ proxy = self._get_proxy() ++ proxy.Hello("Foo", timeout=1000) ++ ++ def test2(): ++ proxy = self._get_proxy() ++ ++ with self.assertRaises(TimeoutError): ++ proxy.Hello("Bar", timeout=0) ++ ++ self._add_client(test1) ++ self._add_client(test2) ++ self._run_test() ++ ++ self.assertEqual(sorted(self.service._names), ["Bar", "Foo"]) ++ + def test_name(self): + """Use a DBus read-only property.""" + self._set_service(ExampleInterface()) +-- +2.33.0 + diff --git a/python-dasbus.spec b/python-dasbus.spec index 8b6129193daba7e376f2a2054df609a7aba1af7f..e86fea521a7f0f1a666d8ffcdb8fbca43e2fd41f 100644 --- a/python-dasbus.spec +++ b/python-dasbus.spec @@ -2,13 +2,15 @@ Name: python-%{srcname} Version: 1.3 -Release: 1 +Release: 2 Summary: DBus library in Python 3 License: LGPLv2+ URL: https://pypi.python.org/pypi/dasbus Source0: https://github.com/rhinstaller/%{srcname}/archive/%{srcname}-%{version}.tar.gz +Patch0001: backport-Raise-TimeoutError-if-a-DBus-call-times-out.patch + BuildArch: noarch %global _description %{expand: @@ -42,5 +44,11 @@ Requires: python3-gobject-base %{python3_sitelib}/%{srcname}/ %changelog +* Fri Oct 21 2022 zhouyihang - 1.3-2 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:Raise TimeoutError if a DBus call times out + * Tue Jun 23 2020 fengtao - 1.3-1 - package init