bec-widgets 0.92.0__py3-none-any.whl → 0.92.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
.gitlab-ci.yml CHANGED
@@ -43,13 +43,20 @@ stages:
43
43
  - export QTWEBENGINE_DISABLE_SANDBOX=1
44
44
 
45
45
  .clone-repos: &clone-repos
46
+ - echo -e "\033[35;1m Using branch $BEC_CORE_BRANCH of BEC CORE \033[0;m";
46
47
  - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
48
+ - echo -e "\033[35;1m Using branch $OPHYD_DEVICES_BRANCH of OPHYD_DEVICES \033[0;m";
47
49
  - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
48
50
  - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
49
51
 
52
+ .install-repos: &install-repos
53
+ - pip install -e ./ophyd_devices
54
+ - pip install -e ./bec/bec_lib[dev]
55
+ - pip install -e ./bec/bec_ipython_client
56
+
50
57
  .install-os-packages: &install-os-packages
51
58
  - apt-get update
52
- - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
59
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3 xvfb
53
60
  - *install-qt-webengine-deps
54
61
 
55
62
  before_script:
@@ -131,8 +138,7 @@ tests:
131
138
  script:
132
139
  - *clone-repos
133
140
  - *install-os-packages
134
- - pip install -e ./bec/bec_lib[dev]
135
- - pip install -e ./bec/bec_ipython_client
141
+ - *install-repos
136
142
  - pip install -e .[dev,pyqt6]
137
143
  - coverage run --source=./bec_widgets -m pytest -v --junitxml=report.xml --random-order --full-trace ./tests/unit_tests
138
144
  - coverage report
@@ -169,8 +175,7 @@ test-matrix:
169
175
  script:
170
176
  - *clone-repos
171
177
  - *install-os-packages
172
- - pip install -e ./bec/bec_lib[dev]
173
- - pip install -e ./bec/bec_ipython_client
178
+ - *install-repos
174
179
  - pip install -e .[dev,$QT_PCKG]
175
180
  - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
176
181
  allow_failure: true
@@ -195,10 +200,9 @@ end-2-end-conda:
195
200
 
196
201
  - cd ./bec
197
202
  - source ./bin/install_bec_dev.sh -t
198
-
199
- - pip install -e ./bec_lib[dev]
200
- - pip install -e ./bec_ipython_client[dev]
201
203
  - cd ../
204
+ - pip install -e ./ophyd_devices
205
+
202
206
  - pip install -e .[dev,pyqt6]
203
207
  - cd ./tests/end-2-end
204
208
  - pytest -v --start-servers --flush-redis --random-order
CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.92.1 (2024-07-28)
4
+
5
+ ### Build
6
+
7
+ * build(ci): install ophyd_devices in editable mode for pipelines ([`06205e0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/06205e07903d93accf40abab153f440059f236ed))
8
+
9
+ ### Fix
10
+
11
+ * fix: use SafeSlot instead of Slot ([`bc1e239`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bc1e23944cc0e5a861e3d0b4dc5b4ac6292d5269))
12
+
13
+ * fix: linting ([`a3fe205`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a3fe20500ae2ac03dcde07432f7e21ce5262ce46))
14
+
15
+ * fix: always add a QApplication for tests ([`61a4e32`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/61a4e32deb337ed27f2f43358b88b7266413b58e))
16
+
17
+ * fix: add xvfb to draw offscreen ([`3d681f7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/3d681f77e144e74138fc5fa65630004d7c166878))
18
+
19
+ * fix: reset ErrorPopup singleton between tests ([`5a9ccfd`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5a9ccfd1f6d2aacd5d86c1a34f74163b272d1ae4))
20
+
21
+ * fix: metaclass + QObject segfaults PyQt(cpp bindings) ([`fc57b7a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fc57b7a1262031a2df9e6a99493db87e766b779a))
22
+
23
+ ### Refactor
24
+
25
+ * refactor: renamed DeviceMonitor2DMessage ([`4be6fd6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4be6fd6b83ea1048f16310f7d2bbe777b13b245e))
26
+
27
+ * refactor: rename device_monitor to device_monitor_2d ([`714e1e1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/714e1e139e0033d2725fefb636c419ca137a68c6))
28
+
3
29
  ## v0.92.0 (2024-07-24)
4
30
 
5
31
  ### Feature
@@ -102,18 +128,6 @@ This reverts commit 3798714369adf4023f833b7749d2f46a0ec74eee ([`fd6ae91`](https:
102
128
 
103
129
  * feat(waveform_widget): dap parameter window ([`1e551d6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1e551d6e9696f79ea2e0a179d13a4fc6c2a128b2))
104
130
 
105
- * feat(waveform): export to matplotlib window of current scene ([`8d93405`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8d9340539967b06b1e15f21a2106a39d5c740f31))
106
-
107
- * feat(figure): export dialog can be launched from CLI and from toolbar ([`6ff6111`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6ff611109153b9412dce37c527b19e839d99bba7))
108
-
109
- * feat(waveform_widget): added error handle utility ([`a8ff1d4`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a8ff1d4cd09cae5eaeb4bd0ea90fdd102e32f3a3))
110
-
111
- * feat(curve_dialog): add DAP functionality ([`e830565`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e8305652fde384da037242cf8f7e3606f22bcfb6))
112
-
113
- * feat(curve_dialog): curves can be added ([`c926a75`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c926a75a7927d672c044ea8f68771209ae5accc6))
114
-
115
- * feat(waveform_widget): BECWaveformWidget toolbar added import/export config ([`fa9b171`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fa9b17191ddbb4043a658dae9aa0801e1dc22b84))
116
-
117
131
  ### Fix
118
132
 
119
133
  * fix(waveform_widget): plot API unified with BECFigure ([`2c8764a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2c8764a27de89b39b717032b58465e120ec57fbc))
@@ -126,22 +140,6 @@ This reverts commit 3798714369adf4023f833b7749d2f46a0ec74eee ([`fd6ae91`](https:
126
140
 
127
141
  * fix(waveform_widget): use @SafeSlot decorator for automatic error message ([`8e588d7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8e588d79c86e950f6915e89c08fa9415c4bd8033))
128
142
 
129
- * fix(waveform): colormaps of curves can be changed and normalised
130
-
131
- feat(waveform): colormap can be changed from curve dialog
132
-
133
- fix(curve_dialog): default dialog parameters fixed
134
-
135
- curve Dialog colormap WIP ([`33495cf`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/33495cfe03b363f18db61d8af2983f49027b7a43))
136
-
137
- * fix(waveform_widget): adapted for changes from improved scan logic from waveform widget ([`8ac35d7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8ac35d7280b1ff007c10612228d163cc0c5d1a99))
138
-
139
- ### Refactor
140
-
141
- * refactor(icons): icons moved to the assets directory ([`a8b6ef2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a8b6ef20cccae87515b10f054d0ed5b10e152769))
142
-
143
- * refactor(waveform_widget): removed PYSIDE6 check ([`47fcb9e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/47fcb9ebfe35ae600cced95a1edc68f6f6e37a04))
144
-
145
143
  ### Test
146
144
 
147
145
  * test(waveform_widget): test added ([`8d764e2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8d764e2d46a1e017dadc3c4630648c1ca708afc2))
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.92.0
3
+ Version: 0.92.1
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -1,12 +1,13 @@
1
1
  # Copyright (C) 2022 The Qt Company Ltd.
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
 
4
- from qtpy.QtCore import Slot
5
4
  from qtpy.QtDesigner import QExtensionFactory, QPyDesignerTaskMenuExtension
6
5
  from qtpy.QtGui import QAction
7
6
  from qtpy.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout
8
7
  from tictactoe import TicTacToe
9
8
 
9
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
10
+
10
11
 
11
12
  class TicTacToeDialog(QDialog): # pragma: no cover
12
13
  def __init__(self, parent):
@@ -6,7 +6,7 @@ from qtpy.QtCore import QObject, Qt, Signal, Slot
6
6
  from qtpy.QtWidgets import QApplication, QMessageBox, QPushButton, QVBoxLayout, QWidget
7
7
 
8
8
 
9
- def SafeSlot(*slot_args, **slot_kwargs):
9
+ def SafeSlot(*slot_args, **slot_kwargs): # pylint: disable=invalid-name
10
10
  """Function with args, acting like a decorator, applying "error_managed" decorator + Qt Slot
11
11
  to the passed function, to display errors instead of potentially raising an exception
12
12
 
@@ -34,10 +34,7 @@ class WarningPopupUtility(QObject):
34
34
  Utility class to show warning popups in the application.
35
35
  """
36
36
 
37
- def __init__(self, parent=None):
38
- super().__init__(parent)
39
-
40
- @Slot(str, str, str, QWidget)
37
+ @SafeSlot(str, str, str, QWidget)
41
38
  def show_warning_message(self, title, message, detailed_text, widget):
42
39
  msg = QMessageBox(widget)
43
40
  msg.setIcon(QMessageBox.Warning)
@@ -60,7 +57,10 @@ class WarningPopupUtility(QObject):
60
57
  self.show_warning_message(title, message, detailed_text, widget)
61
58
 
62
59
 
63
- class ErrorPopupUtility(QObject):
60
+ _popup_utility_instance = None
61
+
62
+
63
+ class _ErrorPopupUtility(QObject):
64
64
  """
65
65
  Utility class to manage error popups in the application to show error messages to the users.
66
66
  This class is singleton and the error popup can be enabled or disabled globally or attach to widget methods with decorator @error_managed.
@@ -68,24 +68,14 @@ class ErrorPopupUtility(QObject):
68
68
 
69
69
  error_occurred = Signal(str, str, QWidget)
70
70
 
71
- _instance = None
72
- _initialized = False
73
-
74
- def __new__(cls, *args, **kwargs):
75
- if cls._instance is None:
76
- cls._instance = super(ErrorPopupUtility, cls).__new__(cls)
77
- cls._instance._initialized = False
78
- return cls._instance
79
-
80
71
  def __init__(self, parent=None):
81
- if not self._initialized:
82
- super().__init__(parent=parent)
83
- self.error_occurred.connect(self.show_error_message)
84
- self.enable_error_popup = False
85
- self._initialized = True
86
- sys.excepthook = self.custom_exception_hook
87
-
88
- @Slot(str, str, QWidget)
72
+ super().__init__(parent=parent)
73
+ self.error_occurred.connect(self.show_error_message)
74
+ self.enable_error_popup = False
75
+ self._initialized = True
76
+ sys.excepthook = self.custom_exception_hook
77
+
78
+ @SafeSlot(str, str, QWidget)
89
79
  def show_error_message(self, title, message, widget):
90
80
  detailed_text = self.format_traceback(message)
91
81
  error_message = self.parse_error_message(detailed_text)
@@ -157,13 +147,12 @@ class ErrorPopupUtility(QObject):
157
147
  """
158
148
  self.enable_error_popup = bool(state)
159
149
 
160
- @classmethod
161
- def reset_singleton(cls):
162
- """
163
- Reset the singleton instance.
164
- """
165
- cls._instance = None
166
- cls._initialized = False
150
+
151
+ def ErrorPopupUtility():
152
+ global _popup_utility_instance
153
+ if not _popup_utility_instance:
154
+ _popup_utility_instance = _ErrorPopupUtility()
155
+ return _popup_utility_instance
167
156
 
168
157
 
169
158
  class ExampleWidget(QWidget): # pragma: no cover
@@ -1,6 +1,7 @@
1
- from qtpy.QtCore import Slot
2
1
  from qtpy.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QPushButton, QVBoxLayout, QWidget
3
2
 
3
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
4
+
4
5
 
5
6
  class SettingWidget(QWidget):
6
7
  """
@@ -10,11 +10,11 @@ import yaml
10
10
  from bec_lib.utils.import_utils import lazy_import_from
11
11
  from pydantic import BaseModel, Field, field_validator
12
12
  from qtpy.QtCore import QObject, QRunnable, QThreadPool, Signal
13
- from qtpy.QtCore import Slot as pyqtSlot
14
13
  from qtpy.QtWidgets import QApplication
15
14
 
16
15
  from bec_widgets.cli.rpc_register import RPCRegister
17
16
  from bec_widgets.qt_utils.error_popups import ErrorPopupUtility
17
+ from bec_widgets.qt_utils.error_popups import SafeSlot as pyqtSlot
18
18
  from bec_widgets.utils.yaml_dialog import load_yaml, load_yaml_gui, save_yaml, save_yaml_gui
19
19
 
20
20
  BECDispatcher = lazy_import_from("bec_widgets.utils.bec_dispatcher", ("BECDispatcher",))
@@ -18,10 +18,11 @@ import pyte
18
18
  from qtpy import QtCore, QtGui, QtWidgets
19
19
  from qtpy.QtCore import QSize, QSocketNotifier, Qt
20
20
  from qtpy.QtCore import Signal as pyqtSignal
21
- from qtpy.QtCore import Slot as pyqtSlot
22
21
  from qtpy.QtGui import QClipboard, QTextCursor
23
22
  from qtpy.QtWidgets import QApplication, QHBoxLayout, QScrollBar, QSizePolicy
24
23
 
24
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
25
+
25
26
  ansi_colors = {
26
27
  "black": "#000000",
27
28
  "red": "#CD0000",
@@ -289,7 +290,7 @@ class _TerminalWidget(QtWidgets.QPlainTextEdit):
289
290
  old["value"] = value
290
291
  self.dataReady(self.backend.screen, reset_scroll=False)
291
292
 
292
- @pyqtSlot(object)
293
+ @Slot(object)
293
294
  def keyPressEvent(self, event):
294
295
  """
295
296
  Redirect all keystrokes to the terminal process.
@@ -164,7 +164,7 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
164
164
  def __getitem__(self, key: tuple | str):
165
165
  if isinstance(key, tuple) and len(key) == 2:
166
166
  return self.axes(*key)
167
- elif isinstance(key, str):
167
+ if isinstance(key, str):
168
168
  widget = self._widgets.get(key)
169
169
  if widget is None:
170
170
  raise KeyError(f"No widget with ID {key}")
@@ -185,7 +185,7 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
185
185
  self.change_theme(self.config.theme)
186
186
 
187
187
  # widget_config has to be reset for not have each widget config twice when added to the figure
188
- widget_configs = [config for config in self.config.widgets.values()]
188
+ widget_configs = list(self.config.widgets.values())
189
189
  self.config.widgets = {}
190
190
  for widget_config in widget_configs:
191
191
  getattr(self, self.widget_method_map[widget_config.widget_class])(
@@ -233,8 +233,8 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
233
233
  """Export the plot widget."""
234
234
  try:
235
235
  plot_item = self.widget_list[0]
236
- except:
237
- raise ValueError("No plot widget available to export.")
236
+ except Exception as exc:
237
+ raise ValueError("No plot widget available to export.") from exc
238
238
 
239
239
  scene = plot_item.scene()
240
240
  scene.contextMenuItem = plot_item
@@ -529,12 +529,12 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
529
529
  if row is not None and col is not None:
530
530
  if self.getItem(row, col):
531
531
  raise ValueError(f"Position at row {row} and column {col} is already occupied.")
532
- else:
533
- widget.config.row = row
534
- widget.config.col = col
535
532
 
536
- # Add widget to the figure
537
- self.addItem(widget, row=row, col=col)
533
+ widget.config.row = row
534
+ widget.config.col = col
535
+
536
+ # Add widget to the figure
537
+ self.addItem(widget, row=row, col=col)
538
538
  else:
539
539
  row, col = self._find_next_empty_position()
540
540
  widget.config.row = row
@@ -721,7 +721,7 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
721
721
 
722
722
  # Populate the new grid with widgets' IDs
723
723
  current_idx = 0
724
- for widget_id, widget in self._widgets.items():
724
+ for widget_id in self._widgets:
725
725
  row = current_idx // len(new_grid[0])
726
726
  col = current_idx % len(new_grid[0])
727
727
  new_grid[row][col] = widget_id
@@ -1,8 +1,8 @@
1
1
  import os
2
2
 
3
- from qtpy.QtCore import Slot
4
3
  from qtpy.QtWidgets import QVBoxLayout
5
4
 
5
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
6
6
  from bec_widgets.qt_utils.settings_dialog import SettingWidget
7
7
  from bec_widgets.utils import UILoader
8
8
  from bec_widgets.utils.widget_io import WidgetIO
@@ -7,9 +7,9 @@ import numpy as np
7
7
  from bec_lib.endpoints import MessageEndpoints
8
8
  from pydantic import BaseModel, Field, ValidationError
9
9
  from qtpy.QtCore import QThread
10
- from qtpy.QtCore import Slot as pyqtSlot
11
10
  from qtpy.QtWidgets import QWidget
12
11
 
12
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
13
13
  from bec_widgets.utils import EntryValidator
14
14
  from bec_widgets.widgets.figure.plots.image.image_item import BECImageItem, ImageItemConfig
15
15
  from bec_widgets.widgets.figure.plots.image.image_processor import (
@@ -247,7 +247,7 @@ class BECImageShow(BECPlotBase):
247
247
  Returns:
248
248
  BECImageItem: The image item.
249
249
  """
250
- image_source = "device_monitor"
250
+ image_source = "device_monitor_2d"
251
251
 
252
252
  image_exits = self._check_image_id(monitor, self._images)
253
253
  if image_exits:
@@ -287,7 +287,7 @@ class BECImageShow(BECPlotBase):
287
287
  **kwargs,
288
288
  ):
289
289
  image_source = "custom"
290
- # image_source = "device_monitor"
290
+ # image_source = "device_monitor_2d"
291
291
 
292
292
  image_exits = self._check_image_id(name, self._images)
293
293
  if image_exits:
@@ -500,7 +500,7 @@ class BECImageShow(BECPlotBase):
500
500
  self.update_image(device, data)
501
501
  self.update_vrange(device, self.processor.config.stats)
502
502
 
503
- @pyqtSlot(dict)
503
+ @Slot(dict)
504
504
  def on_image_update(self, msg: dict):
505
505
  """
506
506
  Update the image of the device monitor from bec.
@@ -510,11 +510,11 @@ class BECImageShow(BECPlotBase):
510
510
  """
511
511
  data = msg["data"]
512
512
  device = msg["device"]
513
- image = self._images["device_monitor"][device]
513
+ image = self._images["device_monitor_2d"][device]
514
514
  image.raw_data = data
515
515
  self.process_image(device, image, data)
516
516
 
517
- @pyqtSlot(str, np.ndarray)
517
+ @Slot(str, np.ndarray)
518
518
  def update_image(self, device: str, data: np.ndarray):
519
519
  """
520
520
  Update the image of the device monitor.
@@ -523,10 +523,10 @@ class BECImageShow(BECPlotBase):
523
523
  device(str): The name of the device.
524
524
  data(np.ndarray): The data to be updated.
525
525
  """
526
- image_to_update = self._images["device_monitor"][device]
526
+ image_to_update = self._images["device_monitor_2d"][device]
527
527
  image_to_update.updateImage(data, autoLevels=image_to_update.config.autorange)
528
528
 
529
- @pyqtSlot(str, ImageStats)
529
+ @Slot(str, ImageStats)
530
530
  def update_vrange(self, device: str, stats: ImageStats):
531
531
  """
532
532
  Update the scaling of the image.
@@ -534,7 +534,7 @@ class BECImageShow(BECPlotBase):
534
534
  Args:
535
535
  stats(ImageStats): The statistics of the image.
536
536
  """
537
- image_to_update = self._images["device_monitor"][device]
537
+ image_to_update = self._images["device_monitor_2d"][device]
538
538
  if image_to_update.config.autorange:
539
539
  image_to_update.auto_update_vrange(stats)
540
540
 
@@ -547,7 +547,7 @@ class BECImageShow(BECPlotBase):
547
547
  data = image.raw_data
548
548
  self.process_image(image_id, image, data)
549
549
 
550
- def _connect_device_monitor(self, monitor: str):
550
+ def _connect_device_monitor_2d(self, monitor: str):
551
551
  """
552
552
  Connect to the device monitor.
553
553
 
@@ -561,13 +561,13 @@ class BECImageShow(BECPlotBase):
561
561
  previous_monitor = None
562
562
  if previous_monitor and image_item.connected is True:
563
563
  self.bec_dispatcher.disconnect_slot(
564
- self.on_image_update, MessageEndpoints.device_monitor(previous_monitor)
564
+ self.on_image_update, MessageEndpoints.device_monitor_2d(previous_monitor)
565
565
  )
566
566
  image_item.connected = False
567
567
  if monitor and image_item.connected is False:
568
568
  self.entry_validator.validate_monitor(monitor)
569
569
  self.bec_dispatcher.connect_slot(
570
- self.on_image_update, MessageEndpoints.device_monitor(monitor)
570
+ self.on_image_update, MessageEndpoints.device_monitor_2d(monitor)
571
571
  )
572
572
  image_item.set_monitor(monitor)
573
573
  image_item.connected = True
@@ -581,8 +581,8 @@ class BECImageShow(BECPlotBase):
581
581
  if self.single_image is True and len(self.images) > 0:
582
582
  self.remove_image(0)
583
583
  self._images[source][name] = image
584
- if source == "device_monitor":
585
- self._connect_device_monitor(config.monitor)
584
+ if source == "device_monitor_2d":
585
+ self._connect_device_monitor_2d(config.monitor)
586
586
  self.config.images[name] = config
587
587
  if data is not None:
588
588
  image.setImage(data)
@@ -668,15 +668,15 @@ class BECImageShow(BECPlotBase):
668
668
  image = self.find_image_by_monitor(image_id)
669
669
  if image:
670
670
  self.bec_dispatcher.disconnect_slot(
671
- self.on_image_update, MessageEndpoints.device_monitor(image.config.monitor)
671
+ self.on_image_update, MessageEndpoints.device_monitor_2d(image.config.monitor)
672
672
  )
673
673
 
674
674
  def cleanup(self):
675
675
  """
676
676
  Clean up the widget.
677
677
  """
678
- for monitor in self._images["device_monitor"]:
678
+ for monitor in self._images["device_monitor_2d"]:
679
679
  self.bec_dispatcher.disconnect_slot(
680
- self.on_image_update, MessageEndpoints.device_monitor(monitor)
680
+ self.on_image_update, MessageEndpoints.device_monitor_2d(monitor)
681
681
  )
682
682
  self.images.clear()
@@ -10,9 +10,9 @@ from pydantic import Field, ValidationError, field_validator
10
10
  from pydantic_core import PydanticCustomError
11
11
  from qtpy import QtCore, QtGui
12
12
  from qtpy.QtCore import Signal as pyqtSignal
13
- from qtpy.QtCore import Slot
14
13
  from qtpy.QtWidgets import QWidget
15
14
 
15
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
16
16
  from bec_widgets.utils import Colors, EntryValidator
17
17
  from bec_widgets.widgets.figure.plots.plot_base import BECPlotBase, SubplotConfig
18
18
  from bec_widgets.widgets.figure.plots.waveform.waveform import Signal, SignalData
@@ -444,7 +444,7 @@ class BECMotorMap(BECPlotBase):
444
444
  return None
445
445
 
446
446
  @Slot()
447
- def _update_plot(self):
447
+ def _update_plot(self, _=None):
448
448
  """Update the motor map plot."""
449
449
  # If the number of points exceeds max_points, delete the oldest points
450
450
  if len(self.database_buffer["x"]) > self.config.max_points:
@@ -11,9 +11,9 @@ from bec_lib.endpoints import MessageEndpoints
11
11
  from pydantic import Field, ValidationError, field_validator
12
12
  from pyqtgraph.exporters import MatplotlibExporter
13
13
  from qtpy.QtCore import Signal as pyqtSignal
14
- from qtpy.QtCore import Slot as pyqtSlot
15
14
  from qtpy.QtWidgets import QWidget
16
15
 
16
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
17
17
  from bec_widgets.utils import Colors, EntryValidator
18
18
  from bec_widgets.widgets.figure.plots.plot_base import BECPlotBase, SubplotConfig
19
19
  from bec_widgets.widgets.figure.plots.waveform.waveform_curve import (
@@ -391,7 +391,7 @@ class BECWaveform(BECPlotBase):
391
391
  self.async_signal_update.emit()
392
392
  self.scan_signal_update.emit()
393
393
 
394
- @pyqtSlot()
394
+ @Slot()
395
395
  def auto_range(self):
396
396
  self.plot_item.autoRange()
397
397
 
@@ -408,7 +408,7 @@ class BECWaveform(BECPlotBase):
408
408
  """
409
409
  self.plot_item.enableAutoRange(axis, enabled)
410
410
 
411
- @pyqtSlot()
411
+ @Slot()
412
412
  def auto_range(self):
413
413
  self.plot_item.autoRange()
414
414
 
@@ -642,7 +642,7 @@ class BECWaveform(BECPlotBase):
642
642
  self.refresh_dap()
643
643
  return curve
644
644
 
645
- @pyqtSlot()
645
+ @Slot()
646
646
  def get_dap_params(self) -> dict:
647
647
  """
648
648
  Get the DAP parameters of all DAP curves.
@@ -655,7 +655,7 @@ class BECWaveform(BECPlotBase):
655
655
  params[curve_id] = curve.dap_params
656
656
  return params
657
657
 
658
- @pyqtSlot()
658
+ @Slot()
659
659
  def get_dap_summary(self) -> dict:
660
660
  """
661
661
  Get the DAP summary of all DAP curves.
@@ -921,7 +921,7 @@ class BECWaveform(BECPlotBase):
921
921
  else:
922
922
  raise IndexError(f"Curve order {N} out of range.")
923
923
 
924
- @pyqtSlot(dict)
924
+ @Slot(dict)
925
925
  def on_scan_status(self, msg):
926
926
  """
927
927
  Handle the scan status message.
@@ -945,7 +945,7 @@ class BECWaveform(BECPlotBase):
945
945
  for curve_id, curve in self._curves_data["async"].items():
946
946
  self.setup_async(curve.config.signals.y.name)
947
947
 
948
- @pyqtSlot(dict, dict)
948
+ @Slot(dict, dict)
949
949
  def on_scan_segment(self, msg: dict, metadata: dict):
950
950
  """
951
951
  Handle new scan segments and saves data to a dictionary. Linked through bec_dispatcher.
@@ -1004,7 +1004,7 @@ class BECWaveform(BECPlotBase):
1004
1004
  self.update_dap, MessageEndpoints.dap_response(f"{new_scan_id}-{self.gui_id}")
1005
1005
  )
1006
1006
 
1007
- @pyqtSlot(str)
1007
+ @Slot(str)
1008
1008
  def setup_async(self, device: str):
1009
1009
  self.bec_dispatcher.disconnect_slot(
1010
1010
  self.on_async_readback, MessageEndpoints.device_async_readback(self.old_scan_id, device)
@@ -1020,8 +1020,8 @@ class BECWaveform(BECPlotBase):
1020
1020
  from_start=True,
1021
1021
  )
1022
1022
 
1023
- @pyqtSlot()
1024
- def refresh_dap(self):
1023
+ @Slot()
1024
+ def refresh_dap(self, _=None):
1025
1025
  """
1026
1026
  Refresh the DAP curves with the latest data from the DAP model MessageEndpoints.dap_response().
1027
1027
  """
@@ -1069,7 +1069,7 @@ class BECWaveform(BECPlotBase):
1069
1069
  )
1070
1070
  self.client.connector.set_and_publish(MessageEndpoints.dap_request(), msg)
1071
1071
 
1072
- @pyqtSlot(dict, dict)
1072
+ @Slot(dict, dict)
1073
1073
  def update_dap(self, msg, metadata):
1074
1074
  self.msg = msg
1075
1075
  scan_id, x_name, x_entry, y_name, y_entry = msg["dap_request"].content["config"]["args"]
@@ -1089,7 +1089,7 @@ class BECWaveform(BECPlotBase):
1089
1089
  self.dap_summary_update.emit(curve.dap_summary)
1090
1090
  break
1091
1091
 
1092
- @pyqtSlot(dict, dict)
1092
+ @Slot(dict, dict)
1093
1093
  def on_async_readback(self, msg, metadata):
1094
1094
  """
1095
1095
  Get async data readback.
@@ -1127,7 +1127,7 @@ class BECWaveform(BECPlotBase):
1127
1127
  else:
1128
1128
  curve.setData(data_plot)
1129
1129
 
1130
- @pyqtSlot()
1130
+ @Slot()
1131
1131
  def replot_async_curve(self):
1132
1132
  try:
1133
1133
  data = self.scan_item.async_data
@@ -1152,8 +1152,8 @@ class BECWaveform(BECPlotBase):
1152
1152
  else:
1153
1153
  curve.setData(data_x, data_y)
1154
1154
 
1155
- @pyqtSlot()
1156
- def _update_scan_curves(self):
1155
+ @Slot()
1156
+ def _update_scan_curves(self, _=None):
1157
1157
  """
1158
1158
  Update the scan curves with the data from the scan segment.
1159
1159
  """
@@ -1,8 +1,8 @@
1
1
  import os
2
2
 
3
- from qtpy.QtCore import Slot
4
3
  from qtpy.QtWidgets import QVBoxLayout
5
4
 
5
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
6
6
  from bec_widgets.qt_utils.settings_dialog import SettingWidget
7
7
  from bec_widgets.utils import UILoader
8
8
  from bec_widgets.utils.widget_io import WidgetIO
@@ -1,6 +1,6 @@
1
- from qtpy.QtCore import Slot
2
1
  from qtpy.QtWidgets import QPushButton
3
2
 
3
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
4
4
  from bec_widgets.utils.bec_widget import BECWidget
5
5
 
6
6
 
@@ -1,8 +1,8 @@
1
1
  import os
2
2
 
3
- from qtpy.QtCore import Slot
4
3
  from qtpy.QtWidgets import QDialog, QTreeWidgetItem, QVBoxLayout
5
4
 
5
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
6
6
  from bec_widgets.utils import UILoader
7
7
 
8
8
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.92.0
3
+ Version: 0.92.1
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -1,12 +1,12 @@
1
1
  .gitignore,sha256=cMQ1MLmnoR88aMCCJwUyfoTnufzl4-ckmHtlFUqHcT4,3253
2
- .gitlab-ci.yml,sha256=zvb4A6QI5lQTsdfI5nPPL-tUNfcrz__SQjxW03QZ5Ek,8204
2
+ .gitlab-ci.yml,sha256=BtKhZI3dhK09En1BfpglYi-ZJwG6ZdC-iJr7kXFVfCg,8346
3
3
  .pylintrc,sha256=eeY8YwSI74oFfq6IYIbCqnx3Vk8ZncKaatv96n_Y8Rs,18544
4
4
  .readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
5
- CHANGELOG.md,sha256=pacucbtN9ZWGj-nEtdxOQUgTWECb9jgd67zZTrIHj2M,7709
5
+ CHANGELOG.md,sha256=-vNTquNVId-xmL688niPOZe0ChDNb_XkdXxmdcagWQY,7294
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=VnZc1usRRpdjc7CFNYGi63h-mkTI7pG7k1qirWunV4k,1308
7
+ PKG-INFO,sha256=KBSOFzJA5iV_W_53ntYovfFeG4uPOv1SDfF-qCArFkY,1308
8
8
  README.md,sha256=Od69x-RS85Hph0-WwWACwal4yUd67XkEn4APEfHhHFw,2649
9
- pyproject.toml,sha256=xcRdrwd813IfFf3F3mtUNLqlDSDwulmLOwRvUcVI2c0,2357
9
+ pyproject.toml,sha256=qkEuEnhJGRrMzSer_iXKyN8Minb6n-OQp67Do3M2bGE,2357
10
10
  .git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
11
11
  .gitlab/issue_templates/bug_report_template.md,sha256=gAuyEwl7XlnebBrkiJ9AqffSNOywmr8vygUFWKTuQeI,386
12
12
  .gitlab/issue_templates/documentation_update_template.md,sha256=FHLdb3TS_D9aL4CYZCjyXSulbaW5mrN2CmwTaeLPbNw,860
@@ -100,13 +100,13 @@ bec_widgets/examples/plugin_example_pyside/registertictactoe.py,sha256=VNFkHc5Sc
100
100
  bec_widgets/examples/plugin_example_pyside/taskmenuextension.pyproject,sha256=O_PSMFJlXxQuf55gIOfkpfZIZGpX8W1SfUVZ-mvtI_E,119
101
101
  bec_widgets/examples/plugin_example_pyside/tictactoe.py,sha256=byR7mTiIXFaA9igPTH04pzm0yfikNB5KgISwvNiRPd8,4940
102
102
  bec_widgets/examples/plugin_example_pyside/tictactoeplugin.py,sha256=tTCUKQX5BM4MTC2NSbbit3kf5CRBtJxTx7SqjA564rY,1918
103
- bec_widgets/examples/plugin_example_pyside/tictactoetaskmenu.py,sha256=LNwplI6deUdKY6FOhUuWBanotxk9asF2G-6k7lFfA8Y,2301
103
+ bec_widgets/examples/plugin_example_pyside/tictactoetaskmenu.py,sha256=iU0L6HE3S19XQo-2rASyrJy5SyIJnTAnW_yHP6w4Jz4,2336
104
104
  bec_widgets/qt_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
- bec_widgets/qt_utils/error_popups.py,sha256=WAN3Qtccy9Yww29kZ3HbLt9VyipgrIamJ6y4PhGTe3I,7983
106
- bec_widgets/qt_utils/settings_dialog.py,sha256=rR_Zk4RGTnI4dz5OEzCc13lVpxlOKuwOf4_7wqXSbRw,3373
105
+ bec_widgets/qt_utils/error_popups.py,sha256=y9gKKWaafp468ioHr96nBhf02ZpEgjDc-BAVOTWh-e8,7680
106
+ bec_widgets/qt_utils/settings_dialog.py,sha256=8eGDV3XCYCUXLougnRM_k1JnYQVG23HfmjrbhRzlsRc,3408
107
107
  bec_widgets/qt_utils/toolbar.py,sha256=89WddOXPePby2CICUumdN_K_3DBgZPCR8HWUJAwrhDU,6503
108
108
  bec_widgets/utils/__init__.py,sha256=1930ji1Jj6dVuY81Wd2kYBhHYNV-2R0bN_L4o9zBj1U,533
109
- bec_widgets/utils/bec_connector.py,sha256=UK0GIWgcC_JTwgKCOmmuXnQvSwD3wiPsJQw6NBW3p74,9961
109
+ bec_widgets/utils/bec_connector.py,sha256=SivHKXVyNVqeu3kCXYEPpbleTVw8g1cW0FKq1QrQgco,9987
110
110
  bec_widgets/utils/bec_designer.py,sha256=ak3G8FdojUPjVBBwdPXw7tN5P2Uxr-SSoQt394jXeAA,4308
111
111
  bec_widgets/utils/bec_dispatcher.py,sha256=fhI7_X0kSZCtXyR55Qn-w7BfNdk2Roc1Tyx0bx3bjoE,6195
112
112
  bec_widgets/utils/bec_table.py,sha256=nA2b8ukSeUfquFMAxGrUVOqdrzMoDYD6O_4EYbOG2zk,717
@@ -151,7 +151,7 @@ bec_widgets/widgets/colormap_selector/colormap_selector.py,sha256=4BqV11XMZVmcwz
151
151
  bec_widgets/widgets/colormap_selector/colormap_selector.pyproject,sha256=lHl9qmlMCB6BKB2orqctKwLcKK3Swc0THsyr-5O_vXM,35
152
152
  bec_widgets/widgets/colormap_selector/colormap_selector_plugin.py,sha256=NWTldO9XMyyOVL0No-Bmr-tvWrinmU7LkDxB5LkIQtA,1416
153
153
  bec_widgets/widgets/colormap_selector/register_colormap_selector.py,sha256=bfw7RWmTmMLTLxGT-izSwcGtxGLKvL3jdivJw2z8oN4,512
154
- bec_widgets/widgets/console/console.py,sha256=IW1OerycmS-cm8CKGFig44Qye8mxsmVcKvLHAc3lXco,17845
154
+ bec_widgets/widgets/console/console.py,sha256=NG0cBuqqPX4hC-sHhk_UEkT-nHhhN9Y7karJITPLzyo,17864
155
155
  bec_widgets/widgets/device_box/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
156
  bec_widgets/widgets/device_box/device_box.py,sha256=2hWCbDaBvYnWK4-HDqeYetzb5KR4DBk7UPQJMLhT4w0,6929
157
157
  bec_widgets/widgets/device_box/device_box.pyproject,sha256=jtwvhaySJRdnuV99mEZT3htmWKVLphFeetEW4al7s-o,28
@@ -175,19 +175,19 @@ bec_widgets/widgets/dock/dock_area.pyproject,sha256=URW0UrDXCnkzk80rbQmUMgF6Uqay
175
175
  bec_widgets/widgets/dock/dock_area_plugin.py,sha256=oG2zDxUA1YLvSBoFVeFVkz4HIWLruAwOsCZ00H2Z70A,1345
176
176
  bec_widgets/widgets/dock/register_dock_area.py,sha256=Yqd1mq6CcHwlxHZxX5EHKONy4P44nMm8pso-4X0tvJI,464
177
177
  bec_widgets/widgets/figure/__init__.py,sha256=3hGx_KOV7QHCYAV06aNuUgKq4QIYCjUTad-DrwkUaBM,44
178
- bec_widgets/widgets/figure/figure.py,sha256=ei--FpbgRgqlx_G6wrWitr1DAnSzu8dcxUi-xyn7YFk,28726
178
+ bec_widgets/widgets/figure/figure.py,sha256=6bYpsYQ2udJy_51mmpM6zKlOIsf_lxlKF31coXGUA0I,28684
179
179
  bec_widgets/widgets/figure/plots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
180
- bec_widgets/widgets/figure/plots/axis_settings.py,sha256=_z20SrMu5iRM0eqhQjsCV1MDOY80hN2dqtvkeofXs0w,3510
180
+ bec_widgets/widgets/figure/plots/axis_settings.py,sha256=QxRpQwgfBr1H0HTjfOpiXi_-n8I0BaZhS8LRXNeVfFg,3544
181
181
  bec_widgets/widgets/figure/plots/axis_settings.ui,sha256=a2qIuK9lyi9HCyrSvPr6wxzmm1FymaWcpmyOhMIiFt8,11013
182
182
  bec_widgets/widgets/figure/plots/plot_base.py,sha256=AxzH2J-bLngxlWcgWWgNpLhIQxQzFz-H6yLf5Dou93Y,10921
183
183
  bec_widgets/widgets/figure/plots/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
184
- bec_widgets/widgets/figure/plots/image/image.py,sha256=xxowHo9LctrX3BQoVo9hWvj9FjALa0FIicFF39zZ3B8,24334
184
+ bec_widgets/widgets/figure/plots/image/image.py,sha256=PCuZyTpPvIgfbAzOydV0op_GM3a8hXZoAw2Ux5z4ymA,24383
185
185
  bec_widgets/widgets/figure/plots/image/image_item.py,sha256=RljjbkqJEr2cKDlqj1j5GQ1h89jpqOV-OpFz1TbED8I,10937
186
186
  bec_widgets/widgets/figure/plots/image/image_processor.py,sha256=GeTtWjbldy6VejMwPGQgM-o3d6bmLglCjdoktu19xfA,5262
187
187
  bec_widgets/widgets/figure/plots/motor_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
188
- bec_widgets/widgets/figure/plots/motor_map/motor_map.py,sha256=IjCwVNb9DlujIDF9rlI7fOAM7udKpt0wL5hAGo2-MUw,18202
188
+ bec_widgets/widgets/figure/plots/motor_map/motor_map.py,sha256=uZKWtXcK9MU-_PleN1xKIyTCUuCHrkbqtbY9sVMgDlw,18244
189
189
  bec_widgets/widgets/figure/plots/waveform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
190
- bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=HRU3d6nhr6DnfDc2N4VTTSABk9veTnnsBOnfc1UbamQ,51720
190
+ bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=EjKwD_pOhZYmXU2M_LdIv9A9cbVYxR1Y9lH0tbMNuJE,51710
191
191
  bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=ZwRxSfPHbMWEvgUC-mL2orpZvtxR-DcrYAFikkdWEzk,8654
192
192
  bec_widgets/widgets/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
193
193
  bec_widgets/widgets/image/bec_image_widget.pyproject,sha256=PHisdBo5_5UCApd27GkizzqgfdjsDx2bFZa_p9LiSW8,30
@@ -202,7 +202,7 @@ bec_widgets/widgets/motor_map/bec_motor_map_widget_plugin.py,sha256=V6iN82E8Za8B
202
202
  bec_widgets/widgets/motor_map/motor_map_widget.py,sha256=URcysThbJKGsCZUqQm2lCtVn5FG8t4kT7DaN5EJUexg,7555
203
203
  bec_widgets/widgets/motor_map/register_bec_motor_map_widget.py,sha256=qRG8PtWGjso0pWbvj_DXKnbUfmQzfGqPSrnAozXfM7o,492
204
204
  bec_widgets/widgets/motor_map/motor_map_dialog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
205
- bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.py,sha256=terJ5NHRzAsiUwdqg-hTbkQ5gadnRT0Ol0_Fm66kPF4,2011
205
+ bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.py,sha256=6mqprDyIwd09swpEpDRg9jwCJtR9MNCXW_Mx2nunCN8,2045
206
206
  bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.ui,sha256=nv5vPftt6vcIl60OOZLRvwD29rdHVWOoGmz168BnwKw,2685
207
207
  bec_widgets/widgets/position_indicator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
208
208
  bec_widgets/widgets/position_indicator/position_indicator.py,sha256=QVlWvs_RvEJe5IMxGYCpi-CXYF7vFeMqEMFCs6u5NGc,2020
@@ -228,7 +228,7 @@ bec_widgets/widgets/spinner/spinner_widget.pyproject,sha256=zzLajGB3DTgVnrSqMey2
228
228
  bec_widgets/widgets/spinner/spinner_widget_plugin.py,sha256=22b3n0ZGBDI44_cd72Q8ts_iKA3X1i1GhAQ80N2SGtU,1376
229
229
  bec_widgets/widgets/stop_button/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
230
  bec_widgets/widgets/stop_button/register_stop_button.py,sha256=U7r3fEOH-uPhAQI-nTituHXDDXDWR4JQZ7_vD6b_dfM,471
231
- bec_widgets/widgets/stop_button/stop_button.py,sha256=_2vNytWjf-pKqyv5wT8j5NSA_4z9Zyk4aBnkEvU8_dA,798
231
+ bec_widgets/widgets/stop_button/stop_button.py,sha256=XLrRFvVrAhD16_-SPgzvsUhy0ROunsrWlI5BPRyqZOI,832
232
232
  bec_widgets/widgets/stop_button/stop_button.pyproject,sha256=Cc_xbv-zfzNVpsdg_1QyzuTlrJaM9_BkIjes70umrx0,29
233
233
  bec_widgets/widgets/stop_button/stop_button_plugin.py,sha256=PgMuMDuw5Fhfg89akNrIBTKl9ibVcgxg5wuI9cvQ9cc,1384
234
234
  bec_widgets/widgets/text_box/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -257,7 +257,7 @@ bec_widgets/widgets/waveform/waveform_popups/curve_dialog/curve_dialog.py,sha256
257
257
  bec_widgets/widgets/waveform/waveform_popups/curve_dialog/curve_dialog.ui,sha256=OaQE5HlyBQ3RQoHqxOFHiUoNcx8SDZP5sHJ9NNGhsPI,10404
258
258
  bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
259
259
  bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/dap_summary.ui,sha256=PFEKro61UXd-jmx65U4pqJ5D29DXtVnhQRnsnDvN-wM,6138
260
- bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/dap_summary_dialog.py,sha256=a5n_gBebETdj80TU7Dgy1cnazPFyxLlWk_lRdvy3qA4,2403
260
+ bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/dap_summary_dialog.py,sha256=UptWjHRVp7gTAMkWikfia3U6k8EV_pAvk-fI_vhWd2w,2437
261
261
  bec_widgets/widgets/website/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
262
262
  bec_widgets/widgets/website/register_website_widget.py,sha256=LIQJpV9uqcBiPR9cEAiDjaUS_l7JroYVdsotnLpD9H0,476
263
263
  bec_widgets/widgets/website/website.py,sha256=FmhVaasAU3ZSdKP-HHSnJHFbG8lIsNAPH9pZq55fhic,1731
@@ -314,8 +314,8 @@ docs/user/widgets/widgets.md,sha256=ZeRNmP7GUOu8kEoGu9XHsyF8Hb1foqZKEbwpgFP7ITk,
314
314
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
315
315
  tests/end-2-end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
316
316
  tests/end-2-end/conftest.py,sha256=-BLnFE-NeCerf6xahGCkbZ4Ktactowi6RkBnboIzRvg,1767
317
- tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=uDhauuLEWg9Baf3N1KSeq6HPUWtuU6a90wnh1fNGVqM,9115
318
- tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=mjg29huqTivLnukG_XyoMtjOy2P_7JACIhMEzahLXb8,6601
317
+ tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=hj06aUBGofq7yeFVoT3LB4NrCjc5FbOo5CGTvz7afpI,9118
318
+ tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=73vuBbPJvkMR3w2jnQ7lk0z4-wN3HAmkLFDdv4BRPrM,6604
319
319
  tests/end-2-end/test_rpc_register_e2e.py,sha256=blhMiW7HVHX1kGm5dg8Sv0PeCuJ0gnBz3evznQFz_B8,1619
320
320
  tests/end-2-end/test_scan_control_e2e.py,sha256=u7oLgFyltkMW2apSZKDukMIXvYrbhHrU32p4mBdn8VE,2276
321
321
  tests/references/SpinnerWidget/SpinnerWidget_darwin.png,sha256=OyiGxyQx0XCKEa1OeAZFVfFXHAllBDOjsvyTA_dDmoc,8353
@@ -324,12 +324,12 @@ tests/references/SpinnerWidget/SpinnerWidget_started_darwin.png,sha256=NA7dOdKY-
324
324
  tests/references/SpinnerWidget/SpinnerWidget_started_linux.png,sha256=NA7dOdKY-leFv8JI_5x3OIIY-XlSXSTIflVquz0UUZc,13784
325
325
  tests/unit_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
326
326
  tests/unit_tests/client_mocks.py,sha256=4pS4KvvFGY9hjphds9i-GoIjVWVkax4XpDnVp6Mctfw,5275
327
- tests/unit_tests/conftest.py,sha256=KrnktXPWmZhnKNue-xGWOLD1XGEvdz9Vf7V2eO3XQ3A,596
328
- tests/unit_tests/test_bec_connector.py,sha256=zGDfNHwLFZTbpyX6-yc7Pwzr2jWO_HGZ8T4NFCNo4IE,2444
327
+ tests/unit_tests/conftest.py,sha256=WsmfK1vOpF4msRHU6s5H8G0k8nf7cPJtazKlDjm-WRw,881
328
+ tests/unit_tests/test_bec_connector.py,sha256=5uqBfjgMeOlGvqJlFbytxEpZ1El7_Y2q8fZHh4GvtD8,2478
329
329
  tests/unit_tests/test_bec_dispatcher.py,sha256=rYPiRizHaswhGZw55IBMneDFxmPiCCLAZQBqjEkpdyY,3992
330
330
  tests/unit_tests/test_bec_dock.py,sha256=j52o5ZhGzcSJ2VTtRPjVf9ZpQTdMLO4w-eXc6GB2c90,5593
331
331
  tests/unit_tests/test_bec_figure.py,sha256=8AojxszCIzMi6EYB5mVFMQjk4pjgBCSp6PH2JZsuDkw,8724
332
- tests/unit_tests/test_bec_image.py,sha256=mjvcrHgOF_FCj6WbUyxvZH9HL63QGA5C0PNZ5dXYn50,2541
332
+ tests/unit_tests/test_bec_image.py,sha256=JqRKT-fdugmST80P0xSgMp6x_ukK-aLpezahPCWb3fA,2547
333
333
  tests/unit_tests/test_bec_image_widget.py,sha256=4-fdbsJsPuzJs8EFw9C1llcF4Zmv3vzJcA9t34J0WD4,7478
334
334
  tests/unit_tests/test_bec_motor_map.py,sha256=dSYopbZS8lGD9cB26Kwmqw5zBoKCZs8t7DEEr50ug-g,8532
335
335
  tests/unit_tests/test_bec_queue.py,sha256=u-uc-iZeGAS8P90o6Cxy5oz_60zHpirGAu04OgQPDXw,4598
@@ -369,8 +369,8 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
369
369
  tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
370
370
  tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
371
371
  tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
372
- bec_widgets-0.92.0.dist-info/METADATA,sha256=VnZc1usRRpdjc7CFNYGi63h-mkTI7pG7k1qirWunV4k,1308
373
- bec_widgets-0.92.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
374
- bec_widgets-0.92.0.dist-info/entry_points.txt,sha256=3otEkCdDB9LZJuBLzG4pFLK5Di0CVybN_12IsZrQ-58,166
375
- bec_widgets-0.92.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
376
- bec_widgets-0.92.0.dist-info/RECORD,,
372
+ bec_widgets-0.92.1.dist-info/METADATA,sha256=KBSOFzJA5iV_W_53ntYovfFeG4uPOv1SDfF-qCArFkY,1308
373
+ bec_widgets-0.92.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
374
+ bec_widgets-0.92.1.dist-info/entry_points.txt,sha256=3otEkCdDB9LZJuBLzG4pFLK5Di0CVybN_12IsZrQ-58,166
375
+ bec_widgets-0.92.1.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
376
+ bec_widgets-0.92.1.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "0.92.0"
7
+ version = "0.92.1"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -98,7 +98,7 @@ def test_rpc_add_dock_with_figure_e2e(bec_client_lib, rpc_server_dock):
98
98
  assert plt_data["bpm4i-bpm4i"]["y"] == plt_last_scan_data["bpm4i"]["bpm4i"].val
99
99
 
100
100
  # image
101
- last_image_device = client.connector.get_last(MessageEndpoints.device_monitor("eiger"))[
101
+ last_image_device = client.connector.get_last(MessageEndpoints.device_monitor_2d("eiger"))[
102
102
  "data"
103
103
  ].data
104
104
  time.sleep(0.5)
@@ -120,7 +120,7 @@ def test_rpc_image(rpc_server_figure, bec_client_lib):
120
120
  status = scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.05, relative=False)
121
121
  status.wait()
122
122
 
123
- last_image_device = client.connector.get_last(MessageEndpoints.device_monitor("eiger"))[
123
+ last_image_device = client.connector.get_last(MessageEndpoints.device_monitor_2d("eiger"))[
124
124
  "data"
125
125
  ].data
126
126
  last_image_plot = im.images[0].get_data()
@@ -1,9 +1,15 @@
1
1
  import pytest
2
2
 
3
3
  from bec_widgets.cli.rpc_register import RPCRegister
4
+ from bec_widgets.qt_utils import error_popups
4
5
  from bec_widgets.utils import bec_dispatcher as bec_dispatcher_module
5
6
 
6
7
 
8
+ @pytest.fixture(autouse=True)
9
+ def qapplication(qapp): # pylint: disable=unused-argument
10
+ yield
11
+
12
+
7
13
  @pytest.fixture(autouse=True)
8
14
  def rpc_register():
9
15
  yield RPCRegister()
@@ -11,7 +17,7 @@ def rpc_register():
11
17
 
12
18
 
13
19
  @pytest.fixture(autouse=True)
14
- def bec_dispatcher(threads_check):
20
+ def bec_dispatcher(threads_check): # pylint: disable=unused-argument
15
21
  bec_dispatcher = bec_dispatcher_module.BECDispatcher()
16
22
  yield bec_dispatcher
17
23
  bec_dispatcher.disconnect_all()
@@ -19,3 +25,8 @@ def bec_dispatcher(threads_check):
19
25
  bec_dispatcher.client.shutdown()
20
26
  # reinitialize singleton for next test
21
27
  bec_dispatcher_module.BECDispatcher.reset_singleton()
28
+
29
+
30
+ @pytest.fixture(autouse=True)
31
+ def clean_singleton():
32
+ error_popups._popup_utility_instance = None
@@ -2,9 +2,9 @@
2
2
  import time
3
3
 
4
4
  import pytest
5
- from qtpy.QtCore import Slot
6
5
  from qtpy.QtWidgets import QApplication
7
6
 
7
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
8
8
  from bec_widgets.utils import BECConnector, ConnectionConfig
9
9
 
10
10
  from .client_mocks import mocked_client
@@ -17,7 +17,7 @@ def bec_image_show(bec_figure):
17
17
 
18
18
  def test_on_image_update(bec_image_show):
19
19
  data = np.random.rand(100, 100)
20
- msg = messages.DeviceMonitorMessage(
20
+ msg = messages.DeviceMonitor2DMessage(
21
21
  device="eiger", data=data, metadata={"scan_id": "12345"}
22
22
  ).model_dump()
23
23
  bec_image_show.on_image_update(msg)
@@ -28,7 +28,7 @@ def test_on_image_update(bec_image_show):
28
28
  def test_autorange_on_image_update(bec_image_show):
29
29
  # Check if autorange mode "mean" works, should be default
30
30
  data = np.random.rand(100, 100)
31
- msg = messages.DeviceMonitorMessage(
31
+ msg = messages.DeviceMonitor2DMessage(
32
32
  device="eiger", data=data, metadata={"scan_id": "12345"}
33
33
  ).model_dump()
34
34
  bec_image_show.on_image_update(msg)
@@ -47,7 +47,7 @@ def test_autorange_on_image_update(bec_image_show):
47
47
  assert np.isclose(img.color_bar.getLevels(), (vmin, vmax), rtol=(1e-5, 1e-5)).all()
48
48
  # Change the input data, and switch to autorange False, colormap levels should stay untouched
49
49
  data *= 100
50
- msg = messages.DeviceMonitorMessage(
50
+ msg = messages.DeviceMonitor2DMessage(
51
51
  device="eiger", data=data, metadata={"scan_id": "12345"}
52
52
  ).model_dump()
53
53
  bec_image_show.set_autorange(False)