mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-04-13 04:00:54 +02:00
Compare commits
14 Commits
refactor/b
...
v0.93.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
482efeb340 | ||
| 99ee545e41 | |||
| cf94599c25 | |||
| b50b3a27e6 | |||
| bf6294ecbf | |||
| a3d4f5ac4b | |||
| bc264975b1 | |||
| ad07bbf85e | |||
| 9856857f4c | |||
| f9e5897900 | |||
|
|
39fb22b716 | ||
| a372925fff | |||
|
|
ec54440569 | ||
| af86860bf3 |
86
CHANGELOG.md
86
CHANGELOG.md
@@ -1,5 +1,45 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.93.3 (2024-08-07)
|
||||
|
||||
### Fix
|
||||
|
||||
* fix(dock): properly shut down docks and temp areas ([`99ee545`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/99ee545e41c6078654958b668b5b329f85553d16))
|
||||
|
||||
* fix(settings): shut down settings dialog ([`b50b3a2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b50b3a27e68956e10e8169a0aa698c911d2d9642))
|
||||
|
||||
* fix(website): fixed teardown of website widgets ([`a3d4f5a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a3d4f5ac4bc52acfed2791a1724fade6972ed320))
|
||||
|
||||
* fix(dock): properly shut down docks and dock areas ([`bc26497`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bc264975b1363c9dfea516621d7878c320677d15))
|
||||
|
||||
* fix(figure): cleanup pyqtgraph ([`ad07bbf`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ad07bbf85e9c8d9838bdd686f69d41c235b7db19))
|
||||
|
||||
### Test
|
||||
|
||||
* test: removed quit from teardown ([`cf94599`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/cf94599c2544d6831c8afbe7b340082077557ed1))
|
||||
|
||||
* test: removed explicit call to close the widget ([`bf6294e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bf6294ecbfd494565d2dc215e4d7e0c280ac7745))
|
||||
|
||||
* test: use factory instead of fixture to properly cleanup widgets on teardown ([`9856857`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9856857f4cc7fa229c10d00fbae4452464a207cb))
|
||||
|
||||
* test: ensure all toplevelwidgets are closed ([`f9e5897`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/f9e58979009cf632feea529700ad191401dd7eb8))
|
||||
|
||||
## v0.93.2 (2024-08-07)
|
||||
|
||||
### Fix
|
||||
|
||||
* fix(scan_group_box): Scan Spinboxes limits increased to max allowed values; setting dialog for step size and decimal precision for ScanDoubleSpinBox on right click ([`a372925`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a372925fffa787c686198ae7cb3f9c15b459c109))
|
||||
|
||||
## v0.93.1 (2024-08-06)
|
||||
|
||||
### Documentation
|
||||
|
||||
* docs: added video tutorial section with BSEG YT video ([`302ae90`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/302ae90139f6a88e2401fe29fe312387486e27a9))
|
||||
|
||||
### Fix
|
||||
|
||||
* fix(dock): docks have more recognizable red icon for closing docks ([`af86860`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/af86860bf35474805fb1a7bc3725cf8835ed4cc7))
|
||||
|
||||
## v0.93.0 (2024-08-05)
|
||||
|
||||
### Feature
|
||||
@@ -103,49 +143,3 @@ This reverts commit fd6ae91993a23a7b8dbb2cf3c4b7c3eda6d2b0f6 ([`5aad401`](https:
|
||||
* test(dock_area): tests extended ([`06fab0e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/06fab0eab926cef5677d4988fd1fce09da342dd8))
|
||||
|
||||
## v0.90.0 (2024-07-23)
|
||||
|
||||
### Feature
|
||||
|
||||
* feat(image_widget): plugin added ([`4371168`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/43711680ba253f81fb0ffe764bcaae701b02bb49))
|
||||
|
||||
* feat(image_widget): all toolbar actions added ([`501eb92`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/501eb923f12fa6aaa93f5428ca78e57694edfbc0))
|
||||
|
||||
* feat(image_widget): image_widget added ([`6a9317f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6a9317facda896ee784c7fc1db0cd3d68cdfcf73))
|
||||
|
||||
### Fix
|
||||
|
||||
* fix(axis_setting): fix compatibility for issue with horizontal line for PyQt6 ([`1cf6e32`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1cf6e32303f82bc7c3f3391d0e96a88bc31f29fc))
|
||||
|
||||
* fix(image_widget): image_widget autorange fixed ([`7f49893`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/7f49893d2ce3b9d02efa764f7f10442ed6ab8f3c))
|
||||
|
||||
* fix(image_widget): image widget adjusted ([`3d2ca48`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/3d2ca4855c36fe0af59a4b540caa3c8023a81773))
|
||||
|
||||
* fix(image): only single monitor image is allowed ([`fe7e542`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fe7e542b19dc5b401523501acb74ac03edf62ad4))
|
||||
|
||||
* fix(image): raw data are saved in image item to always have precise processing ([`c15035b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c15035b6b769a96780a16da9e7f75af3b823654c))
|
||||
|
||||
### Refactor
|
||||
|
||||
* refactor(jupyter_console_example): added examples of standalone widgets ([`ba0d1ea`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ba0d1ea9031b4ae2e2e73bf269fbfad973b924a5))
|
||||
|
||||
### Test
|
||||
|
||||
* test(image_widget): tests added ([`70fb276`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/70fb276fdf31dffc105435d3dfe7c5caea0b10ce))
|
||||
|
||||
## v0.89.0 (2024-07-22)
|
||||
|
||||
### Feature
|
||||
|
||||
* feat(themes): moved themes to bec_qthemes ([`3798714`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/3798714369adf4023f833b7749d2f46a0ec74eee))
|
||||
|
||||
### Unknown
|
||||
|
||||
* Revert "feat(themes): moved themes to bec_qthemes"
|
||||
|
||||
This reverts commit 3798714369adf4023f833b7749d2f46a0ec74eee ([`fd6ae91`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fd6ae91993a23a7b8dbb2cf3c4b7c3eda6d2b0f6))
|
||||
|
||||
## v0.88.1 (2024-07-22)
|
||||
|
||||
### Refactor
|
||||
|
||||
* refactor(toolbar): generalizations of the ToolBarAction ([`ad112d1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ad112d1f08157f6987edd48a0bacf9f669ef1997))
|
||||
|
||||
@@ -106,3 +106,14 @@ class SettingsDialog(QDialog):
|
||||
Apply the changes made in the settings widget without closing the dialog.
|
||||
"""
|
||||
self.widget.accept_changes()
|
||||
|
||||
def cleanup(self):
|
||||
"""
|
||||
Cleanup the dialog.
|
||||
"""
|
||||
self.button_box.close()
|
||||
self.button_box.deleteLater()
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.cleanup()
|
||||
super().closeEvent(event)
|
||||
|
||||
@@ -34,3 +34,10 @@ class ColorButton(pg.ColorButton):
|
||||
return self.color().getRgb()
|
||||
if format == "HEX":
|
||||
return self.color().name()
|
||||
|
||||
def cleanup(self):
|
||||
"""
|
||||
Clean up the ColorButton.
|
||||
"""
|
||||
self.colorDialog.close()
|
||||
self.colorDialog.deleteLater()
|
||||
|
||||
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Any, Literal, Optional
|
||||
|
||||
from pydantic import Field
|
||||
from pyqtgraph.dockarea import Dock, DockLabel
|
||||
from qtpy import QtCore, QtGui
|
||||
|
||||
from bec_widgets.cli.rpc_wigdet_handler import widget_handler
|
||||
from bec_widgets.utils import ConnectionConfig, GridLayoutManager
|
||||
@@ -12,8 +13,6 @@ from bec_widgets.utils.bec_widget import BECWidget
|
||||
if TYPE_CHECKING:
|
||||
from qtpy.QtWidgets import QWidget
|
||||
|
||||
from bec_widgets.widgets.dock import BECDockArea
|
||||
|
||||
|
||||
class DockConfig(ConnectionConfig):
|
||||
widgets: dict[str, Any] = Field({}, description="The widgets in the dock.")
|
||||
@@ -26,6 +25,23 @@ class DockConfig(ConnectionConfig):
|
||||
|
||||
|
||||
class CustomDockLabel(DockLabel):
|
||||
def __init__(self, text: str, closable: bool = True):
|
||||
super().__init__(text, closable)
|
||||
if closable:
|
||||
red_icon = QtGui.QIcon()
|
||||
pixmap = QtGui.QPixmap(32, 32)
|
||||
pixmap.fill(QtCore.Qt.GlobalColor.red)
|
||||
painter = QtGui.QPainter(pixmap)
|
||||
pen = QtGui.QPen(QtCore.Qt.GlobalColor.white)
|
||||
pen.setWidth(2)
|
||||
painter.setPen(pen)
|
||||
painter.drawLine(8, 8, 24, 24)
|
||||
painter.drawLine(24, 8, 8, 24)
|
||||
painter.end()
|
||||
red_icon.addPixmap(pixmap)
|
||||
|
||||
self.closeButton.setIcon(red_icon)
|
||||
|
||||
def updateStyle(self):
|
||||
r = "3px"
|
||||
if self.dim:
|
||||
@@ -137,6 +153,7 @@ class BECDock(BECWidget, Dock):
|
||||
super().dropEvent(event)
|
||||
if old_area in self.orig_area.tempAreas and old_area != self.orig_area:
|
||||
self.orig_area.removeTempArea(old_area)
|
||||
old_area.window().deleteLater()
|
||||
|
||||
def float(self):
|
||||
"""
|
||||
@@ -268,7 +285,7 @@ class BECDock(BECWidget, Dock):
|
||||
"""
|
||||
Attach the dock to the parent dock area.
|
||||
"""
|
||||
self.orig_area.removeTempArea(self.area)
|
||||
self.parent_dock_area.remove_temp_area(self.area)
|
||||
|
||||
def detach(self):
|
||||
"""
|
||||
@@ -303,6 +320,8 @@ class BECDock(BECWidget, Dock):
|
||||
if hasattr(widget, "cleanup"):
|
||||
widget.cleanup()
|
||||
self.widgets.clear()
|
||||
self.label.close()
|
||||
self.label.deleteLater()
|
||||
super().cleanup()
|
||||
|
||||
def close(self):
|
||||
|
||||
@@ -231,6 +231,7 @@ class BECDockArea(BECWidget, QWidget):
|
||||
self.config.docks.pop(name, None)
|
||||
if dock:
|
||||
dock.close()
|
||||
dock.deleteLater()
|
||||
if len(self.dock_area.docks) <= 1:
|
||||
for dock in self.dock_area.docks.values():
|
||||
dock.hide_title_bar()
|
||||
@@ -329,7 +330,16 @@ class BECDockArea(BECWidget, QWidget):
|
||||
"""
|
||||
while self.dock_area.tempAreas:
|
||||
for temp_area in self.dock_area.tempAreas:
|
||||
self.dock_area.removeTempArea(temp_area)
|
||||
self.remove_temp_area(temp_area)
|
||||
|
||||
def remove_temp_area(self, area):
|
||||
"""
|
||||
Remove a temporary area from the dock area.
|
||||
This is a patched method of pyqtgraph's removeTempArea
|
||||
"""
|
||||
self.dock_area.tempAreas.remove(area)
|
||||
area.window().close()
|
||||
area.window().deleteLater()
|
||||
|
||||
def clear_all(self):
|
||||
"""
|
||||
@@ -345,6 +355,10 @@ class BECDockArea(BECWidget, QWidget):
|
||||
Cleanup the dock area.
|
||||
"""
|
||||
self.clear_all()
|
||||
self.toolbar.close()
|
||||
self.toolbar.deleteLater()
|
||||
self.dock_area.close()
|
||||
self.dock_area.deleteLater()
|
||||
super().cleanup()
|
||||
|
||||
def close(self):
|
||||
|
||||
@@ -513,6 +513,13 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
|
||||
if widget_id in self._widgets:
|
||||
raise ValueError(f"Widget with ID '{widget_id}' already exists.")
|
||||
|
||||
# Check if position is occupied
|
||||
if row is not None and col is not None:
|
||||
if self.getItem(row, col):
|
||||
raise ValueError(f"Position at row {row} and column {col} is already occupied.")
|
||||
else:
|
||||
row, col = self._find_next_empty_position()
|
||||
|
||||
widget = self.widget_handler.create_widget(
|
||||
widget_type=widget_type,
|
||||
widget_id=widget_id,
|
||||
@@ -525,23 +532,11 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
|
||||
# used otherwise multiple times
|
||||
widget.set_gui_id(widget_id)
|
||||
|
||||
# Check if position is occupied
|
||||
if row is not None and col is not None:
|
||||
if self.getItem(row, col):
|
||||
raise ValueError(f"Position at row {row} and column {col} is already occupied.")
|
||||
widget.config.row = row
|
||||
widget.config.col = col
|
||||
|
||||
widget.config.row = row
|
||||
widget.config.col = col
|
||||
|
||||
# Add widget to the figure
|
||||
self.addItem(widget, row=row, col=col)
|
||||
else:
|
||||
row, col = self._find_next_empty_position()
|
||||
widget.config.row = row
|
||||
widget.config.col = col
|
||||
|
||||
# Add widget to the figure
|
||||
self.addItem(widget, row=row, col=col)
|
||||
# Add widget to the figure
|
||||
self.addItem(widget, row=row, col=col)
|
||||
|
||||
# Update num_cols and num_rows based on the added widget
|
||||
self.config.num_rows = max(self.config.num_rows, row + 1)
|
||||
@@ -620,6 +615,7 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
|
||||
"""
|
||||
if widget_id in self._widgets:
|
||||
widget = self._widgets.pop(widget_id)
|
||||
widget.cleanup_pyqtgraph()
|
||||
widget.cleanup()
|
||||
self.removeItem(widget)
|
||||
self.grid[widget.config.row][widget.config.col] = None
|
||||
@@ -745,3 +741,12 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
|
||||
self.config = FigureConfig(
|
||||
widget_class=self.__class__.__name__, gui_id=self.gui_id, theme=theme
|
||||
)
|
||||
|
||||
def cleanup_pyqtgraph_all_widgets(self):
|
||||
"""Clean up the pyqtgraph widget."""
|
||||
for widget in self.widget_list:
|
||||
widget.cleanup_pyqtgraph()
|
||||
|
||||
def cleanup(self):
|
||||
"""Close the figure widget."""
|
||||
self.cleanup_pyqtgraph_all_widgets()
|
||||
|
||||
@@ -681,3 +681,17 @@ class BECImageShow(BECPlotBase):
|
||||
self.on_image_update, MessageEndpoints.device_monitor_2d(monitor)
|
||||
)
|
||||
self.images.clear()
|
||||
|
||||
def cleanup_pyqtgraph(self):
|
||||
"""Cleanup pyqtgraph items."""
|
||||
super().cleanup_pyqtgraph()
|
||||
item = self.plot_item
|
||||
if not item.items:
|
||||
return
|
||||
cbar = item.items[0].color_bar
|
||||
cbar.vb.menu.close()
|
||||
cbar.vb.menu.deleteLater()
|
||||
cbar.gradient.menu.close()
|
||||
cbar.gradient.menu.deleteLater()
|
||||
cbar.gradient.colorDialog.close()
|
||||
cbar.gradient.colorDialog.deleteLater()
|
||||
|
||||
@@ -314,3 +314,11 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
||||
"""Remove the plot widget from the figure."""
|
||||
if self.figure is not None:
|
||||
self.figure.remove(widget_id=self.gui_id)
|
||||
|
||||
def cleanup_pyqtgraph(self):
|
||||
"""Cleanup pyqtgraph items."""
|
||||
item = self.plot_item
|
||||
item.vb.menu.close()
|
||||
item.vb.menu.deleteLater()
|
||||
item.ctrlMenu.close()
|
||||
item.ctrlMenu.deleteLater()
|
||||
|
||||
@@ -458,6 +458,8 @@ class BECImageWidget(BECWidget, QWidget):
|
||||
def cleanup(self):
|
||||
self.fig.cleanup()
|
||||
self.client.shutdown()
|
||||
self.toolbar.close()
|
||||
self.toolbar.deleteLater()
|
||||
return super().cleanup()
|
||||
|
||||
|
||||
|
||||
@@ -45,3 +45,12 @@ class MotorMapSettings(SettingWidget):
|
||||
self.target_widget.set_scatter_size(scatter_size)
|
||||
self.target_widget.set_background_value(background_intensity)
|
||||
self.target_widget.set_color(color)
|
||||
|
||||
def cleanup(self):
|
||||
self.ui.color.cleanup()
|
||||
self.ui.color.close()
|
||||
self.ui.color.deleteLater()
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.cleanup()
|
||||
super().closeEvent(event)
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
from typing import Literal
|
||||
|
||||
from qtpy.QtCore import Qt
|
||||
from qtpy.QtWidgets import (
|
||||
QCheckBox,
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QDoubleSpinBox,
|
||||
QFormLayout,
|
||||
QGridLayout,
|
||||
QGroupBox,
|
||||
QLabel,
|
||||
@@ -25,13 +29,46 @@ class ScanArgType:
|
||||
LITERALS = "dict"
|
||||
|
||||
|
||||
class SettingsDialog(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Settings")
|
||||
|
||||
layout = QFormLayout()
|
||||
|
||||
self.precision_spin_box = QSpinBox()
|
||||
self.precision_spin_box.setRange(
|
||||
-2147483647, 2147483647
|
||||
) # 2147483647 is the largest int which qt allows
|
||||
|
||||
self.step_size_spin_box = QDoubleSpinBox()
|
||||
self.step_size_spin_box.setRange(-float("inf"), float("inf"))
|
||||
|
||||
fixed_width = 80
|
||||
self.precision_spin_box.setFixedWidth(fixed_width)
|
||||
self.step_size_spin_box.setFixedWidth(fixed_width)
|
||||
|
||||
layout.addRow("Decimal Precision:", self.precision_spin_box)
|
||||
layout.addRow("Step Size:", self.step_size_spin_box)
|
||||
|
||||
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
button_box.accepted.connect(self.accept)
|
||||
button_box.rejected.connect(self.reject)
|
||||
layout.addWidget(button_box)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def getValues(self):
|
||||
return self.precision_spin_box.value(), self.step_size_spin_box.value()
|
||||
|
||||
|
||||
class ScanSpinBox(QSpinBox):
|
||||
def __init__(
|
||||
self, parent=None, arg_name: str = None, default: int | None = None, *args, **kwargs
|
||||
):
|
||||
super().__init__(parent=parent, *args, **kwargs)
|
||||
self.arg_name = arg_name
|
||||
self.setRange(-9999, 9999)
|
||||
self.setRange(-2147483647, 2147483647) # 2147483647 is the largest int which qt allows
|
||||
if default is not None:
|
||||
self.setValue(default)
|
||||
|
||||
@@ -42,10 +79,25 @@ class ScanDoubleSpinBox(QDoubleSpinBox):
|
||||
):
|
||||
super().__init__(parent=parent, *args, **kwargs)
|
||||
self.arg_name = arg_name
|
||||
self.setRange(-9999, 9999)
|
||||
self.setRange(-float("inf"), float("inf"))
|
||||
if default is not None:
|
||||
self.setValue(default)
|
||||
|
||||
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
self.customContextMenuRequested.connect(self.showSettingsDialog)
|
||||
|
||||
self.setToolTip("Right click to open settings dialog for decimal precision and step size.")
|
||||
|
||||
def showSettingsDialog(self):
|
||||
dialog = SettingsDialog(self)
|
||||
dialog.precision_spin_box.setValue(self.decimals())
|
||||
dialog.step_size_spin_box.setValue(self.singleStep())
|
||||
|
||||
if dialog.exec_() == QDialog.Accepted:
|
||||
precision, step_size = dialog.getValues()
|
||||
self.setDecimals(precision)
|
||||
self.setSingleStep(step_size)
|
||||
|
||||
|
||||
class ScanLineEdit(QLineEdit):
|
||||
def __init__(
|
||||
|
||||
@@ -64,6 +64,12 @@ class WebsiteWidget(BECWidget, QWebEngineView):
|
||||
"""
|
||||
QWebEngineView.forward(self)
|
||||
|
||||
def cleanup(self):
|
||||
"""
|
||||
Cleanup the widget
|
||||
"""
|
||||
self.page().deleteLater()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "bec_widgets"
|
||||
version = "0.93.0"
|
||||
version = "0.93.3"
|
||||
description = "BEC Widgets"
|
||||
requires-python = ">=3.10"
|
||||
classifiers = [
|
||||
|
||||
@@ -12,7 +12,6 @@ def scan_control(qtbot, bec_client_lib): # , mock_dev):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_scan_control_populate_scans_e2e(scan_control):
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import pytest
|
||||
from pytestqt.exceptions import TimeoutError as QtBotTimeoutError
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
from bec_widgets.cli.rpc_register import RPCRegister
|
||||
from bec_widgets.qt_utils import error_popups
|
||||
@@ -6,9 +8,16 @@ from bec_widgets.utils import bec_dispatcher as bec_dispatcher_module
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def qapplication(qapp): # pylint: disable=unused-argument
|
||||
def qapplication(qtbot): # pylint: disable=unused-argument
|
||||
yield
|
||||
qapp.processEvents() # make sure all events are processed before shutting down
|
||||
|
||||
qapp = QApplication.instance()
|
||||
# qapp.quit()
|
||||
qapp.processEvents()
|
||||
try:
|
||||
qtbot.waitUntil(lambda: qapp.topLevelWidgets() == [])
|
||||
except QtBotTimeoutError as exc:
|
||||
raise TimeoutError(f"Failed to close all widgets: {qapp.topLevelWidgets()}") from exc
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -31,3 +40,25 @@ def bec_dispatcher(threads_check): # pylint: disable=unused-argument
|
||||
@pytest.fixture(autouse=True)
|
||||
def clean_singleton():
|
||||
error_popups._popup_utility_instance = None
|
||||
|
||||
|
||||
def create_widget(qtbot, widget, *args, **kwargs):
|
||||
"""
|
||||
Create a widget and add it to the qtbot for testing. This is a helper function that
|
||||
should be used in all tests that require a widget to be created.
|
||||
DO NOT CREATE WIDGETS DIRECTLY IN A FIXTURE!
|
||||
|
||||
Args:
|
||||
qtbot (fixture): pytest-qt fixture
|
||||
widget (QWidget): widget class to be created
|
||||
*args: positional arguments for the widget
|
||||
**kwargs: keyword arguments for the widget
|
||||
|
||||
Returns:
|
||||
QWidget: the created widget
|
||||
|
||||
"""
|
||||
widget = widget(*args, **kwargs)
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
return widget
|
||||
|
||||
@@ -14,7 +14,6 @@ def bec_dock_area(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_bec_dock_area_init(bec_dock_area):
|
||||
|
||||
@@ -9,18 +9,11 @@ from bec_widgets.widgets.figure.plots.motor_map.motor_map import BECMotorMap
|
||||
from bec_widgets.widgets.figure.plots.waveform.waveform import BECWaveform
|
||||
|
||||
from .client_mocks import mocked_client
|
||||
from .conftest import create_widget
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bec_figure(qtbot, mocked_client):
|
||||
widget = BECFigure(client=mocked_client)
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_bec_figure_init(bec_figure):
|
||||
def test_bec_figure_init(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
assert bec_figure is not None
|
||||
assert bec_figure.client is not None
|
||||
assert isinstance(bec_figure, BECFigure)
|
||||
@@ -34,7 +27,8 @@ def test_bec_figure_init_with_config(mocked_client):
|
||||
assert widget.config.theme == "dark"
|
||||
|
||||
|
||||
def test_bec_figure_add_remove_plot(bec_figure):
|
||||
def test_bec_figure_add_remove_plot(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
initial_count = len(bec_figure._widgets)
|
||||
|
||||
# Adding 3 widgets - 2 WaveformBase and 1 PlotBase
|
||||
@@ -64,7 +58,8 @@ def test_bec_figure_add_remove_plot(bec_figure):
|
||||
assert bec_figure._widgets[w1.gui_id].config.widget_class == "BECWaveform"
|
||||
|
||||
|
||||
def test_add_different_types_of_widgets(bec_figure):
|
||||
def test_add_different_types_of_widgets(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
plt = bec_figure.plot(x_name="samx", y_name="bpm4i")
|
||||
im = bec_figure.image("eiger")
|
||||
motor_map = bec_figure.motor_map("samx", "samy")
|
||||
@@ -74,7 +69,8 @@ def test_add_different_types_of_widgets(bec_figure):
|
||||
assert motor_map.__class__ == BECMotorMap
|
||||
|
||||
|
||||
def test_access_widgets_access_errors(bec_figure):
|
||||
def test_access_widgets_access_errors(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
bec_figure.plot(row=0, col=0)
|
||||
|
||||
# access widget by non-existent coordinates
|
||||
@@ -96,7 +92,8 @@ def test_access_widgets_access_errors(bec_figure):
|
||||
)
|
||||
|
||||
|
||||
def test_add_plot_to_occupied_position(bec_figure):
|
||||
def test_add_plot_to_occupied_position(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
bec_figure.plot(row=0, col=0)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@@ -104,7 +101,8 @@ def test_add_plot_to_occupied_position(bec_figure):
|
||||
assert "Position at row 0 and column 0 is already occupied." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_remove_plots(bec_figure):
|
||||
def test_remove_plots(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot(row=0, col=0)
|
||||
w2 = bec_figure.plot(row=0, col=1)
|
||||
w3 = bec_figure.plot(row=1, col=0)
|
||||
@@ -134,7 +132,8 @@ def test_remove_plots(bec_figure):
|
||||
assert len(bec_figure._widgets) == 1
|
||||
|
||||
|
||||
def test_remove_plots_by_coordinates_ints(bec_figure):
|
||||
def test_remove_plots_by_coordinates_ints(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot(row=0, col=0)
|
||||
w2 = bec_figure.plot(row=0, col=1)
|
||||
|
||||
@@ -145,7 +144,8 @@ def test_remove_plots_by_coordinates_ints(bec_figure):
|
||||
assert len(bec_figure._widgets) == 1
|
||||
|
||||
|
||||
def test_remove_plots_by_coordinates_tuple(bec_figure):
|
||||
def test_remove_plots_by_coordinates_tuple(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot(row=0, col=0)
|
||||
w2 = bec_figure.plot(row=0, col=1)
|
||||
|
||||
@@ -156,7 +156,8 @@ def test_remove_plots_by_coordinates_tuple(bec_figure):
|
||||
assert len(bec_figure._widgets) == 1
|
||||
|
||||
|
||||
def test_remove_plot_by_id_error(bec_figure):
|
||||
def test_remove_plot_by_id_error(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
bec_figure.plot()
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@@ -164,7 +165,8 @@ def test_remove_plot_by_id_error(bec_figure):
|
||||
assert "Widget with ID 'non_existent_widget' does not exist." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_remove_plot_by_coordinates_error(bec_figure):
|
||||
def test_remove_plot_by_coordinates_error(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
bec_figure.plot(row=0, col=0)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@@ -172,7 +174,8 @@ def test_remove_plot_by_coordinates_error(bec_figure):
|
||||
assert "No widget at coordinates (0, 1)" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_remove_plot_by_providing_nothing(bec_figure):
|
||||
def test_remove_plot_by_providing_nothing(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
bec_figure.plot(row=0, col=0)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@@ -192,7 +195,8 @@ def test_remove_plot_by_providing_nothing(bec_figure):
|
||||
# assert bec_figure.backgroundBrush().color().name() == "#000000"
|
||||
|
||||
|
||||
def test_change_layout(bec_figure):
|
||||
def test_change_layout(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot(row=0, col=0)
|
||||
w2 = bec_figure.plot(row=0, col=1)
|
||||
w3 = bec_figure.plot(row=1, col=0)
|
||||
@@ -215,7 +219,8 @@ def test_change_layout(bec_figure):
|
||||
assert bec_figure[0, 3] == w4
|
||||
|
||||
|
||||
def test_clear_all(bec_figure):
|
||||
def test_clear_all(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
bec_figure.plot(row=0, col=0)
|
||||
bec_figure.plot(row=0, col=1)
|
||||
bec_figure.plot(row=1, col=0)
|
||||
@@ -227,7 +232,8 @@ def test_clear_all(bec_figure):
|
||||
assert np.shape(bec_figure.grid) == (0,)
|
||||
|
||||
|
||||
def test_shortcuts(bec_figure):
|
||||
def test_shortcuts(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
plt = bec_figure.plot(x_name="samx", y_name="bpm4i")
|
||||
im = bec_figure.image("eiger")
|
||||
motor_map = bec_figure.motor_map("samx", "samy")
|
||||
@@ -240,7 +246,8 @@ def test_shortcuts(bec_figure):
|
||||
assert motor_map.__class__ == BECMotorMap
|
||||
|
||||
|
||||
def test_plot_access_factory(bec_figure):
|
||||
def test_plot_access_factory(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
plt_00 = bec_figure.plot(x_name="samx", y_name="bpm4i")
|
||||
plt_01 = bec_figure.plot(x_name="samx", y_name="bpm4i", row=0, col=1)
|
||||
plt_10 = bec_figure.plot(new=True)
|
||||
|
||||
@@ -6,8 +6,10 @@ import pytest
|
||||
from bec_lib import messages
|
||||
from qtpy.QtGui import QFontInfo
|
||||
|
||||
from bec_widgets.widgets.figure import BECFigure
|
||||
|
||||
from .client_mocks import mocked_client
|
||||
from .test_bec_figure import bec_figure
|
||||
from .conftest import create_widget
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -15,7 +17,8 @@ def bec_image_show(bec_figure):
|
||||
yield bec_figure.image("eiger")
|
||||
|
||||
|
||||
def test_on_image_update(bec_image_show):
|
||||
def test_on_image_update(qtbot, mocked_client):
|
||||
bec_image_show = create_widget(qtbot, BECFigure, client=mocked_client).image("eiger")
|
||||
data = np.random.rand(100, 100)
|
||||
msg = messages.DeviceMonitor2DMessage(device="eiger", data=data, metadata={"scan_id": "12345"})
|
||||
bec_image_show.on_image_update(msg.content, msg.metadata)
|
||||
@@ -23,7 +26,8 @@ def test_on_image_update(bec_image_show):
|
||||
assert np.array_equal(img.get_data(), data)
|
||||
|
||||
|
||||
def test_autorange_on_image_update(bec_image_show):
|
||||
def test_autorange_on_image_update(qtbot, mocked_client):
|
||||
bec_image_show = create_widget(qtbot, BECFigure, client=mocked_client).image("eiger")
|
||||
# Check if autorange mode "mean" works, should be default
|
||||
data = np.random.rand(100, 100)
|
||||
msg = messages.DeviceMonitor2DMessage(device="eiger", data=data, metadata={"scan_id": "12345"})
|
||||
|
||||
@@ -15,7 +15,6 @@ def image_widget(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -2,14 +2,16 @@ import numpy as np
|
||||
import pytest
|
||||
from bec_lib.messages import DeviceMessage
|
||||
|
||||
from bec_widgets.widgets.figure import BECFigure
|
||||
from bec_widgets.widgets.figure.plots.motor_map.motor_map import BECMotorMap, MotorMapConfig
|
||||
from bec_widgets.widgets.figure.plots.waveform.waveform_curve import SignalData
|
||||
|
||||
from .client_mocks import mocked_client
|
||||
from .test_bec_figure import bec_figure
|
||||
from .conftest import create_widget
|
||||
|
||||
|
||||
def test_motor_map_init(bec_figure):
|
||||
def test_motor_map_init(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
default_config = MotorMapConfig(widget_class="BECMotorMap")
|
||||
|
||||
mm = bec_figure.motor_map(config=default_config.model_dump())
|
||||
@@ -18,7 +20,8 @@ def test_motor_map_init(bec_figure):
|
||||
assert mm.config == default_config
|
||||
|
||||
|
||||
def test_motor_map_change_motors(bec_figure):
|
||||
def test_motor_map_change_motors(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
|
||||
assert mm.motor_x == "samx"
|
||||
@@ -32,7 +35,8 @@ def test_motor_map_change_motors(bec_figure):
|
||||
assert mm.config.signals.y == SignalData(name="samz", entry="samz", limits=[-8, 8])
|
||||
|
||||
|
||||
def test_motor_map_get_limits(bec_figure):
|
||||
def test_motor_map_get_limits(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
expected_limits = {"samx": [-10, 10], "samy": [-5, 5]}
|
||||
|
||||
@@ -41,7 +45,8 @@ def test_motor_map_get_limits(bec_figure):
|
||||
assert actual_limit == expected_limit
|
||||
|
||||
|
||||
def test_motor_map_get_init_position(bec_figure):
|
||||
def test_motor_map_get_init_position(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
mm.set_precision(2)
|
||||
|
||||
@@ -57,7 +62,8 @@ def test_motor_map_get_init_position(bec_figure):
|
||||
assert actual_position == expected_position
|
||||
|
||||
|
||||
def test_motor_movement_updates_position_and_database(bec_figure):
|
||||
def test_motor_movement_updates_position_and_database(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
motor_map_dev = mm.client.device_manager.devices
|
||||
|
||||
@@ -85,7 +91,8 @@ def test_motor_movement_updates_position_and_database(bec_figure):
|
||||
assert mm.database_buffer["y"] == init_positions["samy"]
|
||||
|
||||
|
||||
def test_scatter_plot_rendering(bec_figure):
|
||||
def test_scatter_plot_rendering(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
motor_map_dev = mm.client.device_manager.devices
|
||||
|
||||
@@ -115,7 +122,8 @@ def test_scatter_plot_rendering(bec_figure):
|
||||
), "Scatter plot Y data should retain last known position"
|
||||
|
||||
|
||||
def test_plot_visualization_consistency(bec_figure):
|
||||
def test_plot_visualization_consistency(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
mm.change_motors("samx", "samy")
|
||||
# Simulate updating the plot with new data
|
||||
@@ -133,7 +141,8 @@ def test_plot_visualization_consistency(bec_figure):
|
||||
), "Plot not updated correctly with new data"
|
||||
|
||||
|
||||
def test_change_background_value(bec_figure, qtbot):
|
||||
def test_change_background_value(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
|
||||
assert mm.config.background_value == 25
|
||||
@@ -146,7 +155,8 @@ def test_change_background_value(bec_figure, qtbot):
|
||||
assert np.all(mm.plot_components["limit_map"].image == 50.0)
|
||||
|
||||
|
||||
def test_motor_map_init_from_config(bec_figure):
|
||||
def test_motor_map_init_from_config(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
config = {
|
||||
"widget_class": "BECMotorMap",
|
||||
"gui_id": "mm_id",
|
||||
@@ -200,7 +210,8 @@ def test_motor_map_init_from_config(bec_figure):
|
||||
assert mm._config_dict == config
|
||||
|
||||
|
||||
def test_motor_map_set_scatter_size(bec_figure, qtbot):
|
||||
def test_motor_map_set_scatter_size(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
|
||||
assert mm.config.scatter_size == 5
|
||||
@@ -213,7 +224,8 @@ def test_motor_map_set_scatter_size(bec_figure, qtbot):
|
||||
assert mm.plot_components["scatter"].opts["size"] == 10
|
||||
|
||||
|
||||
def test_motor_map_change_precision(bec_figure):
|
||||
def test_motor_map_change_precision(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
|
||||
assert mm.config.precision == 2
|
||||
@@ -221,7 +233,8 @@ def test_motor_map_change_precision(bec_figure):
|
||||
assert mm.config.precision == 10
|
||||
|
||||
|
||||
def test_motor_map_set_color(bec_figure, qtbot):
|
||||
def test_motor_map_set_color(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
|
||||
assert mm.config.color == (255, 255, 255, 255)
|
||||
@@ -231,7 +244,8 @@ def test_motor_map_set_color(bec_figure, qtbot):
|
||||
assert mm.config.color == (0, 0, 0, 255)
|
||||
|
||||
|
||||
def test_motor_map_get_data_max_points(bec_figure, qtbot):
|
||||
def test_motor_map_get_data_max_points(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
mm = bec_figure.motor_map("samx", "samy")
|
||||
motor_map_dev = mm.client.device_manager.devices
|
||||
|
||||
|
||||
@@ -93,7 +93,6 @@ def bec_queue(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_bec_queue(bec_queue, bec_queue_msg_full):
|
||||
|
||||
@@ -20,7 +20,6 @@ def status_box(qtbot, mocked_client, service_status_fixture):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_update_top_item(status_box):
|
||||
|
||||
@@ -10,7 +10,6 @@ def color_map_selector(qtbot):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_color_map_selector_init(color_map_selector):
|
||||
|
||||
@@ -19,7 +19,6 @@ def device_input_base(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_device_input_base_init(device_input_base):
|
||||
|
||||
@@ -12,7 +12,6 @@ def device_input_combobox(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -28,7 +27,6 @@ def device_input_combobox_with_config(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -43,7 +41,6 @@ def device_input_combobox_with_kwargs(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_device_input_combobox_init(device_input_combobox):
|
||||
@@ -101,7 +98,6 @@ def device_input_line_edit(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -117,7 +113,6 @@ def device_input_line_edit_with_config(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -132,7 +127,6 @@ def device_input_line_edit_with_kwargs(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_device_input_line_edit_init(device_input_line_edit):
|
||||
|
||||
@@ -16,7 +16,6 @@ def motor_map_widget(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -139,7 +138,6 @@ def motor_map_settings(qtbot):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_display_current_settings(motor_map_settings):
|
||||
|
||||
@@ -4,18 +4,22 @@ from unittest import mock
|
||||
import pytest
|
||||
from qtpy.QtGui import QFontInfo
|
||||
|
||||
from bec_widgets.widgets.figure import BECFigure
|
||||
|
||||
from .client_mocks import mocked_client
|
||||
from .test_bec_figure import bec_figure
|
||||
from .conftest import create_widget
|
||||
|
||||
|
||||
def test_init_plot_base(bec_figure):
|
||||
def test_init_plot_base(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
|
||||
assert plot_base is not None
|
||||
assert plot_base.config.widget_class == "BECPlotBase"
|
||||
assert plot_base.config.gui_id == "test_plot"
|
||||
|
||||
|
||||
def test_plot_base_axes_by_separate_methods(bec_figure):
|
||||
def test_plot_base_axes_by_separate_methods(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
|
||||
|
||||
plot_base.set_title("Test Title")
|
||||
@@ -65,7 +69,8 @@ def test_plot_base_axes_by_separate_methods(bec_figure):
|
||||
assert mock_set_title.call_args == call
|
||||
|
||||
|
||||
def test_plot_base_axes_added_by_kwargs(bec_figure):
|
||||
def test_plot_base_axes_added_by_kwargs(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
|
||||
|
||||
plot_base.set(
|
||||
|
||||
@@ -18,7 +18,6 @@ def ring_progress_bar(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_bar_init(ring_progress_bar):
|
||||
|
||||
@@ -220,7 +220,6 @@ def scan_control(qtbot, mocked_client): # , mock_dev):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_populate_scans(scan_control, mocked_client):
|
||||
|
||||
@@ -16,7 +16,6 @@ def setting_widget(qtbot):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_setting_widget_initialization(setting_widget):
|
||||
@@ -61,8 +60,8 @@ def settings_dialog(qtbot, setting_widget):
|
||||
qtbot.addWidget(dialog)
|
||||
qtbot.waitExposed(dialog)
|
||||
yield dialog, parent_widget, setting_widget
|
||||
dialog.close()
|
||||
parent_widget.close()
|
||||
parent_widget.deleteLater()
|
||||
|
||||
|
||||
def test_settings_dialog_initialization(settings_dialog):
|
||||
|
||||
@@ -13,7 +13,6 @@ def stop_button(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_stop_button(stop_button):
|
||||
|
||||
@@ -14,7 +14,6 @@ def text_box_widget(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_textbox_widget(text_box_widget):
|
||||
|
||||
@@ -10,7 +10,6 @@ def toggle(qtbot):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_toggle(toggle):
|
||||
|
||||
@@ -14,9 +14,9 @@ from .client_mocks import mocked_client
|
||||
def vscode_widget(qtbot, mocked_client):
|
||||
with mock.patch("bec_widgets.widgets.vscode.vscode.subprocess.Popen") as mock_popen:
|
||||
widget = VSCodeEditor(client=mocked_client)
|
||||
# qtbot.addWidget(widget)
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
# widget.close()
|
||||
|
||||
|
||||
def test_vscode_widget(qtbot, vscode_widget):
|
||||
|
||||
@@ -4,13 +4,15 @@ from unittest import mock
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from bec_widgets.widgets.figure import BECFigure
|
||||
from bec_widgets.widgets.figure.plots.waveform.waveform_curve import CurveConfig, Signal, SignalData
|
||||
|
||||
from .client_mocks import mocked_client
|
||||
from .test_bec_figure import bec_figure
|
||||
from .conftest import create_widget
|
||||
|
||||
|
||||
def test_adding_curve_to_waveform(bec_figure):
|
||||
def test_adding_curve_to_waveform(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
# adding curve which is in bec - only names
|
||||
@@ -38,7 +40,8 @@ def test_adding_curve_to_waveform(bec_figure):
|
||||
assert c3.config.label == "non_existent_device-non_existent_device"
|
||||
|
||||
|
||||
def test_adding_curve_with_same_id(bec_figure):
|
||||
def test_adding_curve_with_same_id(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i", gui_id="test_curve")
|
||||
|
||||
@@ -47,7 +50,8 @@ def test_adding_curve_with_same_id(bec_figure):
|
||||
assert "Curve with ID 'test_curve' already exists." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_create_waveform1D_by_config(bec_figure):
|
||||
def test_create_waveform1D_by_config(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1_config_input = {
|
||||
"widget_class": "BECWaveform",
|
||||
"gui_id": "widget_1",
|
||||
@@ -132,7 +136,8 @@ def test_create_waveform1D_by_config(bec_figure):
|
||||
assert w1.config.axis.title == "Widget 1"
|
||||
|
||||
|
||||
def test_change_gui_id(bec_figure):
|
||||
def test_change_gui_id(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i")
|
||||
w1.change_gui_id("new_id")
|
||||
@@ -141,7 +146,8 @@ def test_change_gui_id(bec_figure):
|
||||
assert c1.config.parent_id == "new_id"
|
||||
|
||||
|
||||
def test_getting_curve(bec_figure):
|
||||
def test_getting_curve(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i", gui_id="test_curve")
|
||||
c1_expected_config = CurveConfig(
|
||||
@@ -173,7 +179,8 @@ def test_getting_curve(bec_figure):
|
||||
assert c1.get_config() == c1_expected_config.model_dump()
|
||||
|
||||
|
||||
def test_getting_curve_errors(bec_figure):
|
||||
def test_getting_curve_errors(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i", gui_id="test_curve")
|
||||
|
||||
@@ -190,7 +197,8 @@ def test_getting_curve_errors(bec_figure):
|
||||
)
|
||||
|
||||
|
||||
def test_add_curve(bec_figure):
|
||||
def test_add_curve(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i")
|
||||
@@ -201,7 +209,8 @@ def test_add_curve(bec_figure):
|
||||
assert c1.config.source == "scan_segment"
|
||||
|
||||
|
||||
def test_change_legend_font_size(bec_figure):
|
||||
def test_change_legend_font_size(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
plot = bec_figure.plot()
|
||||
|
||||
w1 = plot.add_curve_bec(x_name="samx", y_name="bpm4i")
|
||||
@@ -213,7 +222,8 @@ def test_change_legend_font_size(bec_figure):
|
||||
assert mock_set_scale.call_args == mock.call(2)
|
||||
|
||||
|
||||
def test_remove_curve(bec_figure):
|
||||
def test_remove_curve(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
w1.add_curve_bec(x_name="samx", y_name="bpm4i")
|
||||
@@ -231,7 +241,8 @@ def test_remove_curve(bec_figure):
|
||||
)
|
||||
|
||||
|
||||
def test_change_curve_appearance_methods(bec_figure, qtbot):
|
||||
def test_change_curve_appearance_methods(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i")
|
||||
@@ -260,7 +271,8 @@ def test_change_curve_appearance_methods(bec_figure, qtbot):
|
||||
}
|
||||
|
||||
|
||||
def test_change_curve_appearance_args(bec_figure):
|
||||
def test_change_curve_appearance_args(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i")
|
||||
@@ -290,7 +302,8 @@ def test_change_curve_appearance_args(bec_figure):
|
||||
}
|
||||
|
||||
|
||||
def test_set_custom_curve_data(bec_figure, qtbot):
|
||||
def test_set_custom_curve_data(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1 = w1.add_curve_custom(
|
||||
@@ -326,7 +339,8 @@ def test_set_custom_curve_data(bec_figure, qtbot):
|
||||
assert np.array_equal(y_new, [7, 8, 9])
|
||||
|
||||
|
||||
def test_custom_data_2D_array(bec_figure, qtbot):
|
||||
def test_custom_data_2D_array(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
|
||||
data = np.random.rand(10, 2)
|
||||
|
||||
@@ -338,7 +352,8 @@ def test_custom_data_2D_array(bec_figure, qtbot):
|
||||
assert np.array_equal(y, data[:, 1])
|
||||
|
||||
|
||||
def test_get_all_data(bec_figure):
|
||||
def test_get_all_data(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1 = w1.add_curve_custom(
|
||||
@@ -373,7 +388,8 @@ def test_get_all_data(bec_figure):
|
||||
}
|
||||
|
||||
|
||||
def test_curve_add_by_config(bec_figure):
|
||||
def test_curve_add_by_config(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1_config_input = {
|
||||
@@ -413,7 +429,8 @@ def test_curve_add_by_config(bec_figure):
|
||||
assert c1.get_config(False) == CurveConfig(**c1_config_input)
|
||||
|
||||
|
||||
def test_scan_update(bec_figure, qtbot):
|
||||
def test_scan_update(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="bpm4i")
|
||||
@@ -447,7 +464,8 @@ def test_scan_update(bec_figure, qtbot):
|
||||
assert c1.get_data() == ([10], [5])
|
||||
|
||||
|
||||
def test_scan_history_with_val_access(bec_figure, qtbot):
|
||||
def test_scan_history_with_val_access(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
w1.plot(x_name="samx", y_name="bpm4i")
|
||||
@@ -472,7 +490,8 @@ def test_scan_history_with_val_access(bec_figure, qtbot):
|
||||
assert np.array_equal(y_data, [4, 5, 6])
|
||||
|
||||
|
||||
def test_scatter_2d_update(bec_figure, qtbot):
|
||||
def test_scatter_2d_update(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
c1 = w1.add_curve_bec(x_name="samx", y_name="samx", z_name="bpm4i")
|
||||
@@ -512,7 +531,8 @@ def test_scatter_2d_update(bec_figure, qtbot):
|
||||
assert colors == expected_z_colors
|
||||
|
||||
|
||||
def test_waveform_single_arg_inputs(bec_figure, qtbot):
|
||||
def test_waveform_single_arg_inputs(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
|
||||
w1.plot("bpm4i")
|
||||
@@ -544,7 +564,8 @@ def test_waveform_single_arg_inputs(bec_figure, qtbot):
|
||||
assert np.array_equal(w1._curves_data["custom"]["np_ndarray 2D"].get_data(), data_array_2D.T)
|
||||
|
||||
|
||||
def test_waveform_set_x_sync(bec_figure, qtbot):
|
||||
def test_waveform_set_x_sync(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot()
|
||||
custom_label = "custom_label"
|
||||
w1.plot("bpm4i")
|
||||
@@ -601,7 +622,8 @@ def test_waveform_set_x_sync(bec_figure, qtbot):
|
||||
assert w1.plot_item.getAxis("bottom").labelText == custom_label + " [timestamp]"
|
||||
|
||||
|
||||
def test_waveform_async_data_update(bec_figure, qtbot):
|
||||
def test_waveform_async_data_update(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot("async_device")
|
||||
custom_label = "custom_label"
|
||||
w1.set_x_label(custom_label)
|
||||
@@ -647,7 +669,8 @@ def test_waveform_async_data_update(bec_figure, qtbot):
|
||||
assert w1.plot_item.getAxis("bottom").labelText == custom_label + " [best_effort]"
|
||||
|
||||
|
||||
def test_waveform_set_x_async(bec_figure, qtbot):
|
||||
def test_waveform_set_x_async(qtbot, mocked_client):
|
||||
bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
|
||||
w1 = bec_figure.plot("async_device")
|
||||
custom_label = "custom_label"
|
||||
w1.set_x_label(custom_label)
|
||||
|
||||
@@ -14,7 +14,6 @@ def waveform_widget(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -12,8 +12,6 @@ def website_widget(qtbot, mocked_client):
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.page().deleteLater()
|
||||
qtbot.wait(1000)
|
||||
|
||||
|
||||
def test_website_widget_set_url(website_widget):
|
||||
|
||||
Reference in New Issue
Block a user