From 9f580fbe6adabf3e2f66e7ef481a70d1d7365474 Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Fri, 16 Oct 2026 14:06:33 +0000 Subject: [PATCH] refactor(rpc): rename generator timeout marker to rpc_timeout_hint --- bec_widgets/utils/bec_widget.py | 6 ++-- bec_widgets/utils/rpc_decorator.py | 17 +++++++++- .../widgets/containers/dock_area/dock_area.py | 8 ++--- tests/unit_tests/test_generate_cli_client.py | 31 +++++++++++++++++++ 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/bec_widgets/utils/bec_widget.py b/bec_widgets/utils/bec_widget.py index 7a6f0f06..4b8362ff 100644 --- a/bec_widgets/utils/bec_widget.py +++ b/bec_widgets/utils/bec_widget.py @@ -24,7 +24,7 @@ import bec_widgets.widgets.containers.qt_ads as QtAds from bec_widgets.utils.bec_connector import BECConnector, ConnectionConfig from bec_widgets.utils.busy_loader import install_busy_loader from bec_widgets.utils.error_popups import SafeConnect, SafeSlot -from bec_widgets.utils.rpc_decorator import rpc_timeout +from bec_widgets.utils.rpc_decorator import rpc_timeout_hint from bec_widgets.utils.rpc_register import RPCRegister from bec_widgets.utils.widget_io import WidgetHierarchy from bec_widgets.widgets.utility.spinner.spinner import SpinnerWidget @@ -330,7 +330,7 @@ class BECWidget(BECConnector): @SafeSlot() @SafeSlot(str) - @rpc_timeout(None) + @rpc_timeout_hint(None) def screenshot(self, file_name: str | None = None): """ Take a screenshot of the dock area and save it to a file. @@ -397,7 +397,7 @@ class BECWidget(BECConnector): return ba @SafeSlot(popup_error=True) - @rpc_timeout(None) + @rpc_timeout_hint(None) def screenshot_to_scilog(self) -> None: """ Take a screenshot of the widget and send it to SciLog through BEC messaging services. diff --git a/bec_widgets/utils/rpc_decorator.py b/bec_widgets/utils/rpc_decorator.py index faa1d569..550478c9 100644 --- a/bec_widgets/utils/rpc_decorator.py +++ b/bec_widgets/utils/rpc_decorator.py @@ -1,4 +1,7 @@ -def rpc_timeout(timeout: float | None): +import warnings + + +def rpc_timeout_hint(timeout: float | None): """ Decorator to set a timeout for RPC methods. The actual implementation of timeout handling is within the cli module. This decorator @@ -10,3 +13,15 @@ def rpc_timeout(timeout: float | None): return func return decorator + + +def rpc_timeout(timeout: float | None): + """ + Deprecated alias of rpc_timeout_hint, kept so plugin widgets using the old name still work. + """ + warnings.warn( + "bec_widgets.utils.rpc_decorator.rpc_timeout is deprecated, use rpc_timeout_hint instead.", + DeprecationWarning, + stacklevel=2, + ) + return rpc_timeout_hint(timeout) diff --git a/bec_widgets/widgets/containers/dock_area/dock_area.py b/bec_widgets/widgets/containers/dock_area/dock_area.py index 8d7e5f54..504c7466 100644 --- a/bec_widgets/widgets/containers/dock_area/dock_area.py +++ b/bec_widgets/widgets/containers/dock_area/dock_area.py @@ -28,7 +28,7 @@ from bec_widgets.utils.bec_plugin_helper import ( from bec_widgets.utils.colors import apply_theme from bec_widgets.utils.name_utils import pascal_to_title from bec_widgets.utils.plugin_utils import get_rpc_widget_registry -from bec_widgets.utils.rpc_decorator import rpc_timeout +from bec_widgets.utils.rpc_decorator import rpc_timeout_hint from bec_widgets.utils.rpc_widget_handler import widget_handler from bec_widgets.utils.toolbars.actions import ( ExpandableMenuAction, @@ -766,7 +766,7 @@ class BECDockArea(DockAreaWidget): return list_profiles(namespace) @SafeSlot(str) - @rpc_timeout(None) + @rpc_timeout_hint(None) def save_profile( self, name: str | None = None, @@ -889,7 +889,7 @@ class BECDockArea(DockAreaWidget): @SafeSlot() @SafeSlot(str) @SafeSlot(str, bool) - @rpc_timeout(None) + @rpc_timeout_hint(None) def load_profile(self, name: str | None = None, restore_baseline: bool = False): """ Load a workspace profile. @@ -974,7 +974,7 @@ class BECDockArea(DockAreaWidget): @SafeSlot() @SafeSlot(str) @SafeSlot(str, bool) - @rpc_timeout(None) + @rpc_timeout_hint(None) def restore_baseline_profile(self, name: str | None = None, show_dialog: bool = False): """ Overwrite the runtime copy of *name* with the baseline. diff --git a/tests/unit_tests/test_generate_cli_client.py b/tests/unit_tests/test_generate_cli_client.py index f548e018..2c287825 100644 --- a/tests/unit_tests/test_generate_cli_client.py +++ b/tests/unit_tests/test_generate_cli_client.py @@ -8,6 +8,7 @@ import pytest from bec_widgets.utils.generate_cli import ClientGenerator, write_designer_plugins from bec_widgets.utils.generate_designer_plugin import DesignerPluginInfo from bec_widgets.utils.plugin_utils import BECClassContainer, BECClassInfo +from bec_widgets.utils.rpc_decorator import rpc_timeout, rpc_timeout_hint # pylint: disable=missing-function-docstring @@ -60,6 +61,18 @@ class MockViewWithContent: """Activate view.""" +class MockWidgetWithTimeout: + USER_ACCESS = ["slow_call", "blocking_call"] + + @rpc_timeout_hint(30) + def slow_call(self): + """Slow call.""" + + @rpc_timeout_hint(None) + def blocking_call(self): + """Blocking call.""" + + class MockDesignerWidgetBase: ICON_NAME = "mock_icon" @@ -309,3 +322,21 @@ def test_write_designer_plugins(tmp_path): assert '"MockDesignerWidget"' in content assert '"MockDesignerWidget": "mock_icon"' in content assert "MockDesignerWidgetPlugin" not in content + + +def test_generate_content_for_class_emits_rpc_timeout_hint(): + generator = ClientGenerator() + generator.generate_content_for_class(MockWidgetWithTimeout) + + assert "@rpc_timeout(30)\n @rpc_call\n def slow_call(self):" in generator.content + assert "@rpc_timeout(None)\n @rpc_call\n def blocking_call(self):" in generator.content + + +def test_deprecated_rpc_timeout_alias_still_sets_hint(): + with pytest.warns(DeprecationWarning, match="rpc_timeout_hint"): + + @rpc_timeout(5) + def legacy_call(): + """Legacy call.""" + + assert legacy_call.__rpc_timeout__ == 5