From 2a8b5ac351eff4c3611c6aaad2a430e6a874f5e0 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Mon, 27 Jan 2025 15:29:32 +0100 Subject: [PATCH] tests/templates: Rework ImplRequest The portal backend mocks would all implement the same pattern by copy and pasting a bunch of code which is not that easy to understand and also subtly broken because they would often not unexport the request object. This changes the ImplRequest to own the control flow and do all the right things in a single place and provides callbacks for more advanced use cases. --- tests/templates/__init__.py | 144 +++++++++++++++++++---------- tests/templates/access.py | 45 ++++----- tests/templates/account.py | 40 +++----- tests/templates/appchooser.py | 40 +++----- tests/templates/dynamiclauncher.py | 56 +++++------ tests/templates/email.py | 42 +++------ tests/templates/filechooser.py | 83 ++++++----------- tests/templates/globalshortcuts.py | 93 ++++++++----------- tests/templates/inhibit.py | 88 ++++++++---------- tests/templates/print.py | 87 +++++++---------- tests/templates/remotedesktop.py | 137 +++++++++++---------------- tests/templates/screenshot.py | 77 ++++++--------- tests/templates/usb.py | 38 ++++---- tests/templates/wallpaper.py | 48 +++++----- 14 files changed, 447 insertions(+), 571 deletions(-) diff --git a/tests/templates/__init__.py b/tests/templates/__init__.py index 6d5e8cf84..09c56f5ad 100644 --- a/tests/templates/__init__.py +++ b/tests/templates/__init__.py @@ -3,6 +3,7 @@ # This file is formatted with Python Black from typing import Callable, Dict, Optional, NamedTuple +from gi.repository import GLib import dbus import dbusmock import logging @@ -35,62 +36,113 @@ class Response(NamedTuple): class ImplRequest: """ - Implementation of a org.freedesktop.impl.portal.Request object. Typically - this object needs to be merely exported: + Implementation of an ``org.freedesktop.impl.portal.Request`` object exposed + on the object path ``handle``. - >>> r = ImplRequest(mock, "org.freedesktop.impl.portal.Test", handle) - >>> r.export() - - Where the test or the backend implementation relies on the Closed() method - of the ImplRequest, provide a callback to be invoked. - - >>> r.export(close_callback=my_callback) - - Note that the latter only works if the test invokes methods - asynchronously. - - .. attribute:: closed - - Set to True if the Close() method on the Request was invoked + The dbus method implementations need to be invoked asynchronously and the + async callbacks must be passed in ``cb_success`` and ``cb_error``. + The request either waits until it is closed by x-d-p (``wait_for_close``) or + responds to the request (``respond``). """ - def __init__(self, mock: "dbusmock.DBusMockObject", busname: str, handle: str): + def __init__( + self, + mock: dbusmock.DBusMockObject, + busname: str, + handle: str, + logger: logging.Logger, + cb_success: Callable, + cb_error: Callable, + ): self.mock = mock - self.handle = handle - self.closed = False - self._close_callback: Optional[Callable] = None - bus = mock.connection proxy = bus.get_object(busname, handle) - mock_interface = dbus.Interface(proxy, dbusmock.MOCK_IFACE) + self.mock_interface = dbus.Interface(proxy, dbusmock.MOCK_IFACE) + self.handle = handle + self.logger = logger + self.cb_success = cb_success + self.cb_error = cb_error + + def respond( + self, + response: Callable | Response, + delay: int = 0, + done_cb: Callable | None = None, + ) -> None: + def reply(): + nonlocal response + logger.debug(f"Request {self.handle}: trying to reply") + if callable(response): + try: + response = response() + except Exception as e: + logger.critical( + f"Request {self.handle}: failed getting response: {e}" + ) + self.cb_error(e) + self._unexport() + return + + assert response + logger.debug(f"Request {self.handle}: replying {response}") + + self.cb_success(response.response, response.results) + self._unexport() + + if done_cb: + done_cb() + + self._export() + + if delay > 0: + logger.debug(f"Request {self.handle}: scheduling delay of {delay}ms") + GLib.timeout_add(delay, reply) + else: + reply() + + def wait_for_close( + self, + close_callback: Callable | None = None, + ) -> None: + def closed(): + logger.debug(f"Request {self.handle}: closed") + + self.mock.EmitSignal( + "org.freedesktop.impl.portal.Mock", + "RequestClosed", + "s", + (self.handle,), + ) + + if close_callback: + try: + close_callback() + except Exception as e: + logger.critical( + f"Request {self.handle}: failed running close callback: {e}" + ) + self.cb_error(e) + self._unexport() + return + + response = Response(2, {}) + self.cb_success(response.response, response.results) + self._unexport() - # Register for the Close() call on the impl.Request. If it gets - # called, use the side-channel RequestClosed signal so we can notify - # the test that the impl.Request was actually closed by the - # xdg-desktop-portal def cb_methodcall(name, args): if name == "Close": - self.closed = True - logger.debug(f"Close() on {self}") - if self._close_callback: - self._close_callback() - self.mock.EmitSignal( - "org.freedesktop.impl.portal.Mock", - "RequestClosed", - "s", - (self.handle,), - ) - self.mock.RemoveObject(self.handle) + closed() - mock_interface.connect_to_signal("MethodCalled", cb_methodcall) + self._export() - def export(self, close_callback: Optional[Callable] = None): - """ - Create the object on the bus. If close_callback is not None, that - callback will be invoked in response to the Close() method called on - this object. - """ + logger.debug(f"Request {self.handle}: waiting for x-d-p to call close") + self.mock_interface.connect_to_signal("MethodCalled", cb_methodcall) + + def _export(self): + # In the future we can pass a class extending + # dbusmock.mockobject.DBusMockObject as mock_class to avoid going + # through the mock MethodCalled signal self.mock.AddObject( path=self.handle, interface="org.freedesktop.impl.portal.Request", @@ -104,10 +156,8 @@ def export(self, close_callback: Optional[Callable] = None): ) ], ) - self._close_callback = close_callback - return self - def unexport(self): + def _unexport(self): self.mock.RemoveObject(self.handle) def __str__(self): diff --git a/tests/templates/access.py b/tests/templates/access.py index c071762ed..7e6cd952e 100644 --- a/tests/templates/access.py +++ b/tests/templates/access.py @@ -5,7 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service -from gi.repository import GLib BUS_NAME = "org.freedesktop.impl.portal.Test" @@ -43,30 +42,20 @@ def AccessDialog( cb_success, cb_error, ): - try: - logger.debug( - f"AccessDialog({handle}, {app_id}, {parent_window}, {title}, {subtitle}, {body}, {options})" - ) - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"AccessDialog Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(request): - response = Response(self.response, {}) - logger.debug(f"AccessDialog with response {response}") - request.unexport() - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback, request) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug( + f"AccessDialog({handle}, {app_id}, {parent_window}, {title}, {subtitle}, {body}, {options})" + ) + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, {}), delay=self.delay) diff --git a/tests/templates/account.py b/tests/templates/account.py index ad90b134a..d4f87e899 100644 --- a/tests/templates/account.py +++ b/tests/templates/account.py @@ -5,7 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service import dbus -from gi.repository import GLib BUS_NAME = "org.freedesktop.impl.portal.Test" MAIN_OBJ = "/org/freedesktop/portal/desktop" @@ -31,27 +30,18 @@ def load(mock, parameters={}): async_callbacks=("cb_success", "cb_error"), ) def GetUserInformation(self, handle, app_id, window, options, cb_success, cb_error): - try: - logger.debug(f"GetUserInformation({handle}, {app_id}, {window}, {options})") - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"GetUserInformation Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, self.results) - logger.debug(f"GetUserInformation with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug(f"GetUserInformation({handle}, {app_id}, {window}, {options})") + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, self.results), delay=self.delay) diff --git a/tests/templates/appchooser.py b/tests/templates/appchooser.py index 20901988d..3ea88b1a8 100644 --- a/tests/templates/appchooser.py +++ b/tests/templates/appchooser.py @@ -5,7 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service -from gi.repository import GLib BUS_NAME = "org.freedesktop.impl.portal.Test" @@ -43,32 +42,23 @@ def load(mock, parameters={}): def ChooseApplication( self, handle, app_id, parent_window, choices, options, cb_success, cb_error ): - try: - logger.debug( - f"ChooseApplication({handle}, {app_id}, {parent_window}, {options})" - ) - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"ChooseApplication Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, {}) - logger.debug(f"ChooseApplication with response {response}") - cb_success(response.response, response.results) + logger.debug( + f"ChooseApplication({handle}, {app_id}, {parent_window}, {choices}, {options})" + ) - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, {}), delay=self.delay) @dbus.service.method( diff --git a/tests/templates/dynamiclauncher.py b/tests/templates/dynamiclauncher.py index 9c206df0a..e60c0f227 100644 --- a/tests/templates/dynamiclauncher.py +++ b/tests/templates/dynamiclauncher.py @@ -5,8 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service -from gi.repository import GLib - BUS_NAME = "org.freedesktop.impl.portal.Test" MAIN_OBJ = "/org/freedesktop/portal/desktop" @@ -44,38 +42,28 @@ def load(mock, parameters={}): def PrepareInstall( self, handle, app_id, parent_window, name, icon_v, options, cb_success, cb_error ): - try: - logger.debug( - f"PrepareInstall({handle}, {app_id}, {parent_window}, {name}, {icon_v}, {options})" - ) - - response = Response( - self.response, - { - "name": self.launcher_name if self.launcher_name else name, - "icon": dbus.Struct(list(icon_v), signature="sv", variant_level=2), - }, - ) - - request = ImplRequest(self, BUS_NAME, handle) - - if self.expect_close: - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"PrepareInstall Close() response {response}") - cb_success(response.response, response.results) + logger.debug( + f"PrepareInstall({handle}, {app_id}, {parent_window}, {name}, {icon_v}, {options})" + ) - request.export(closed_callback) - else: - request.export() + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - def reply(): - logger.debug(f"PrepareInstall with response {response}") - cb_success(response.response, response.results) + response = Response( + self.response, + { + "name": self.launcher_name if self.launcher_name else name, + "icon": dbus.Struct(list(icon_v), signature="sv", variant_level=2), + }, + ) - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond(response, delay=self.delay) diff --git a/tests/templates/email.py b/tests/templates/email.py index ea28166ce..9c600c55d 100644 --- a/tests/templates/email.py +++ b/tests/templates/email.py @@ -5,8 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service -from gi.repository import GLib - BUS_NAME = "org.freedesktop.impl.portal.Test" MAIN_OBJ = "/org/freedesktop/portal/desktop" @@ -41,30 +39,18 @@ def load(mock, parameters={}): async_callbacks=("cb_success", "cb_error"), ) def ComposeEmail(self, handle, app_id, parent_window, options, cb_success, cb_error): - try: - logger.debug(f"ComposeEmail({handle}, {app_id}, {parent_window}, {options})") - - response = Response(self.response, {}) - - request = ImplRequest(self, BUS_NAME, handle) - - if self.expect_close: - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"ComposeEmail Close() response {response}") - cb_success(response.response, response.results) - - request.export(closed_callback) - else: - request.export() - - def reply(): - logger.debug(f"ComposeEmail with response {response}") - cb_success(response.response, response.results) + logger.debug(f"ComposeEmail({handle}, {app_id}, {parent_window}, {options})") + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, {}), delay=self.delay) diff --git a/tests/templates/filechooser.py b/tests/templates/filechooser.py index 8af2efaea..c1d4135f2 100644 --- a/tests/templates/filechooser.py +++ b/tests/templates/filechooser.py @@ -5,7 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service -from gi.repository import GLib BUS_NAME = "org.freedesktop.impl.portal.Test" @@ -42,32 +41,21 @@ def load(mock, parameters={}): async_callbacks=("cb_success", "cb_error"), ) def OpenFile(self, handle, app_id, parent_window, title, options, cb_success, cb_error): - try: - logger.debug( - f"OpenFile({handle}, {app_id}, {parent_window}, {title}, {options})" - ) - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"OpenFile Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, self.results) - logger.debug(f"OpenFile with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug(f"OpenFile({handle}, {app_id}, {parent_window}, {title}, {options})") + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, self.results), delay=self.delay) @dbus.service.method( @@ -77,29 +65,18 @@ def reply_callback(): async_callbacks=("cb_success", "cb_error"), ) def SaveFile(self, handle, app_id, parent_window, title, options, cb_success, cb_error): - try: - logger.debug( - f"SaveFile({handle}, {app_id}, {parent_window}, {title}, {options})" - ) - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"SaveFile Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, self.results) - logger.debug(f"SaveFile with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug(f"SaveFile({handle}, {app_id}, {parent_window}, {title}, {options})") + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, self.results), delay=self.delay) diff --git a/tests/templates/globalshortcuts.py b/tests/templates/globalshortcuts.py index c6aa7ba33..1be4e40b1 100644 --- a/tests/templates/globalshortcuts.py +++ b/tests/templates/globalshortcuts.py @@ -46,44 +46,29 @@ def load(mock, parameters={}): async_callbacks=("cb_success", "cb_error"), ) def CreateSession(self, handle, session_handle, app_id, options, cb_success, cb_error): - try: - logger.debug(f"CreateSession({handle}, {session_handle}, {app_id}, {options})") - - session = ImplSession(self, BUS_NAME, session_handle, app_id).export() - self.sessions[session_handle] = session - - response = Response(self.response, {"session_handle": session.handle}) - - request = ImplRequest(self, BUS_NAME, handle) - - if self.expect_close: - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"CreateSession Close() response {response}") - cb_success(response.response, response.results) - - request.export(closed_callback) - else: - request.export() - - def reply(): - logger.debug(f"CreateSession with response {response}") - cb_success(response.response, response.results) - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) - - if self.force_close > 0: - - def force_close(): - session.close() - - GLib.timeout_add(self.force_close, force_close) + logger.debug(f"CreateSession({handle}, {session_handle}, {app_id}, {options})") + + session = ImplSession(self, BUS_NAME, session_handle, app_id).export() + self.sessions[session_handle] = session + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond( + Response(self.response, {"session_handle": session.handle}), + delay=self.delay, + ) + if self.force_close > 0: + GLib.timeout_add(self.force_close, session.close) @dbus.service.method( @@ -102,27 +87,29 @@ def BindShortcuts( cb_success, cb_error, ): - try: - logger.debug( - f"BindShortcuts({handle}, {session_handle}, {shortcuts}, {options})" - ) + logger.debug(f"BindShortcuts({handle}, {session_handle}, {shortcuts}, {options})") - assert session_handle in self.sessions - response = Response(self.response, {}) - request = ImplRequest(self, BUS_NAME, handle) - request.export() + assert session_handle in self.sessions + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: def reply(): - logger.debug(f"BindShortcuts with response {response}") + logger.debug(f"BindShortcuts with shortcuts {shortcuts}") self.sessions[session_handle].shortcuts = shortcuts - cb_success(response.response, response.results) - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) + return Response(self.response, {}) - except Exception as e: - logger.critical(e) - cb_error(e) + request.respond(reply, delay=self.delay) @dbus.service.method( diff --git a/tests/templates/inhibit.py b/tests/templates/inhibit.py index 8f091d930..192298529 100644 --- a/tests/templates/inhibit.py +++ b/tests/templates/inhibit.py @@ -51,30 +51,21 @@ def load(mock, parameters={}): async_callbacks=("cb_success", "cb_error"), ) def Inhibit(self, handle, app_id, window, flags, options, cb_success, cb_error): - try: - logger.debug(f"Inhibit({handle}, {app_id}, {window}, {flags}, {options})") - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"Inhibit Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, {}) - logger.debug(f"Inhibit with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug(f"Inhibit({handle}, {app_id}, {window}, {flags}, {options})") + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, {}), delay=self.delay) @dbus.service.method( @@ -113,35 +104,34 @@ def close_session(): async_callbacks=("cb_success", "cb_error"), ) def CreateMonitor(self, handle, session_handle, app_id, window, cb_success, cb_error): - try: - logger.debug(f"CreateMonitor({handle}, {session_handle}, {app_id}, {window})") - - session = ImplSession(self, BUS_NAME, session_handle, app_id).export() - self.sessions[session_handle] = session + logger.debug(f"CreateMonitor({handle}, {session_handle}, {app_id}, {window})") + + session = ImplSession(self, BUS_NAME, session_handle, app_id).export() + self.sessions[session_handle] = session + + # This is irregular: the backend doesn't return the results vardict + def internal_cb_success(response, results): + cb_success(response) + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + internal_cb_success, + cb_error, + ) - def closed_callback(): - response = Response(2, {}) - logger.debug(f"CreateMonitor Close() response {response}") - cb_success(response.response) + if self.expect_close: + request.wait_for_close() + else: - def reply_callback(): - response = Response(self.response, {}) - logger.debug(f"CreateMonitor with response {response}") - cb_success(response.response) + def arm_timer(): self.ArmTimer(session_handle) - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - - except Exception as e: - logger.critical(e) - cb_error(e) + request.respond( + Response(self.response, {}), delay=self.delay, done_cb=arm_timer + ) @dbus.service.method( diff --git a/tests/templates/print.py b/tests/templates/print.py index ef7110574..00235af7c 100644 --- a/tests/templates/print.py +++ b/tests/templates/print.py @@ -5,7 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service -from gi.repository import GLib BUS_NAME = "org.freedesktop.impl.portal.Test" @@ -54,32 +53,23 @@ def PreparePrint( cb_success, cb_error, ): - try: - logger.debug( - f"PreparePrint({handle}, {app_id}, {parent_window}, {title}, {settings}, {page_setup}, {options})" - ) - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"PreparePrint Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, self.prepare_results) - logger.debug(f"PreparePrint with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug( + f"PreparePrint({handle}, {app_id}, {parent_window}, {title}, {settings}, {page_setup}, {options})" + ) + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, self.prepare_results), delay=self.delay) @dbus.service.method( @@ -91,29 +81,20 @@ def reply_callback(): def Print( self, handle, app_id, parent_window, title, fd, options, cb_success, cb_error ): - try: - logger.debug( - f"Print({handle}, {app_id}, {parent_window}, {title}, {fd}, {options})" - ) - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"Print Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, self.results) - logger.debug(f"Print with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug( + f"Print({handle}, {app_id}, {parent_window}, {title}, {fd}, {options})" + ) + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, self.results), delay=self.delay) diff --git a/tests/templates/remotedesktop.py b/tests/templates/remotedesktop.py index 0bf30a5b6..6a60449ba 100644 --- a/tests/templates/remotedesktop.py +++ b/tests/templates/remotedesktop.py @@ -50,44 +50,29 @@ def load(mock, parameters={}): async_callbacks=("cb_success", "cb_error"), ) def CreateSession(self, handle, session_handle, app_id, options, cb_success, cb_error): - try: - logger.debug(f"CreateSession({handle}, {session_handle}, {app_id}, {options})") - - session = ImplSession(self, BUS_NAME, session_handle, app_id).export() - self.sessions[session_handle] = session - - response = Response(self.response, {"session_handle": session.handle}) - - request = ImplRequest(self, BUS_NAME, handle) - - if self.expect_close: - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"CreateSession Close() response {response}") - cb_success(response.response, response.results) - - request.export(closed_callback) - else: - request.export() - - def reply(): - logger.debug(f"CreateSession with response {response}") - cb_success(response.response, response.results) - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) - - if self.force_close > 0: - - def force_close(): - session.close() - - GLib.timeout_add(self.force_close, force_close) + logger.debug(f"CreateSession({handle}, {session_handle}, {app_id}, {options})") + + session = ImplSession(self, BUS_NAME, session_handle, app_id).export() + self.sessions[session_handle] = session + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond( + Response(self.response, {"session_handle": session.handle}), + delay=self.delay, + ) + if self.force_close > 0: + GLib.timeout_add(self.force_close, session.close) @dbus.service.method( @@ -97,24 +82,23 @@ def force_close(): async_callbacks=("cb_success", "cb_error"), ) def SelectDevices(self, handle, session_handle, app_id, options, cb_success, cb_error): - try: - logger.debug(f"SelectDevices({handle}, {session_handle}, {app_id}, {options})") - - assert session_handle in self.sessions - response = Response(self.response, {}) - request = ImplRequest(self, BUS_NAME, handle) - request.export() + logger.debug(f"SelectDevices({handle}, {session_handle}, {app_id}, {options})") - def reply(): - logger.debug(f"SelectDevices with response {response}") - cb_success(response.response, response.results) + assert session_handle in self.sessions - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, {}), delay=self.delay) @dbus.service.method( @@ -126,40 +110,29 @@ def reply(): def Start( self, handle, session_handle, app_id, parent_window, options, cb_success, cb_error ): - try: - logger.debug( - f"Start({handle}, {session_handle}, {parent_window}, {app_id}, {options})" - ) - - assert session_handle in self.sessions - response = Response(self.response, {}) - - if self.force_clipoboard_enabled: - response.results["clipboard_enabled"] = True - - request = ImplRequest(self, BUS_NAME, handle) - - if self.expect_close: - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"Start Close() response {response}") - cb_success(response.response, response.results) + logger.debug( + f"Start({handle}, {session_handle}, {parent_window}, {app_id}, {options})" + ) - request.export(closed_callback) - else: - request.export() + assert session_handle in self.sessions - def reply(): - logger.debug(f"Start with response {response}") - cb_success(response.response, response.results) + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) + response = Response(self.response, {}) + if self.force_clipoboard_enabled: + response.results["clipboard_enabled"] = True - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond(response, delay=self.delay) @dbus.service.method( diff --git a/tests/templates/screenshot.py b/tests/templates/screenshot.py index fcd451012..2921a3564 100644 --- a/tests/templates/screenshot.py +++ b/tests/templates/screenshot.py @@ -5,7 +5,6 @@ from tests.templates import Response, init_logger, ImplRequest import dbus.service -from gi.repository import GLib BUS_NAME = "org.freedesktop.impl.portal.Test" @@ -42,30 +41,21 @@ def load(mock, parameters={}): async_callbacks=("cb_success", "cb_error"), ) def Screenshot(self, handle, app_id, parent_window, options, cb_success, cb_error): - try: - logger.debug(f"Screenshot({handle}, {app_id}, {parent_window}, {options})") - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"Screenshot Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, self.results) - logger.debug(f"Screenshot with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() + logger.debug(f"Screenshot({handle}, {app_id}, {parent_window}, {options})") + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, self.results), delay=self.delay) @dbus.service.method( @@ -75,27 +65,18 @@ def reply_callback(): async_callbacks=("cb_success", "cb_error"), ) def PickColor(self, handle, app_id, parent_window, options, cb_success, cb_error): - try: - logger.debug(f"PickColor({handle}, {app_id}, {parent_window}, {options})") - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"PickColor Close() response {response}") - cb_success(response.response, response.results) - - def reply_callback(): - response = Response(self.response, self.results) - logger.debug(f"PickColor with response {response}") - cb_success(response.response, response.results) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug(f"PickColor({handle}, {app_id}, {parent_window}, {options})") + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, self.results), delay=self.delay) diff --git a/tests/templates/usb.py b/tests/templates/usb.py index 228d23b7b..d3868dc93 100644 --- a/tests/templates/usb.py +++ b/tests/templates/usb.py @@ -7,8 +7,6 @@ import dbus.service from dbusmock import MOCK_IFACE -from gi.repository import GLib - BUS_NAME = "org.freedesktop.impl.portal.Test" MAIN_OBJ = "/org/freedesktop/portal/desktop" @@ -25,6 +23,7 @@ def load(mock, parameters={}): mock.delay: int = parameters.get("delay", 200) mock.response: int = parameters.get("response", 0) + mock.expect_close: bool = parameters.get("expect-close", False) mock.filters = parameters.get("filters", {}) mock.AddProperties( MAIN_IFACE, @@ -52,11 +51,20 @@ def AcquireDevices( cb_success, cb_error, ): - try: - logger.debug( - f"AcquireDevices({handle}, {parent_window}, {app_id}, {devices}, {options})" - ) + logger.debug( + f"AcquireDevices({handle}, {parent_window}, {app_id}, {devices}, {options})" + ) + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + cb_success, + cb_error, + ) + + def reply(): # no options supported assert not options devices_out = [] @@ -99,23 +107,15 @@ def AcquireDevices( dbus.Struct([id, access_options], signature="sa{sv}", variant_level=1) ) - response = Response( + return Response( self.response, {"devices": dbus.Array(devices_out, signature="(sa{sv})", variant_level=1)}, ) - request = ImplRequest(self, BUS_NAME, handle) - request.export() - - def reply(): - logger.debug(f"AcquireDevices with response {response}") - cb_success(response.response, response.results) - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply) - except Exception as e: - logger.critical(e) - cb_error(e) + if self.expect_close: + request.wait_for_close() + else: + request.respond(reply, delay=self.delay) @dbus.service.method( diff --git a/tests/templates/wallpaper.py b/tests/templates/wallpaper.py index 2b69598d8..0c614b4da 100644 --- a/tests/templates/wallpaper.py +++ b/tests/templates/wallpaper.py @@ -6,7 +6,6 @@ import dbus import dbus.service -from gi.repository import GLib BUS_NAME = "org.freedesktop.impl.portal.Test" MAIN_OBJ = "/org/freedesktop/portal/desktop" @@ -34,29 +33,24 @@ def load(mock, parameters={}): def SetWallpaperURI( self, handle, app_id, parent_window, uri, options, cb_success, cb_error ): - try: - logger.debug( - f"SetWallpaperURI({handle}, {app_id}, {parent_window}, {uri}, {options})" - ) - - def closed_callback(): - response = Response(2, {}) - logger.debug(f"SetWallpaperURI Close() response {response}") - cb_success(response.response) - - def reply_callback(): - response = Response(self.response, {}) - logger.debug(f"SetWallpaperURI with response {response}") - cb_success(response.response) - - request = ImplRequest(self, BUS_NAME, handle) - if self.expect_close: - request.export(closed_callback) - else: - request.export() - - logger.debug(f"scheduling delay of {self.delay}") - GLib.timeout_add(self.delay, reply_callback) - except Exception as e: - logger.critical(e) - cb_error(e) + logger.debug( + f"SetWallpaperURI({handle}, {app_id}, {parent_window}, {uri}, {options})" + ) + + # This is irregular: the backend doesn't return the results vardict + def internal_cb_success(response, results): + cb_success(response) + + request = ImplRequest( + self, + BUS_NAME, + handle, + logger, + internal_cb_success, + cb_error, + ) + + if self.expect_close: + request.wait_for_close() + else: + request.respond(Response(self.response, {}), delay=self.delay)