0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-13 19:21:50 +02:00

feat(bec_connector): export config to yaml

This commit is contained in:
2024-06-30 18:18:36 +02:00
parent b6e1e20b7c
commit a391f3018c
6 changed files with 98 additions and 21 deletions

View File

@ -622,12 +622,6 @@ class BECFigure(RPCBase):
list[BECPlotBase]: List of all widgets in the figure.
"""
@rpc_call
def apply_config(self, config: "dict | FigureConfig"):
"""
None
"""
class BECImageItem(RPCBase):
@property

View File

@ -47,9 +47,6 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
"d0": self.d0,
"d1": self.d1,
"d2": self.d2,
"fig0": self.fig0,
"fig1": self.fig1,
"fig2": self.fig2,
"plt": self.plt,
"bar": self.bar,
}
@ -108,6 +105,8 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
# curves for w1
self.c1 = self.w1.get_config()
self.fig_c = self.figure.config_dict
def _init_dock(self):
self.d0 = self.dock.add_dock(name="dock_0")

View File

@ -1,15 +1,19 @@
# pylint: disable = no-name-in-module,missing-module-docstring
from __future__ import annotations
import os
import time
import uuid
from typing import Optional
import yaml
from bec_lib.utils.import_utils import lazy_import_from
from pydantic import BaseModel, Field, field_validator
from qtpy.QtCore import QObject, QRunnable, QThreadPool, Signal
from qtpy.QtCore import Slot as pyqtSlot
from bec_widgets.cli.rpc_register import RPCRegister
from bec_widgets.utils.yaml_dialog import load_yaml, load_yaml_gui, save_yaml, save_yaml_gui
BECDispatcher = lazy_import_from("bec_widgets.utils.bec_dispatcher", ("BECDispatcher",))
@ -161,6 +165,60 @@ class BECConnector:
"""
self.config = config
def apply_config(self, config: dict, generate_new_id: bool = True) -> None:
"""
Apply the configuration to the widget.
Args:
config(dict): Configuration settings.
generate_new_id(bool): If True, generate a new GUI ID for the widget.
"""
self.config = ConnectionConfig(**config)
if generate_new_id is True:
gui_id = str(uuid.uuid4())
self.rpc_register.remove_rpc(self)
self.set_gui_id(gui_id)
self.rpc_register.add_rpc(self)
else:
self.gui_id = self.config.gui_id
def load_config(self, path: str | None = None, gui: bool = False):
"""
Load the configuration of the widget from YAML.
Args:
path(str): Path to the configuration file for non-GUI dialog mode.
gui(bool): If True, use the GUI dialog to load the configuration file.
"""
if gui is True:
config = load_yaml_gui(self)
else:
config = load_yaml(path)
if config is not None:
if config.get("widget_class") != self.__class__.__name__:
raise ValueError(
f"Configuration file is not for {self.__class__.__name__}. Got configuration for {config.get('widget_class')}."
)
self.apply_config(config)
def save_config(self, path: str | None = None, gui: bool = False):
"""
Save the configuration of the widget to YAML.
Args:
path(str): Path to save the configuration file for non-GUI dialog mode.
gui(bool): If True, use the GUI dialog to save the configuration file.
"""
if gui is True:
save_yaml_gui(self, self.config_dict)
else:
if path is None:
path = os.getcwd()
file_path = os.path.join(path, f"{self.__class__.__name__}_config.yaml")
save_yaml(file_path, self.config_dict)
@pyqtSlot(str)
def set_gui_id(self, gui_id: str) -> None:
"""

View File

@ -6,7 +6,7 @@ import yaml
from qtpy.QtWidgets import QFileDialog
def load_yaml(instance) -> Union[dict, None]:
def load_yaml_gui(instance) -> Union[dict, None]:
"""
Load YAML file from disk.
@ -20,12 +20,25 @@ def load_yaml(instance) -> Union[dict, None]:
file_path, _ = QFileDialog.getOpenFileName(
instance, "Load Settings", "", "YAML Files (*.yaml *.yml);;All Files (*)", options=options
)
config = load_yaml(file_path)
return config
def load_yaml(file_path: str) -> Union[dict, None]:
"""
Load YAML file from disk.
Args:
file_path(str): Path to the YAML file.
Returns:
dict: Configuration data loaded from the YAML file.
"""
if not file_path:
return None
try:
with open(file_path, "r") as file:
config = yaml.safe_load(file)
config = yaml.load(file, Loader=yaml.FullLoader)
return config
except FileNotFoundError:
@ -38,7 +51,7 @@ def load_yaml(instance) -> Union[dict, None]:
print(f"An error occurred while loading the settings from {file_path}: {e}")
def save_yaml(instance, config: dict) -> None:
def save_yaml_gui(instance, config: dict) -> None:
"""
Save YAML file to disk.
@ -51,6 +64,17 @@ def save_yaml(instance, config: dict) -> None:
instance, "Save Settings", "", "YAML Files (*.yaml *.yml);;All Files (*)", options=options
)
save_yaml(file_path, config)
def save_yaml(file_path: str, config: dict) -> None:
"""
Save YAML file to disk.
Args:
file_path(str): Path to the YAML file.
config(dict): Configuration data to be saved.
"""
if not file_path:
return
try:

View File

@ -123,7 +123,9 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
"clear_all",
"get_all_rpc",
"widget_list",
"apply_config",
# "apply_config",
# "save_config",
# "load_config",
]
subplot_map = {
"PlotBase": BECPlotBase,
@ -173,7 +175,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
"Key must be a string (widget id) or a tuple of two integers (grid coordinates)"
)
def apply_config(self, config: dict | FigureConfig):
def apply_config(self, config: dict | FigureConfig): # ,generate_new_id: bool = False):
if isinstance(config, dict):
try:
config = FigureConfig(**config)

View File

@ -7,7 +7,7 @@ import pytest
import yaml
from qtpy.QtWidgets import QPushButton, QVBoxLayout, QWidget
from bec_widgets.utils.yaml_dialog import load_yaml, save_yaml
from bec_widgets.utils.yaml_dialog import load_yaml_gui, save_yaml_gui
@pytest.fixture(scope="function")
@ -33,7 +33,7 @@ def test_load_yaml(qtbot, example_widget):
temp_file.write(b"name: test\nvalue: 42")
def load_yaml_wrapper():
config = load_yaml(example_widget)
config = load_yaml_gui(example_widget)
if config:
example_widget.config.update(config)
@ -49,7 +49,7 @@ def test_load_yaml(qtbot, example_widget):
def test_load_yaml_file_not_found(qtbot, example_widget, capsys):
def load_yaml_wrapper():
config = load_yaml(example_widget)
config = load_yaml_gui(example_widget)
if config:
example_widget.config.update(config)
@ -76,7 +76,7 @@ def test_load_yaml_general_exception(qtbot, example_widget, capsys, monkeypatch)
monkeypatch.setattr("builtins.open", mock_open)
def load_yaml_wrapper():
config = load_yaml(example_widget)
config = load_yaml_gui(example_widget)
if config:
example_widget.config.update(config)
@ -96,7 +96,7 @@ def test_load_yaml_permission_error(qtbot, example_widget, monkeypatch, capsys):
os.chmod(temp_file_path, 0o000) # Remove permissions
def load_yaml_wrapper():
config = load_yaml(example_widget)
config = load_yaml_gui(example_widget)
if config:
example_widget.config.update(config)
@ -120,7 +120,7 @@ def test_load_yaml_invalid_yaml(qtbot, example_widget, capsys):
temp_file.write(b"\tinvalid_yaml: [unbalanced_brackets: ]")
def load_yaml_wrapper():
config = load_yaml(example_widget)
config = load_yaml_gui(example_widget)
if config:
example_widget.config.update(config)
@ -147,7 +147,7 @@ def test_save_yaml(qtbot, example_widget):
example_widget.saved_config = {"name": "test", "value": 42}
def save_yaml_wrapper():
save_yaml(example_widget, example_widget.saved_config)
save_yaml_gui(example_widget, example_widget.saved_config)
example_widget.export_button.clicked.connect(save_yaml_wrapper)