bec-widgets 0.99.1__py3-none-any.whl → 0.99.9__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.
Files changed (250) hide show
  1. .gitlab-ci.yml +0 -1
  2. CHANGELOG.md +76 -70
  3. PKG-INFO +2 -2
  4. bec_widgets/cli/client.py +3 -3
  5. bec_widgets/qt_utils/toolbar.py +11 -5
  6. bec_widgets/utils/bec_widget.py +11 -2
  7. bec_widgets/utils/colors.py +18 -2
  8. bec_widgets/utils/plugin_templates/plugin.template +2 -2
  9. bec_widgets/widgets/bec_queue/bec_queue.py +2 -0
  10. bec_widgets/widgets/bec_queue/bec_queue_plugin.py +1 -1
  11. bec_widgets/widgets/bec_status_box/bec_status_box.py +2 -0
  12. bec_widgets/widgets/bec_status_box/bec_status_box_plugin.py +1 -1
  13. bec_widgets/widgets/color_button/color_button.py +2 -0
  14. bec_widgets/widgets/color_button/color_button_plugin.py +1 -1
  15. bec_widgets/widgets/colormap_selector/colormap_selector.py +1 -0
  16. bec_widgets/widgets/colormap_selector/colormap_selector_plugin.py +1 -1
  17. bec_widgets/widgets/dark_mode_button/dark_mode_button.py +12 -3
  18. bec_widgets/widgets/dark_mode_button/dark_mode_button_plugin.py +1 -1
  19. bec_widgets/widgets/device_browser/device_browser.py +2 -0
  20. bec_widgets/widgets/device_browser/device_browser_plugin.py +1 -1
  21. bec_widgets/widgets/device_combobox/device_combo_box_plugin.py +1 -1
  22. bec_widgets/widgets/device_combobox/device_combobox.py +2 -0
  23. bec_widgets/widgets/device_line_edit/device_line_edit.py +2 -0
  24. bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py +1 -1
  25. bec_widgets/widgets/dock/dock.py +1 -0
  26. bec_widgets/widgets/dock/dock_area.py +30 -10
  27. bec_widgets/widgets/dock/dock_area_plugin.py +1 -1
  28. bec_widgets/widgets/figure/figure.py +1 -1
  29. bec_widgets/widgets/figure/plots/waveform/waveform.py +12 -7
  30. bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +3 -3
  31. bec_widgets/widgets/image/bec_image_widget_plugin.py +1 -1
  32. bec_widgets/widgets/image/image_widget.py +1 -0
  33. bec_widgets/widgets/motor_map/bec_motor_map_widget_plugin.py +1 -1
  34. bec_widgets/widgets/motor_map/motor_map_widget.py +1 -0
  35. bec_widgets/widgets/position_indicator/position_indicator.py +2 -0
  36. bec_widgets/widgets/position_indicator/position_indicator_plugin.py +1 -1
  37. bec_widgets/widgets/positioner_box/positioner_box.py +1 -0
  38. bec_widgets/widgets/positioner_box/positioner_box_plugin.py +1 -1
  39. bec_widgets/widgets/positioner_box/positioner_control_line.py +2 -0
  40. bec_widgets/widgets/positioner_box/positioner_control_line_plugin.py +1 -1
  41. bec_widgets/widgets/ring_progress_bar/ring_progress_bar.py +1 -0
  42. bec_widgets/widgets/ring_progress_bar/ring_progress_bar_plugin.py +1 -1
  43. bec_widgets/widgets/scan_control/scan_control.py +2 -0
  44. bec_widgets/widgets/scan_control/scan_control_plugin.py +1 -4
  45. bec_widgets/widgets/spinner/spinner.py +2 -0
  46. bec_widgets/widgets/spinner/spinner_widget_plugin.py +1 -1
  47. bec_widgets/widgets/stop_button/stop_button.py +2 -0
  48. bec_widgets/widgets/stop_button/stop_button_plugin.py +1 -1
  49. bec_widgets/widgets/text_box/text_box.py +1 -0
  50. bec_widgets/widgets/text_box/text_box_plugin.py +1 -1
  51. bec_widgets/widgets/toggle/toggle.py +1 -0
  52. bec_widgets/widgets/toggle/toggle_switch_plugin.py +1 -1
  53. bec_widgets/widgets/vscode/vs_code_editor_plugin.py +1 -1
  54. bec_widgets/widgets/vscode/vscode.py +1 -0
  55. bec_widgets/widgets/waveform/bec_waveform_widget_plugin.py +1 -1
  56. bec_widgets/widgets/waveform/waveform_popups/curve_dialog/curve_dialog.py +14 -13
  57. bec_widgets/widgets/waveform/waveform_widget.py +3 -2
  58. bec_widgets/widgets/website/website.py +42 -10
  59. bec_widgets/widgets/website/website_widget_plugin.py +1 -1
  60. {bec_widgets-0.99.1.dist-info → bec_widgets-0.99.9.dist-info}/METADATA +2 -2
  61. bec_widgets-0.99.9.dist-info/RECORD +231 -0
  62. pyproject.toml +7 -2
  63. bec_widgets/assets/toolbar_icons/add.svg +0 -3
  64. bec_widgets/assets/toolbar_icons/attach_all.svg +0 -3
  65. bec_widgets/assets/toolbar_icons/auto_range.svg +0 -3
  66. bec_widgets/assets/toolbar_icons/compare.svg +0 -3
  67. bec_widgets/assets/toolbar_icons/connection.svg +0 -4
  68. bec_widgets/assets/toolbar_icons/device_line_edit.svg +0 -3
  69. bec_widgets/assets/toolbar_icons/drag_pan_mode.svg +0 -3
  70. bec_widgets/assets/toolbar_icons/export.svg +0 -9
  71. bec_widgets/assets/toolbar_icons/fft.svg +0 -11
  72. bec_widgets/assets/toolbar_icons/fitting_parameters.svg +0 -3
  73. bec_widgets/assets/toolbar_icons/history.svg +0 -4
  74. bec_widgets/assets/toolbar_icons/image.svg +0 -3
  75. bec_widgets/assets/toolbar_icons/image_autorange.svg +0 -3
  76. bec_widgets/assets/toolbar_icons/import.svg +0 -9
  77. bec_widgets/assets/toolbar_icons/line_axis.svg +0 -3
  78. bec_widgets/assets/toolbar_icons/line_curve.svg +0 -3
  79. bec_widgets/assets/toolbar_icons/lock_aspect_ratio.svg +0 -3
  80. bec_widgets/assets/toolbar_icons/log_scale.png +0 -0
  81. bec_widgets/assets/toolbar_icons/motor_map.svg +0 -3
  82. bec_widgets/assets/toolbar_icons/photo_library.svg +0 -3
  83. bec_widgets/assets/toolbar_icons/positioner_box.svg +0 -3
  84. bec_widgets/assets/toolbar_icons/progress.svg +0 -3
  85. bec_widgets/assets/toolbar_icons/queue.svg +0 -3
  86. bec_widgets/assets/toolbar_icons/rectangle_mode.svg +0 -3
  87. bec_widgets/assets/toolbar_icons/remove.svg +0 -5
  88. bec_widgets/assets/toolbar_icons/reset_settings.svg +0 -3
  89. bec_widgets/assets/toolbar_icons/restore_state.svg +0 -3
  90. bec_widgets/assets/toolbar_icons/ring_progress.svg +0 -3
  91. bec_widgets/assets/toolbar_icons/rotate_left.svg +0 -3
  92. bec_widgets/assets/toolbar_icons/rotate_right.svg +0 -3
  93. bec_widgets/assets/toolbar_icons/save.svg +0 -3
  94. bec_widgets/assets/toolbar_icons/save_state.svg +0 -3
  95. bec_widgets/assets/toolbar_icons/scan_control.svg +0 -3
  96. bec_widgets/assets/toolbar_icons/settings.svg +0 -4
  97. bec_widgets/assets/toolbar_icons/status.svg +0 -3
  98. bec_widgets/assets/toolbar_icons/terminal.svg +0 -3
  99. bec_widgets/assets/toolbar_icons/transform.svg +0 -3
  100. bec_widgets/assets/toolbar_icons/waveform.svg +0 -3
  101. bec_widgets-0.99.1.dist-info/RECORD +0 -415
  102. docs/Makefile +0 -20
  103. docs/_static/custom.css +0 -170
  104. docs/_templates/custom-class-template.rst +0 -34
  105. docs/_templates/custom-module-template.rst +0 -66
  106. docs/api_reference/api_reference.md +0 -12
  107. docs/assets/apps_48dp.svg +0 -1
  108. docs/assets/display_settings_48dp.svg +0 -1
  109. docs/assets/index_api.svg +0 -97
  110. docs/assets/index_contribute.svg +0 -76
  111. docs/assets/index_getting_started.svg +0 -66
  112. docs/assets/index_user_guide.svg +0 -67
  113. docs/assets/rocket_launch_48dp.svg +0 -1
  114. docs/assets/widget_screenshots/buttons.png +0 -0
  115. docs/assets/widget_screenshots/device_box.png +0 -0
  116. docs/assets/widget_screenshots/device_browser.png +0 -0
  117. docs/assets/widget_screenshots/device_inputs.png +0 -0
  118. docs/assets/widget_screenshots/dock_area.png +0 -0
  119. docs/assets/widget_screenshots/figure.png +0 -0
  120. docs/assets/widget_screenshots/image_widget.png +0 -0
  121. docs/assets/widget_screenshots/motor_map_widget.png +0 -0
  122. docs/assets/widget_screenshots/position_indicator.png +0 -0
  123. docs/assets/widget_screenshots/queue.png +0 -0
  124. docs/assets/widget_screenshots/ring_progress_bar.png +0 -0
  125. docs/assets/widget_screenshots/scan_controller.png +0 -0
  126. docs/assets/widget_screenshots/spinner.gif +0 -0
  127. docs/assets/widget_screenshots/status_box.png +0 -0
  128. docs/assets/widget_screenshots/text_box.png +0 -0
  129. docs/assets/widget_screenshots/toggle.png +0 -0
  130. docs/assets/widget_screenshots/waveform_widget.png +0 -0
  131. docs/assets/widget_screenshots/website.png +0 -0
  132. docs/conf.py +0 -82
  133. docs/developer/developer.md +0 -52
  134. docs/developer/introduction/concepts.md +0 -14
  135. docs/developer/introduction/contributing.md +0 -28
  136. docs/developer/introduction/introduction.md +0 -16
  137. docs/developer/introduction/useful_links.md +0 -23
  138. docs/developer/widget_development/bec_dispatcher.md +0 -143
  139. docs/developer/widget_development/widget_development.md +0 -13
  140. docs/index.md +0 -74
  141. docs/introduction/introduction.md +0 -18
  142. docs/make.bat +0 -35
  143. docs/requirements.txt +0 -12
  144. docs/user/api_reference/api_reference.md +0 -11
  145. docs/user/applications/applications.md +0 -10
  146. docs/user/customisation.md +0 -123
  147. docs/user/getting_started/BECDockArea.png +0 -0
  148. docs/user/getting_started/auto_updates.md +0 -82
  149. docs/user/getting_started/getting_started.md +0 -15
  150. docs/user/getting_started/gui_complex_gui.gif +0 -0
  151. docs/user/getting_started/installation.md +0 -33
  152. docs/user/getting_started/quick_start.md +0 -110
  153. docs/user/getting_started/video_tutorials.md +0 -17
  154. docs/user/user.md +0 -71
  155. docs/user/widgets/bec_figure/BECFigure.png +0 -0
  156. docs/user/widgets/bec_figure/bec_figure.md +0 -105
  157. docs/user/widgets/bec_status_box/bec_status_box.gif +0 -0
  158. docs/user/widgets/bec_status_box/bec_status_box.md +0 -38
  159. docs/user/widgets/buttons/buttons.md +0 -63
  160. docs/user/widgets/buttons/dark_mode_disabled.png +0 -0
  161. docs/user/widgets/buttons/dark_mode_enabled.png +0 -0
  162. docs/user/widgets/device_browser/device_browser.md +0 -36
  163. docs/user/widgets/device_browser/device_browser.png +0 -0
  164. docs/user/widgets/device_input/device_input.md +0 -100
  165. docs/user/widgets/dock_area/BECDockArea.png +0 -0
  166. docs/user/widgets/dock_area/bec_dock_area.md +0 -107
  167. docs/user/widgets/image/image_plot.gif +0 -0
  168. docs/user/widgets/image/image_widget.md +0 -84
  169. docs/user/widgets/motor_map/motor.gif +0 -0
  170. docs/user/widgets/motor_map/motor_map.md +0 -80
  171. docs/user/widgets/position_indicator/position_indicator.md +0 -76
  172. docs/user/widgets/positioner_box/positioner_box.md +0 -63
  173. docs/user/widgets/progress_bar/progress_bar.gif +0 -0
  174. docs/user/widgets/progress_bar/ring_progress_bar.md +0 -103
  175. docs/user/widgets/queue/queue.md +0 -41
  176. docs/user/widgets/scan_control/hide_scan_control.png +0 -0
  177. docs/user/widgets/scan_control/scan_control.gif +0 -0
  178. docs/user/widgets/scan_control/scan_control.md +0 -54
  179. docs/user/widgets/spinner/spinner.md +0 -75
  180. docs/user/widgets/text_box/text_box.md +0 -74
  181. docs/user/widgets/toggle/toggle.md +0 -66
  182. docs/user/widgets/waveform/bec_figure_dap.gif +0 -0
  183. docs/user/widgets/waveform/scatter_2D.gif +0 -0
  184. docs/user/widgets/waveform/w1D.gif +0 -0
  185. docs/user/widgets/waveform/waveform_widget.md +0 -132
  186. docs/user/widgets/website/website.md +0 -69
  187. docs/user/widgets/widgets.md +0 -220
  188. tests/__init__.py +0 -0
  189. tests/end-2-end/__init__.py +0 -0
  190. tests/end-2-end/conftest.py +0 -53
  191. tests/end-2-end/test_bec_dock_rpc_e2e.py +0 -298
  192. tests/end-2-end/test_bec_figure_rpc_e2e.py +0 -212
  193. tests/end-2-end/test_rpc_register_e2e.py +0 -40
  194. tests/end-2-end/test_scan_control_e2e.py +0 -71
  195. tests/references/SpinnerWidget/SpinnerWidget_darwin.png +0 -0
  196. tests/references/SpinnerWidget/SpinnerWidget_linux.png +0 -0
  197. tests/references/SpinnerWidget/SpinnerWidget_started_darwin.png +0 -0
  198. tests/references/SpinnerWidget/SpinnerWidget_started_linux.png +0 -0
  199. tests/unit_tests/__init__.py +0 -0
  200. tests/unit_tests/client_mocks.py +0 -189
  201. tests/unit_tests/conftest.py +0 -64
  202. tests/unit_tests/test_bec_connector.py +0 -80
  203. tests/unit_tests/test_bec_dispatcher.py +0 -119
  204. tests/unit_tests/test_bec_dock.py +0 -155
  205. tests/unit_tests/test_bec_figure.py +0 -270
  206. tests/unit_tests/test_bec_image.py +0 -63
  207. tests/unit_tests/test_bec_image_widget.py +0 -217
  208. tests/unit_tests/test_bec_motor_map.py +0 -282
  209. tests/unit_tests/test_bec_queue.py +0 -111
  210. tests/unit_tests/test_bec_status_box.py +0 -123
  211. tests/unit_tests/test_client_utils.py +0 -76
  212. tests/unit_tests/test_color_map_selector.py +0 -42
  213. tests/unit_tests/test_color_validation.py +0 -75
  214. tests/unit_tests/test_configs/config_device.yaml +0 -33
  215. tests/unit_tests/test_configs/config_device_no_entry.yaml +0 -27
  216. tests/unit_tests/test_configs/config_scan.yaml +0 -82
  217. tests/unit_tests/test_crosshair.py +0 -143
  218. tests/unit_tests/test_dark_mode_button.py +0 -70
  219. tests/unit_tests/test_device_browser.py +0 -83
  220. tests/unit_tests/test_device_input_base.py +0 -76
  221. tests/unit_tests/test_device_input_widgets.py +0 -178
  222. tests/unit_tests/test_error_utils.py +0 -63
  223. tests/unit_tests/test_generate_cli_client.py +0 -123
  224. tests/unit_tests/test_generate_plugin.py +0 -155
  225. tests/unit_tests/test_motor_map_widget.py +0 -194
  226. tests/unit_tests/test_msgs/__init__.py +0 -0
  227. tests/unit_tests/test_msgs/available_scans_message.py +0 -989
  228. tests/unit_tests/test_plot_base.py +0 -95
  229. tests/unit_tests/test_plugin_utils.py +0 -13
  230. tests/unit_tests/test_positioner_box.py +0 -130
  231. tests/unit_tests/test_ring_progress_bar.py +0 -337
  232. tests/unit_tests/test_rpc_register.py +0 -52
  233. tests/unit_tests/test_rpc_server.py +0 -42
  234. tests/unit_tests/test_rpc_widget_handler.py +0 -7
  235. tests/unit_tests/test_scan_control.py +0 -324
  236. tests/unit_tests/test_scan_control_group_box.py +0 -160
  237. tests/unit_tests/test_setting_dialog.py +0 -96
  238. tests/unit_tests/test_spinner.py +0 -31
  239. tests/unit_tests/test_stop_button.py +0 -27
  240. tests/unit_tests/test_text_box_widget.py +0 -54
  241. tests/unit_tests/test_toggle.py +0 -38
  242. tests/unit_tests/test_vscode_widget.py +0 -75
  243. tests/unit_tests/test_waveform1d.py +0 -712
  244. tests/unit_tests/test_waveform_widget.py +0 -462
  245. tests/unit_tests/test_website_widget.py +0 -25
  246. tests/unit_tests/test_widget_io.py +0 -90
  247. tests/unit_tests/test_yaml_dialog.py +0 -163
  248. {bec_widgets-0.99.1.dist-info → bec_widgets-0.99.9.dist-info}/WHEEL +0 -0
  249. {bec_widgets-0.99.1.dist-info → bec_widgets-0.99.9.dist-info}/entry_points.txt +0 -0
  250. {bec_widgets-0.99.1.dist-info → bec_widgets-0.99.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,83 +0,0 @@
1
- from typing import TYPE_CHECKING
2
- from unittest import mock
3
-
4
- import pytest
5
- from qtpy.QtCore import Qt
6
-
7
- from bec_widgets.widgets.device_browser.device_browser import DeviceBrowser
8
-
9
- from .client_mocks import mocked_client
10
-
11
- if TYPE_CHECKING:
12
- from qtpy.QtWidgets import QListWidgetItem
13
-
14
- from bec_widgets.widgets.device_browser.device_item.device_item import DeviceItem
15
-
16
-
17
- @pytest.fixture
18
- def device_browser(qtbot, mocked_client):
19
- dev_browser = DeviceBrowser(client=mocked_client)
20
- qtbot.addWidget(dev_browser)
21
- qtbot.waitExposed(dev_browser)
22
- yield dev_browser
23
-
24
-
25
- def test_device_browser_init_with_devices(device_browser):
26
- """
27
- Test that the device browser is initialized with the correct number of devices.
28
- """
29
- device_list = device_browser.ui.device_list
30
- assert device_list.count() == len(device_browser.dev)
31
-
32
-
33
- def test_device_browser_filtering(qtbot, device_browser):
34
- """
35
- Test that the device browser is able to filter the device list.
36
- """
37
- device_list = device_browser.ui.device_list
38
- device_browser.ui.filter_input.setText("sam")
39
- qtbot.wait(1000)
40
- assert device_list.count() == 3
41
-
42
- device_browser.ui.filter_input.setText("nonexistent")
43
- qtbot.wait(1000)
44
- assert device_list.count() == 0
45
-
46
- device_browser.ui.filter_input.setText("")
47
- qtbot.wait(1000)
48
- assert device_list.count() == len(device_browser.dev)
49
-
50
-
51
- def test_device_item_mouse_press_event(device_browser, qtbot):
52
- """
53
- Test that the mousePressEvent is triggered correctly.
54
- """
55
- # Simulate a left mouse press event on the device item
56
- device_item: QListWidgetItem = device_browser.ui.device_list.itemAt(0, 0)
57
- widget: DeviceItem = device_browser.ui.device_list.itemWidget(device_item)
58
- qtbot.mousePress(widget.label, Qt.MouseButton.LeftButton)
59
-
60
-
61
- def test_device_item_mouse_press_event_creates_drag(device_browser, qtbot):
62
- """
63
- Test that the mousePressEvent is triggered correctly and initiates a drag.
64
- """
65
- device_item: QListWidgetItem = device_browser.ui.device_list.itemAt(0, 0)
66
- widget: DeviceItem = device_browser.ui.device_list.itemWidget(device_item)
67
- device_name = widget.device
68
- with mock.patch("qtpy.QtGui.QDrag.exec_") as mock_exec:
69
- with mock.patch("qtpy.QtGui.QDrag.setMimeData") as mock_set_mimedata:
70
- qtbot.mousePress(widget.label, Qt.MouseButton.LeftButton)
71
- mock_set_mimedata.assert_called_once()
72
- mock_exec.assert_called_once()
73
- assert mock_set_mimedata.call_args[0][0].text() == device_name
74
-
75
-
76
- def test_device_item_double_click_event(device_browser, qtbot):
77
- """
78
- Test that the mouseDoubleClickEvent is triggered correctly.
79
- """
80
- # Simulate a left mouse press event on the device item
81
- device_item: QListWidgetItem = device_browser.ui.device_list.itemAt(0, 0)
82
- widget: DeviceItem = device_browser.ui.device_list.itemWidget(device_item)
83
- qtbot.mouseDClick(widget, Qt.LeftButton)
@@ -1,76 +0,0 @@
1
- import pytest
2
- from qtpy.QtWidgets import QWidget
3
-
4
- from bec_widgets.widgets.base_classes.device_input_base import DeviceInputBase
5
-
6
- from .client_mocks import mocked_client
7
-
8
-
9
- # DeviceInputBase is meant to be mixed in a QWidget
10
- class DeviceInputWidget(DeviceInputBase, QWidget):
11
- def __init__(self, parent=None, client=None, config=None, gui_id=None):
12
- super().__init__(client=client, config=config, gui_id=gui_id)
13
- QWidget.__init__(self, parent=parent)
14
-
15
-
16
- @pytest.fixture
17
- def device_input_base(qtbot, mocked_client):
18
- widget = DeviceInputWidget(client=mocked_client)
19
- qtbot.addWidget(widget)
20
- qtbot.waitExposed(widget)
21
- yield widget
22
-
23
-
24
- def test_device_input_base_init(device_input_base):
25
- assert device_input_base is not None
26
- assert device_input_base.client is not None
27
- assert isinstance(device_input_base, DeviceInputBase)
28
- assert device_input_base.config.widget_class == "DeviceInputWidget"
29
- assert device_input_base.config.device_filter is None
30
- assert device_input_base.config.default is None
31
- assert device_input_base.devices == []
32
-
33
-
34
- def test_device_input_base_init_with_config(mocked_client):
35
- config = {
36
- "widget_class": "DeviceInputWidget",
37
- "gui_id": "test_gui_id",
38
- "device_filter": "FakePositioner",
39
- "default": "samx",
40
- }
41
- widget = DeviceInputWidget(client=mocked_client, config=config)
42
- assert widget.config.gui_id == "test_gui_id"
43
- assert widget.config.device_filter == "FakePositioner"
44
- assert widget.config.default == "samx"
45
-
46
-
47
- def test_device_input_base_set_device_filter(device_input_base):
48
- device_input_base.set_device_filter("FakePositioner")
49
- assert device_input_base.config.device_filter == "FakePositioner"
50
-
51
-
52
- def test_device_input_base_set_device_filter_error(device_input_base):
53
- with pytest.raises(ValueError) as excinfo:
54
- device_input_base.set_device_filter("NonExistingClass")
55
- assert "Device filter NonExistingClass is not in the device list." in str(excinfo.value)
56
-
57
-
58
- def test_device_input_base_set_default_device(device_input_base):
59
- device_input_base.set_default_device("samx")
60
- assert device_input_base.config.default == "samx"
61
-
62
-
63
- def test_device_input_base_set_default_device_error(device_input_base):
64
- with pytest.raises(ValueError) as excinfo:
65
- device_input_base.set_default_device("NonExistingDevice")
66
- assert "Default device NonExistingDevice is not in the device list." in str(excinfo.value)
67
-
68
-
69
- def test_device_input_base_get_device_list(device_input_base):
70
- devices = device_input_base.get_device_list("FakePositioner")
71
- assert devices == ["samx", "samy", "samz", "aptrx", "aptry"]
72
-
73
-
74
- def test_device_input_base_get_filters(device_input_base):
75
- filters = device_input_base.get_available_filters()
76
- assert filters == {"FakePositioner", "FakeDevice", "Positioner", "Device"}
@@ -1,178 +0,0 @@
1
- import pytest
2
-
3
- from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
4
- from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
5
-
6
- from .client_mocks import mocked_client
7
-
8
-
9
- @pytest.fixture
10
- def device_input_combobox(qtbot, mocked_client):
11
- widget = DeviceComboBox(client=mocked_client)
12
- qtbot.addWidget(widget)
13
- qtbot.waitExposed(widget)
14
- yield widget
15
-
16
-
17
- @pytest.fixture
18
- def device_input_combobox_with_config(qtbot, mocked_client):
19
- config = {
20
- "widget_class": "DeviceComboBox",
21
- "gui_id": "test_gui_id",
22
- "device_filter": "FakePositioner",
23
- "default": "samx",
24
- "arg_name": "test_arg_name",
25
- }
26
- widget = DeviceComboBox(client=mocked_client, config=config)
27
- qtbot.addWidget(widget)
28
- qtbot.waitExposed(widget)
29
- yield widget
30
-
31
-
32
- @pytest.fixture
33
- def device_input_combobox_with_kwargs(qtbot, mocked_client):
34
- widget = DeviceComboBox(
35
- client=mocked_client,
36
- gui_id="test_gui_id",
37
- device_filter="FakePositioner",
38
- default="samx",
39
- arg_name="test_arg_name",
40
- )
41
- qtbot.addWidget(widget)
42
- qtbot.waitExposed(widget)
43
- yield widget
44
-
45
-
46
- def test_device_input_combobox_init(device_input_combobox):
47
- assert device_input_combobox is not None
48
- assert device_input_combobox.client is not None
49
- assert isinstance(device_input_combobox, DeviceComboBox)
50
- assert device_input_combobox.config.widget_class == "DeviceComboBox"
51
- assert device_input_combobox.config.device_filter is None
52
- assert device_input_combobox.config.default is None
53
- assert device_input_combobox.devices == [
54
- "samx",
55
- "samy",
56
- "samz",
57
- "aptrx",
58
- "aptry",
59
- "gauss_bpm",
60
- "gauss_adc1",
61
- "gauss_adc2",
62
- "gauss_adc3",
63
- "bpm4i",
64
- "bpm3a",
65
- "bpm3i",
66
- "eiger",
67
- "async_device",
68
- "test",
69
- "test_device",
70
- ]
71
-
72
-
73
- def test_device_input_combobox_init_with_config(device_input_combobox_with_config):
74
- assert device_input_combobox_with_config.config.gui_id == "test_gui_id"
75
- assert device_input_combobox_with_config.config.device_filter == "FakePositioner"
76
- assert device_input_combobox_with_config.config.default == "samx"
77
- assert device_input_combobox_with_config.config.arg_name == "test_arg_name"
78
-
79
-
80
- def test_device_input_combobox_init_with_kwargs(device_input_combobox_with_kwargs):
81
- assert device_input_combobox_with_kwargs.config.gui_id == "test_gui_id"
82
- assert device_input_combobox_with_kwargs.config.device_filter == "FakePositioner"
83
- assert device_input_combobox_with_kwargs.config.default == "samx"
84
- assert device_input_combobox_with_kwargs.config.arg_name == "test_arg_name"
85
-
86
-
87
- def test_get_device_from_input_combobox_init(device_input_combobox):
88
- device_input_combobox.setCurrentIndex(0)
89
- device_text = device_input_combobox.currentText()
90
- current_device = device_input_combobox.get_device()
91
-
92
- assert current_device.name == device_text
93
-
94
-
95
- @pytest.fixture
96
- def device_input_line_edit(qtbot, mocked_client):
97
- widget = DeviceLineEdit(client=mocked_client)
98
- qtbot.addWidget(widget)
99
- qtbot.waitExposed(widget)
100
- yield widget
101
-
102
-
103
- @pytest.fixture
104
- def device_input_line_edit_with_config(qtbot, mocked_client):
105
- config = {
106
- "widget_class": "DeviceLineEdit",
107
- "gui_id": "test_gui_id",
108
- "device_filter": "FakePositioner",
109
- "default": "samx",
110
- "arg_name": "test_arg_name",
111
- }
112
- widget = DeviceLineEdit(client=mocked_client, config=config)
113
- qtbot.addWidget(widget)
114
- qtbot.waitExposed(widget)
115
- yield widget
116
-
117
-
118
- @pytest.fixture
119
- def device_input_line_edit_with_kwargs(qtbot, mocked_client):
120
- widget = DeviceLineEdit(
121
- client=mocked_client,
122
- gui_id="test_gui_id",
123
- device_filter="FakePositioner",
124
- default="samx",
125
- arg_name="test_arg_name",
126
- )
127
- qtbot.addWidget(widget)
128
- qtbot.waitExposed(widget)
129
- yield widget
130
-
131
-
132
- def test_device_input_line_edit_init(device_input_line_edit):
133
- assert device_input_line_edit is not None
134
- assert device_input_line_edit.client is not None
135
- assert isinstance(device_input_line_edit, DeviceLineEdit)
136
- assert device_input_line_edit.config.widget_class == "DeviceLineEdit"
137
- assert device_input_line_edit.config.device_filter is None
138
- assert device_input_line_edit.config.default is None
139
- assert device_input_line_edit.devices == [
140
- "samx",
141
- "samy",
142
- "samz",
143
- "aptrx",
144
- "aptry",
145
- "gauss_bpm",
146
- "gauss_adc1",
147
- "gauss_adc2",
148
- "gauss_adc3",
149
- "bpm4i",
150
- "bpm3a",
151
- "bpm3i",
152
- "eiger",
153
- "async_device",
154
- "test",
155
- "test_device",
156
- ]
157
-
158
-
159
- def test_device_input_line_edit_init_with_config(device_input_line_edit_with_config):
160
- assert device_input_line_edit_with_config.config.gui_id == "test_gui_id"
161
- assert device_input_line_edit_with_config.config.device_filter == "FakePositioner"
162
- assert device_input_line_edit_with_config.config.default == "samx"
163
- assert device_input_line_edit_with_config.config.arg_name == "test_arg_name"
164
-
165
-
166
- def test_device_input_line_edit_init_with_kwargs(device_input_line_edit_with_kwargs):
167
- assert device_input_line_edit_with_kwargs.config.gui_id == "test_gui_id"
168
- assert device_input_line_edit_with_kwargs.config.device_filter == "FakePositioner"
169
- assert device_input_line_edit_with_kwargs.config.default == "samx"
170
- assert device_input_line_edit_with_kwargs.config.arg_name == "test_arg_name"
171
-
172
-
173
- def test_get_device_from_input_line_edit_init(device_input_line_edit):
174
- device_input_line_edit.setText("samx")
175
- device_text = device_input_line_edit.text()
176
- current_device = device_input_line_edit.get_device()
177
-
178
- assert current_device.name == device_text
@@ -1,63 +0,0 @@
1
- from unittest.mock import patch
2
-
3
- import pytest
4
- import pytestqt
5
- from qtpy.QtWidgets import QMessageBox
6
-
7
- from bec_widgets.qt_utils.error_popups import ErrorPopupUtility, ExampleWidget
8
-
9
-
10
- @pytest.fixture
11
- def widget(qtbot):
12
- test_widget = ExampleWidget()
13
- qtbot.addWidget(test_widget)
14
- qtbot.waitExposed(test_widget)
15
- yield test_widget
16
- test_widget.close()
17
-
18
-
19
- @patch.object(QMessageBox, "exec_", return_value=QMessageBox.Ok)
20
- def test_show_error_message_global(mock_exec, widget, qtbot):
21
- error_utility = ErrorPopupUtility()
22
- error_utility.enable_global_error_popups(True)
23
-
24
- with qtbot.waitSignal(error_utility.error_occurred, timeout=1000) as blocker:
25
- error_utility.error_occurred.emit("Test Error", "This is a test error message.", widget)
26
-
27
- assert mock_exec.called
28
- assert blocker.signal_triggered
29
-
30
-
31
- @pytest.mark.parametrize("global_pop", [False, True])
32
- @patch.object(QMessageBox, "exec_", return_value=QMessageBox.Ok)
33
- def test_slot_with_popup_on_error(mock_exec, widget, qtbot, global_pop):
34
- error_utility = ErrorPopupUtility()
35
- error_utility.enable_global_error_popups(global_pop)
36
-
37
- with qtbot.waitSignal(error_utility.error_occurred, timeout=200) as blocker:
38
- widget.method_with_error_handling()
39
-
40
- assert blocker.signal_triggered
41
- assert mock_exec.called
42
-
43
-
44
- @pytest.mark.parametrize("global_pop", [False, True])
45
- @patch.object(QMessageBox, "exec_", return_value=QMessageBox.Ok)
46
- def test_slot_no_popup_by_default_on_error(mock_exec, widget, qtbot, capsys, global_pop):
47
- error_utility = ErrorPopupUtility()
48
- error_utility.enable_global_error_popups(global_pop)
49
-
50
- try:
51
- with qtbot.waitSignal(error_utility.error_occurred, timeout=200) as blocker:
52
- widget.method_without_error_handling()
53
- except pytestqt.exceptions.TimeoutError:
54
- assert not global_pop
55
-
56
- if global_pop:
57
- assert blocker.signal_triggered
58
- assert mock_exec.called
59
- else:
60
- assert not blocker.signal_triggered
61
- assert not mock_exec.called
62
- stdout, stderr = capsys.readouterr()
63
- assert "ValueError" in stderr
@@ -1,123 +0,0 @@
1
- from textwrap import dedent
2
-
3
- import black
4
- import isort
5
-
6
- from bec_widgets.cli.generate_cli import ClientGenerator
7
- from bec_widgets.utils.plugin_utils import BECClassContainer, BECClassInfo
8
-
9
- # pylint: disable=missing-function-docstring
10
-
11
-
12
- # Mock classes to test the generator
13
- class MockBECWaveform1D:
14
- USER_ACCESS = ["set_frequency", "set_amplitude"]
15
-
16
- def set_frequency(self, frequency: float) -> list:
17
- """Set the frequency of the waveform."""
18
- return [frequency]
19
-
20
- def set_amplitude(self, amplitude: float) -> tuple[float, float]:
21
- """Set the amplitude of the waveform."""
22
- return amplitude, amplitude
23
-
24
-
25
- class MockBECFigure:
26
- USER_ACCESS = ["add_plot", "remove_plot"]
27
-
28
- def add_plot(self, plot_id: str):
29
- """Add a plot to the figure."""
30
-
31
- def remove_plot(self, plot_id: str):
32
- """Remove a plot from the figure."""
33
-
34
-
35
- def test_client_generator_with_black_formatting():
36
- generator = ClientGenerator()
37
- container = BECClassContainer()
38
- container.add_class(
39
- BECClassInfo(
40
- name="MockBECWaveform1D",
41
- module="test_module",
42
- file="test_file",
43
- obj=MockBECWaveform1D,
44
- is_connector=True,
45
- is_widget=True,
46
- is_top_level=False,
47
- )
48
- )
49
- container.add_class(
50
- BECClassInfo(
51
- name="MockBECFigure",
52
- module="test_module",
53
- file="test_file",
54
- obj=MockBECFigure,
55
- is_connector=True,
56
- is_widget=True,
57
- is_top_level=True,
58
- )
59
- )
60
-
61
- generator.generate_client(container)
62
-
63
- # Format the expected output with black to ensure it matches the generator output
64
- expected_output = dedent(
65
- '''\
66
- # This file was automatically generated by generate_cli.py
67
-
68
- import enum
69
- from typing import Literal, Optional, overload
70
-
71
- from bec_widgets.cli.client_utils import BECGuiClientMixin, RPCBase, rpc_call
72
-
73
- # pylint: skip-file
74
-
75
-
76
- class Widgets(str, enum.Enum):
77
- """
78
- Enum for the available widgets.
79
- """
80
-
81
- MockBECFigure = "MockBECFigure"
82
-
83
-
84
- class MockBECFigure(RPCBase):
85
- @rpc_call
86
- def add_plot(self, plot_id: str):
87
- """
88
- Add a plot to the figure.
89
- """
90
-
91
- @rpc_call
92
- def remove_plot(self, plot_id: str):
93
- """
94
- Remove a plot from the figure.
95
- """
96
-
97
-
98
- class MockBECWaveform1D(RPCBase):
99
- @rpc_call
100
- def set_frequency(self, frequency: float) -> list:
101
- """
102
- Set the frequency of the waveform.
103
- """
104
-
105
- @rpc_call
106
- def set_amplitude(self, amplitude: float) -> tuple[float, float]:
107
- """
108
- Set the amplitude of the waveform.
109
- """
110
- '''
111
- )
112
-
113
- expected_output_formatted = black.format_str(
114
- expected_output, mode=black.FileMode(line_length=100)
115
- ).lstrip()
116
-
117
- generated_output_formatted = black.format_str(
118
- generator.header + "\n" + generator.content, mode=black.FileMode(line_length=100)
119
- )
120
-
121
- generated_output_formatted = isort.code(generated_output_formatted)
122
-
123
- assert expected_output_formatted == generated_output_formatted
@@ -1,155 +0,0 @@
1
- import importlib
2
- import inspect
3
- import os
4
- import sys
5
-
6
- import pytest
7
-
8
- from bec_widgets.utils.generate_designer_plugin import DesignerPluginGenerator
9
-
10
-
11
- def load_plugin(dir_path, content, plugin_name="MyWidget"):
12
- plugin_path = dir_path.mkdir("plugin").join("plugin.py")
13
- plugin_path.write(content)
14
- sys.path.append(str(dir_path))
15
- plugin = importlib.import_module("plugin.plugin")
16
- importlib.reload(plugin)
17
- yield getattr(plugin, plugin_name)
18
- sys.path.pop()
19
-
20
-
21
- @pytest.fixture(
22
- params=[
23
- """
24
- from qtpy.QtWidgets import QWidget
25
- class MyWidget(QWidget):
26
- def __init__(self, parent=None):
27
- QWidget.__init__(self, parent)
28
- """,
29
- """
30
- from qtpy.QtWidgets import QWidget
31
- class MyWidget(QWidget):
32
- def __init__(self, parent=None):
33
- QWidget.__init__(self, parent=parent)
34
- """,
35
- """
36
- from qtpy.QtWidgets import QWidget
37
- class MyWidget(QWidget):
38
- def __init__(self, parent=None):
39
- super().__init__(parent)
40
- """,
41
- """
42
- from qtpy.QtWidgets import QWidget
43
- class MyWidget(QWidget):
44
- def __init__(self, parent=None):
45
- super().__init__(parent=parent)
46
- """,
47
- """
48
- from qtpy.QtWidgets import QWidget
49
- class MyWidget(QWidget):
50
- def __init__(self, parent=None):
51
- super(QWidget, self).__init__(parent)"""
52
- """
53
- from qtpy.QtWidgets import QWidget
54
- class MyWidget(QWidget):
55
- def __init__(self, parent=None):
56
- super(QWidget, self).__init__(parent=parent)
57
- """,
58
- ]
59
- )
60
- def plugin_with_correct_parent(tmpdir, request):
61
- yield from load_plugin(tmpdir, request.param)
62
-
63
-
64
- @pytest.fixture(
65
- params=[
66
- """
67
- from qtpy.QtWidgets import QWidget
68
- class MyWidget(QWidget):
69
- def __init__(self, parent=None):
70
- QWidget.__init__(self)
71
- """,
72
- """
73
- from qtpy.QtWidgets import QWidget
74
- class MyWidget(QWidget):
75
- def __init__(self, parent=None):
76
- super().__init__()
77
- """,
78
- """
79
- from qtpy.QtWidgets import QWidget
80
- class MyWidget(QWidget):
81
- def __init__(self, parent=None):
82
- super(QWidget, self).__init__()
83
- """,
84
- ]
85
- )
86
- def plugin_with_missing_parent(tmpdir, request):
87
- yield from load_plugin(tmpdir, request.param)
88
-
89
-
90
- def test_generate_plugin(plugin_with_correct_parent):
91
- generator = DesignerPluginGenerator(plugin_with_correct_parent)
92
- generator.run()
93
- assert os.path.exists(f"{generator.info.base_path}/register_my_widget.py")
94
- assert os.path.exists(f"{generator.info.base_path}/my_widget_plugin.py")
95
- assert os.path.exists(f"{generator.info.base_path}/my_widget.pyproject")
96
-
97
-
98
- def test_generate_plugin_with_missing_parent(plugin_with_missing_parent):
99
- with pytest.raises(ValueError) as excinfo:
100
- generator = DesignerPluginGenerator(plugin_with_missing_parent)
101
- generator.run()
102
- assert "Widget class MyWidget must call the super constructor with parent." in str(
103
- excinfo.value
104
- )
105
-
106
-
107
- @pytest.fixture()
108
- def plugin_with_excluded_widget(tmpdir):
109
- content = """
110
- from qtpy.QtWidgets import QWidget
111
- class BECDock(QWidget):
112
- def __init__(self, parent=None):
113
- QWidget.__init__(self, parent)
114
- """
115
- yield from load_plugin(tmpdir, content, plugin_name="BECDock")
116
-
117
-
118
- def test_generate_plugin_with_excluded_widget(plugin_with_excluded_widget, capsys):
119
- generator = DesignerPluginGenerator(plugin_with_excluded_widget)
120
- generator.run()
121
- captured = capsys.readouterr()
122
-
123
- assert "Plugin BECDock is excluded from generation." in captured.out
124
- assert not os.path.exists(f"{generator.info.base_path}/register_bec_dock.py")
125
- assert not os.path.exists(f"{generator.info.base_path}/bec_dock_plugin.py")
126
- assert not os.path.exists(f"{generator.info.base_path}/bec_dock.pyproject")
127
-
128
-
129
- @pytest.fixture(
130
- params=[
131
- """
132
- from qtpy.QtWidgets import QWidget
133
- class MyWidget(QWidget):
134
- def __init__(self):
135
- QWidget.__init__(self)
136
- """,
137
- """
138
- from qtpy.QtWidgets import QWidget
139
- class MyWidget(QWidget):
140
- def __init__(self, config, parent=None):
141
- super().__init__()
142
- """,
143
- ]
144
- )
145
- def plugin_with_no_parent_as_first_arg(tmpdir, request):
146
- yield from load_plugin(tmpdir, request.param)
147
-
148
-
149
- def test_generate_plugin_raises_exception_when_first_argument_is_not_parent(
150
- plugin_with_no_parent_as_first_arg,
151
- ):
152
- with pytest.raises(ValueError) as excinfo:
153
- generator = DesignerPluginGenerator(plugin_with_no_parent_as_first_arg)
154
- generator.run()
155
- assert "Widget class MyWidget must have parent as the first argument." in str(excinfo.value)