feat(generate_cli): RPC API from content widget can be merged with the RPC API of the container widget statically

This commit is contained in:
2026-03-05 18:12:33 +01:00
parent 010373fd5b
commit 758956be09
9 changed files with 425 additions and 12 deletions
@@ -34,6 +34,31 @@ class MockBECFigure:
"""Remove a plot from the figure."""
class MockContentWidget:
USER_ACCESS = ["list_profiles", "mode", "mode.setter"]
def list_profiles(self) -> list[str]:
"""List profiles."""
return []
@property
def mode(self) -> str:
"""Current mode."""
return "creator"
@mode.setter
def mode(self, value: str) -> None:
_ = value
class MockViewWithContent:
USER_ACCESS = ["activate"]
RPC_CONTENT_CLASS = MockContentWidget
def activate(self):
"""Activate view."""
def test_client_generator_with_black_formatting():
generator = ClientGenerator(base=True)
container = BECClassContainer()
@@ -228,6 +253,16 @@ def test_generate_content_for_class():
assert "Test method" in generator.content
def test_generate_content_for_class_uses_rpc_content_class_user_access():
generator = ClientGenerator()
generator.generate_content_for_class(MockViewWithContent)
assert "def activate(self):" in generator.content
assert "def list_profiles(self) -> list[str]:" in generator.content
assert "def mode(self) -> str:" in generator.content
assert "@mode.setter" in generator.content
def test_write_is_black_formatted(tmp_path):
"""
Test the write method of the ClientGenerator class.
+23 -1
View File
@@ -4,6 +4,7 @@ from qtpy.QtWidgets import QWidget
from bec_widgets.applications.main_app import BECMainApp
from bec_widgets.applications.views.view import ViewBase
from bec_widgets.utils.bec_widget import BECWidget
from .client_mocks import mocked_client
@@ -133,7 +134,28 @@ def test_view_switch_method_switches_to_target(app_with_spies, qtbot):
def test_view_content_widget_is_hidden_from_namespace(app_with_spies):
app, _, _, _ = app_with_spies
assert app.dock_area.content is app.dock_area.dock_area
assert app.dock_area.content.skip_rpc_namespace is True
def test_developer_plotting_area_parent_id_uses_view_namespace(app_with_spies):
app, _, _, _ = app_with_spies
plotting_area = app.developer_view.developer_widget.plotting_ads
assert plotting_area.parent_id == app.developer_view.gui_id
def test_parent_id_ignores_plain_qwidget_between_connectors(qtbot, mocked_client):
class RootConnector(BECWidget, QWidget):
RPC = True
class ChildConnector(BECWidget, QWidget):
RPC = True
root = RootConnector(client=mocked_client)
qtbot.addWidget(root)
spacer = QWidget(root)
child = ChildConnector(parent=spacer, client=mocked_client)
assert child.parent_id == root.gui_id
def test_guided_tour_is_initialized(app_with_spies):
+8
View File
@@ -109,6 +109,14 @@ def test_show_launcher_creates_launcher_when_missing(bec_main_window):
assert bec_main_window._launcher_window is launcher
def test_hidden_scan_progress_parent_blocks_children_namespace(bec_main_window):
hidden_progress = bec_main_window._scan_progress_bar_full
nested_progress = hidden_progress.progressbar
assert hidden_progress.rpc_exposed is False
assert nested_progress.parent_id == hidden_progress.gui_id
#################################################################
# Tests for BECMainWindow Addons
#################################################################
+33
View File
@@ -138,3 +138,36 @@ def test_serialize_result_and_send_max_delay_exceeded(rpc_server, qtbot, dummy_w
assert args[1] is False # accepted=False
assert "error" in args[2]
assert "Max delay exceeded" in args[2]["error"]
def test_run_rpc_delegates_to_rpc_content_class(rpc_server):
class Content:
USER_ACCESS = ["foo", "mode", "mode.setter"]
def __init__(self):
self._mode = "initial"
def foo(self):
return "ok"
@property
def mode(self):
return self._mode
@mode.setter
def mode(self, value):
self._mode = value
class View:
RPC_CONTENT_CLASS = Content
RPC_CONTENT_ATTR = "content"
def __init__(self):
self.content = Content()
view = View()
assert rpc_server.run_rpc(view, "foo", [], {}) == "ok"
assert rpc_server.run_rpc(view, "mode", [], {}) == "initial"
assert rpc_server.run_rpc(view, "mode", ["creator"], {}) is None
assert view.content.mode == "creator"