bec-widgets 0.99.8__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 (155) hide show
  1. CHANGELOG.md +6 -6
  2. PKG-INFO +1 -1
  3. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/METADATA +1 -1
  4. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/RECORD +8 -155
  5. pyproject.toml +6 -1
  6. docs/Makefile +0 -20
  7. docs/_static/custom.css +0 -170
  8. docs/_templates/custom-class-template.rst +0 -34
  9. docs/_templates/custom-module-template.rst +0 -66
  10. docs/api_reference/api_reference.md +0 -12
  11. docs/assets/apps_48dp.svg +0 -1
  12. docs/assets/display_settings_48dp.svg +0 -1
  13. docs/assets/index_api.svg +0 -97
  14. docs/assets/index_contribute.svg +0 -76
  15. docs/assets/index_getting_started.svg +0 -66
  16. docs/assets/index_user_guide.svg +0 -67
  17. docs/assets/rocket_launch_48dp.svg +0 -1
  18. docs/assets/widget_screenshots/buttons.png +0 -0
  19. docs/assets/widget_screenshots/device_box.png +0 -0
  20. docs/assets/widget_screenshots/device_browser.png +0 -0
  21. docs/assets/widget_screenshots/device_inputs.png +0 -0
  22. docs/assets/widget_screenshots/dock_area.png +0 -0
  23. docs/assets/widget_screenshots/figure.png +0 -0
  24. docs/assets/widget_screenshots/image_widget.png +0 -0
  25. docs/assets/widget_screenshots/motor_map_widget.png +0 -0
  26. docs/assets/widget_screenshots/position_indicator.png +0 -0
  27. docs/assets/widget_screenshots/queue.png +0 -0
  28. docs/assets/widget_screenshots/ring_progress_bar.png +0 -0
  29. docs/assets/widget_screenshots/scan_controller.png +0 -0
  30. docs/assets/widget_screenshots/spinner.gif +0 -0
  31. docs/assets/widget_screenshots/status_box.png +0 -0
  32. docs/assets/widget_screenshots/text_box.png +0 -0
  33. docs/assets/widget_screenshots/toggle.png +0 -0
  34. docs/assets/widget_screenshots/waveform_widget.png +0 -0
  35. docs/assets/widget_screenshots/website.png +0 -0
  36. docs/conf.py +0 -82
  37. docs/developer/developer.md +0 -52
  38. docs/developer/introduction/concepts.md +0 -14
  39. docs/developer/introduction/contributing.md +0 -28
  40. docs/developer/introduction/introduction.md +0 -16
  41. docs/developer/introduction/useful_links.md +0 -23
  42. docs/developer/widget_development/bec_dispatcher.md +0 -143
  43. docs/developer/widget_development/widget_base_class.md +0 -171
  44. docs/developer/widget_development/widget_development.md +0 -14
  45. docs/index.md +0 -74
  46. docs/introduction/introduction.md +0 -18
  47. docs/make.bat +0 -35
  48. docs/requirements.txt +0 -12
  49. docs/user/api_reference/api_reference.md +0 -11
  50. docs/user/applications/applications.md +0 -10
  51. docs/user/customisation.md +0 -123
  52. docs/user/getting_started/BECDockArea.png +0 -0
  53. docs/user/getting_started/auto_updates.md +0 -82
  54. docs/user/getting_started/getting_started.md +0 -15
  55. docs/user/getting_started/gui_complex_gui.gif +0 -0
  56. docs/user/getting_started/installation.md +0 -33
  57. docs/user/getting_started/quick_start.md +0 -110
  58. docs/user/getting_started/video_tutorials.md +0 -17
  59. docs/user/user.md +0 -71
  60. docs/user/widgets/bec_figure/BECFigure.png +0 -0
  61. docs/user/widgets/bec_figure/bec_figure.md +0 -105
  62. docs/user/widgets/bec_status_box/bec_status_box.gif +0 -0
  63. docs/user/widgets/bec_status_box/bec_status_box.md +0 -38
  64. docs/user/widgets/buttons/buttons.md +0 -90
  65. docs/user/widgets/buttons/dark_mode_disabled.png +0 -0
  66. docs/user/widgets/buttons/dark_mode_enabled.png +0 -0
  67. docs/user/widgets/device_browser/device_browser.md +0 -36
  68. docs/user/widgets/device_browser/device_browser.png +0 -0
  69. docs/user/widgets/device_input/device_input.md +0 -100
  70. docs/user/widgets/dock_area/BECDockArea.png +0 -0
  71. docs/user/widgets/dock_area/bec_dock_area.md +0 -109
  72. docs/user/widgets/image/image_plot.gif +0 -0
  73. docs/user/widgets/image/image_widget.md +0 -84
  74. docs/user/widgets/motor_map/motor.gif +0 -0
  75. docs/user/widgets/motor_map/motor_map.md +0 -80
  76. docs/user/widgets/position_indicator/position_indicator.md +0 -69
  77. docs/user/widgets/positioner_box/positioner_box.md +0 -63
  78. docs/user/widgets/progress_bar/progress_bar.gif +0 -0
  79. docs/user/widgets/progress_bar/ring_progress_bar.md +0 -103
  80. docs/user/widgets/queue/queue.md +0 -41
  81. docs/user/widgets/scan_control/hide_scan_control.png +0 -0
  82. docs/user/widgets/scan_control/scan_control.gif +0 -0
  83. docs/user/widgets/scan_control/scan_control.md +0 -54
  84. docs/user/widgets/spinner/spinner.md +0 -68
  85. docs/user/widgets/text_box/text_box.md +0 -74
  86. docs/user/widgets/toggle/toggle.md +0 -66
  87. docs/user/widgets/waveform/bec_figure_dap.gif +0 -0
  88. docs/user/widgets/waveform/scatter_2D.gif +0 -0
  89. docs/user/widgets/waveform/w1D.gif +0 -0
  90. docs/user/widgets/waveform/waveform_widget.md +0 -132
  91. docs/user/widgets/website/website.md +0 -69
  92. docs/user/widgets/widgets.md +0 -220
  93. tests/__init__.py +0 -0
  94. tests/end-2-end/__init__.py +0 -0
  95. tests/end-2-end/conftest.py +0 -53
  96. tests/end-2-end/test_bec_dock_rpc_e2e.py +0 -298
  97. tests/end-2-end/test_bec_figure_rpc_e2e.py +0 -212
  98. tests/end-2-end/test_rpc_register_e2e.py +0 -40
  99. tests/end-2-end/test_scan_control_e2e.py +0 -71
  100. tests/references/SpinnerWidget/SpinnerWidget_darwin.png +0 -0
  101. tests/references/SpinnerWidget/SpinnerWidget_linux.png +0 -0
  102. tests/references/SpinnerWidget/SpinnerWidget_started_darwin.png +0 -0
  103. tests/references/SpinnerWidget/SpinnerWidget_started_linux.png +0 -0
  104. tests/unit_tests/__init__.py +0 -0
  105. tests/unit_tests/client_mocks.py +0 -189
  106. tests/unit_tests/conftest.py +0 -64
  107. tests/unit_tests/test_bec_connector.py +0 -80
  108. tests/unit_tests/test_bec_dispatcher.py +0 -119
  109. tests/unit_tests/test_bec_dock.py +0 -155
  110. tests/unit_tests/test_bec_figure.py +0 -270
  111. tests/unit_tests/test_bec_image.py +0 -63
  112. tests/unit_tests/test_bec_image_widget.py +0 -217
  113. tests/unit_tests/test_bec_motor_map.py +0 -282
  114. tests/unit_tests/test_bec_queue.py +0 -111
  115. tests/unit_tests/test_bec_status_box.py +0 -123
  116. tests/unit_tests/test_client_utils.py +0 -76
  117. tests/unit_tests/test_color_map_selector.py +0 -42
  118. tests/unit_tests/test_color_validation.py +0 -75
  119. tests/unit_tests/test_configs/config_device.yaml +0 -33
  120. tests/unit_tests/test_configs/config_device_no_entry.yaml +0 -27
  121. tests/unit_tests/test_configs/config_scan.yaml +0 -82
  122. tests/unit_tests/test_crosshair.py +0 -143
  123. tests/unit_tests/test_dark_mode_button.py +0 -70
  124. tests/unit_tests/test_device_browser.py +0 -83
  125. tests/unit_tests/test_device_input_base.py +0 -76
  126. tests/unit_tests/test_device_input_widgets.py +0 -178
  127. tests/unit_tests/test_error_utils.py +0 -63
  128. tests/unit_tests/test_generate_cli_client.py +0 -123
  129. tests/unit_tests/test_generate_plugin.py +0 -155
  130. tests/unit_tests/test_motor_map_widget.py +0 -194
  131. tests/unit_tests/test_msgs/__init__.py +0 -0
  132. tests/unit_tests/test_msgs/available_scans_message.py +0 -989
  133. tests/unit_tests/test_plot_base.py +0 -95
  134. tests/unit_tests/test_plugin_utils.py +0 -13
  135. tests/unit_tests/test_positioner_box.py +0 -130
  136. tests/unit_tests/test_ring_progress_bar.py +0 -337
  137. tests/unit_tests/test_rpc_register.py +0 -52
  138. tests/unit_tests/test_rpc_server.py +0 -42
  139. tests/unit_tests/test_rpc_widget_handler.py +0 -7
  140. tests/unit_tests/test_scan_control.py +0 -324
  141. tests/unit_tests/test_scan_control_group_box.py +0 -160
  142. tests/unit_tests/test_setting_dialog.py +0 -96
  143. tests/unit_tests/test_spinner.py +0 -31
  144. tests/unit_tests/test_stop_button.py +0 -27
  145. tests/unit_tests/test_text_box_widget.py +0 -54
  146. tests/unit_tests/test_toggle.py +0 -38
  147. tests/unit_tests/test_vscode_widget.py +0 -75
  148. tests/unit_tests/test_waveform1d.py +0 -712
  149. tests/unit_tests/test_waveform_widget.py +0 -462
  150. tests/unit_tests/test_website_widget.py +0 -25
  151. tests/unit_tests/test_widget_io.py +0 -90
  152. tests/unit_tests/test_yaml_dialog.py +0 -163
  153. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/WHEEL +0 -0
  154. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/entry_points.txt +0 -0
  155. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,95 +0,0 @@
1
- # pylint: disable=missing-function-docstring, missing-module-docstring, unused-import
2
- from unittest import mock
3
-
4
- import pytest
5
- from qtpy.QtGui import QFontInfo
6
-
7
- from bec_widgets.widgets.figure import BECFigure
8
-
9
- from .client_mocks import mocked_client
10
- from .conftest import create_widget
11
-
12
-
13
- def test_init_plot_base(qtbot, mocked_client):
14
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
15
- plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
16
- assert plot_base is not None
17
- assert plot_base.config.widget_class == "BECPlotBase"
18
- assert plot_base.config.gui_id == "test_plot"
19
-
20
-
21
- def test_plot_base_axes_by_separate_methods(qtbot, mocked_client):
22
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
23
- plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
24
-
25
- plot_base.set_title("Test Title")
26
- plot_base.set_x_label("Test x Label")
27
- plot_base.set_y_label("Test y Label")
28
- plot_base.set_x_lim(1, 100)
29
- plot_base.set_y_lim(5, 500)
30
- plot_base.set_grid(True, True)
31
- plot_base.set_x_scale("log")
32
- plot_base.set_y_scale("log")
33
-
34
- assert plot_base.plot_item.titleLabel.text == "Test Title"
35
- assert plot_base.config.axis.title == "Test Title"
36
- assert plot_base.plot_item.getAxis("bottom").labelText == "Test x Label"
37
- assert plot_base.config.axis.x_label == "Test x Label"
38
- assert plot_base.plot_item.getAxis("left").labelText == "Test y Label"
39
- assert plot_base.config.axis.y_label == "Test y Label"
40
- assert plot_base.config.axis.x_lim == (1, 100)
41
- assert plot_base.config.axis.y_lim == (5, 500)
42
- assert plot_base.plot_item.ctrl.xGridCheck.isChecked() == True
43
- assert plot_base.plot_item.ctrl.yGridCheck.isChecked() == True
44
- assert plot_base.plot_item.ctrl.logXCheck.isChecked() == True
45
- assert plot_base.plot_item.ctrl.logYCheck.isChecked() == True
46
-
47
- # Check the font size by mocking the set functions
48
- # I struggled retrieving it from the QFont object directly
49
- # thus I mocked the set functions to check internally the functionality
50
- with (
51
- mock.patch.object(plot_base.plot_item, "setLabel") as mock_set_label,
52
- mock.patch.object(plot_base.plot_item, "setTitle") as mock_set_title,
53
- ):
54
- plot_base.set_x_label("Test x Label", 20)
55
- plot_base.set_y_label("Test y Label", 16)
56
- assert mock_set_label.call_count == 2
57
- assert plot_base.config.axis.x_label_size == 20
58
- assert plot_base.config.axis.y_label_size == 16
59
- col = plot_base.get_text_color()
60
- calls = []
61
- style = {"color": col, "font-size": "20pt"}
62
- calls.append(mock.call("bottom", "Test x Label", **style))
63
- style = {"color": col, "font-size": "16pt"}
64
- calls.append(mock.call("left", "Test y Label", **style))
65
- assert mock_set_label.call_args_list == calls
66
- plot_base.set_title("Test Title", 16)
67
- style = {"color": col, "size": "16pt"}
68
- call = mock.call("Test Title", **style)
69
- assert mock_set_title.call_args == call
70
-
71
-
72
- def test_plot_base_axes_added_by_kwargs(qtbot, mocked_client):
73
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
74
- plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
75
-
76
- plot_base.set(
77
- title="Test Title",
78
- x_label="Test x Label",
79
- y_label="Test y Label",
80
- x_lim=(1, 100),
81
- y_lim=(5, 500),
82
- x_scale="log",
83
- y_scale="log",
84
- )
85
-
86
- assert plot_base.plot_item.titleLabel.text == "Test Title"
87
- assert plot_base.config.axis.title == "Test Title"
88
- assert plot_base.plot_item.getAxis("bottom").labelText == "Test x Label"
89
- assert plot_base.config.axis.x_label == "Test x Label"
90
- assert plot_base.plot_item.getAxis("left").labelText == "Test y Label"
91
- assert plot_base.config.axis.y_label == "Test y Label"
92
- assert plot_base.config.axis.x_lim == (1, 100)
93
- assert plot_base.config.axis.y_lim == (5, 500)
94
- assert plot_base.plot_item.ctrl.logXCheck.isChecked() == True
95
- assert plot_base.plot_item.ctrl.logYCheck.isChecked() == True
@@ -1,13 +0,0 @@
1
- from bec_widgets.utils.plugin_utils import get_rpc_classes
2
-
3
-
4
- def test_client_generator_classes():
5
- out = get_rpc_classes("bec_widgets")
6
- connector_cls_names = [cls.__name__ for cls in out.connector_classes]
7
- top_level_cls_names = [cls.__name__ for cls in out.top_level_classes]
8
-
9
- assert "BECFigure" in connector_cls_names
10
- assert "BECWaveform" in connector_cls_names
11
- assert "BECDockArea" in top_level_cls_names
12
- assert "BECFigure" in top_level_cls_names
13
- assert "BECWaveform" not in top_level_cls_names
@@ -1,130 +0,0 @@
1
- from unittest import mock
2
-
3
- import pytest
4
- from bec_lib.device import Positioner
5
- from bec_lib.endpoints import MessageEndpoints
6
- from bec_lib.messages import ScanQueueMessage
7
- from qtpy.QtGui import QValidator
8
-
9
- from bec_widgets.widgets.positioner_box.positioner_box import PositionerBox
10
- from bec_widgets.widgets.positioner_box.positioner_control_line import PositionerControlLine
11
-
12
- from .client_mocks import mocked_client
13
-
14
-
15
- @pytest.fixture
16
- def positioner_box(qtbot, mocked_client):
17
- """Fixture for PositionerBox widget"""
18
- with mock.patch("bec_widgets.widgets.positioner_box.positioner_box.uuid.uuid4") as mock_uuid:
19
- mock_uuid.return_value = "fake_uuid"
20
- with mock.patch(
21
- "bec_widgets.widgets.positioner_box.positioner_box.PositionerBox._check_device_is_valid",
22
- return_value=True,
23
- ):
24
- db = PositionerBox(device="samx", client=mocked_client)
25
- qtbot.addWidget(db)
26
- yield db
27
-
28
-
29
- def test_positioner_box(positioner_box):
30
- """Test init of positioner box"""
31
- assert positioner_box.device == "samx"
32
- data = positioner_box.dev["samx"].read()
33
- # Avoid check for Positioner class from BEC in _init_device
34
-
35
- setpoint_text = positioner_box.ui.setpoint.text()
36
- # check that the setpoint is taken correctly after init
37
- assert float(setpoint_text) == data["samx_setpoint"]["value"]
38
-
39
- # check that the precision is taken correctly after isnit
40
- precision = positioner_box.dev["samx"].precision
41
- assert setpoint_text == f"{data['samx_setpoint']['value']:.{precision}f}"
42
-
43
- # check that the step size is set according to the device precision
44
- assert positioner_box.ui.step_size.value() == 10**-precision * 10
45
-
46
-
47
- def test_positioner_box_update_limits(positioner_box):
48
- """Test update of limits"""
49
- positioner_box._limits = None
50
- positioner_box.update_limits([0, 10])
51
- assert positioner_box._limits == [0, 10]
52
- assert positioner_box.setpoint_validator.bottom() == 0
53
- assert positioner_box.setpoint_validator.top() == 10
54
- assert positioner_box.setpoint_validator.validate("100", 0) == (
55
- QValidator.State.Intermediate,
56
- "100",
57
- 0,
58
- )
59
-
60
- positioner_box.update_limits(None)
61
- assert positioner_box._limits is None
62
- assert positioner_box.setpoint_validator.validate("100", 0) == (
63
- QValidator.State.Acceptable,
64
- "100",
65
- 0,
66
- )
67
-
68
-
69
- def test_positioner_box_on_stop(positioner_box):
70
- """Test on stop button"""
71
- with mock.patch.object(positioner_box.client.connector, "send") as mock_send:
72
- positioner_box.on_stop()
73
- params = {"device": "samx", "rpc_id": "fake_uuid", "func": "stop", "args": [], "kwargs": {}}
74
- msg = ScanQueueMessage(
75
- scan_type="device_rpc",
76
- parameter=params,
77
- queue="emergency",
78
- metadata={"RID": "fake_uuid", "response": False},
79
- )
80
- mock_send.assert_called_once_with(MessageEndpoints.scan_queue_request(), msg)
81
-
82
-
83
- def test_positioner_box_setpoint_change(positioner_box):
84
- """Test positioner box setpoint change"""
85
- with mock.patch.object(positioner_box.dev["samx"], "move") as mock_move:
86
- positioner_box.ui.setpoint.setText("100")
87
- positioner_box.on_setpoint_change()
88
- mock_move.assert_called_once_with(100, relative=False)
89
-
90
-
91
- def test_positioner_box_on_tweak_right(positioner_box):
92
- """Test tweak right button"""
93
- with mock.patch.object(positioner_box.dev["samx"], "move") as mock_move:
94
- positioner_box.ui.step_size.setValue(0.1)
95
- positioner_box.on_tweak_right()
96
- mock_move.assert_called_once_with(0.1, relative=True)
97
-
98
-
99
- def test_positioner_box_on_tweak_left(positioner_box):
100
- """Test tweak left button"""
101
- with mock.patch.object(positioner_box.dev["samx"], "move") as mock_move:
102
- positioner_box.ui.step_size.setValue(0.1)
103
- positioner_box.on_tweak_left()
104
- mock_move.assert_called_once_with(-0.1, relative=True)
105
-
106
-
107
- def test_positioner_box_setpoint_out_of_range(positioner_box):
108
- """Test setpoint out of range"""
109
- positioner_box.update_limits([0, 10])
110
- positioner_box.ui.setpoint.setText("100")
111
- positioner_box.on_setpoint_change()
112
- assert positioner_box.ui.setpoint.text() == "100"
113
- assert positioner_box.ui.setpoint.hasAcceptableInput() == False
114
-
115
-
116
- def test_positioner_control_line(qtbot, mocked_client):
117
- """Test PositionerControlLine.
118
- Inherits from PositionerBox, but the layout is changed. Check dimensions only
119
- """
120
- with mock.patch("bec_widgets.widgets.positioner_box.positioner_box.uuid.uuid4") as mock_uuid:
121
- mock_uuid.return_value = "fake_uuid"
122
- with mock.patch(
123
- "bec_widgets.widgets.positioner_box.positioner_box.PositionerBox._check_device_is_valid",
124
- return_value=True,
125
- ):
126
- db = PositionerControlLine(device="samx", client=mocked_client)
127
- qtbot.addWidget(db)
128
-
129
- assert db.ui.device_box.height() == 60
130
- assert db.ui.device_box.width() == 600
@@ -1,337 +0,0 @@
1
- # pylint: disable=missing-function-docstring, missing-module-docstring, unused-import
2
-
3
- import pytest
4
- from bec_lib.endpoints import MessageEndpoints
5
- from pydantic import ValidationError
6
-
7
- from bec_widgets.utils import Colors
8
- from bec_widgets.widgets.ring_progress_bar import RingProgressBar
9
- from bec_widgets.widgets.ring_progress_bar.ring import ProgressbarConnections, RingConfig
10
- from bec_widgets.widgets.ring_progress_bar.ring_progress_bar import RingProgressBarConfig
11
-
12
- from .client_mocks import mocked_client
13
-
14
-
15
- @pytest.fixture
16
- def ring_progress_bar(qtbot, mocked_client):
17
- widget = RingProgressBar(client=mocked_client)
18
- qtbot.addWidget(widget)
19
- qtbot.waitExposed(widget)
20
- yield widget
21
-
22
-
23
- def test_bar_init(ring_progress_bar):
24
- assert ring_progress_bar is not None
25
- assert ring_progress_bar.client is not None
26
- assert isinstance(ring_progress_bar, RingProgressBar)
27
- assert ring_progress_bar.config.widget_class == "RingProgressBar"
28
- assert ring_progress_bar.config.gui_id is not None
29
- assert ring_progress_bar.gui_id == ring_progress_bar.config.gui_id
30
-
31
-
32
- def test_config_validation_num_of_bars():
33
- config = RingProgressBarConfig(num_bars=100, min_num_bars=1, max_num_bars=10)
34
-
35
- assert config.num_bars == 10
36
-
37
-
38
- def test_config_validation_num_of_ring_error():
39
- ring_config_0 = RingConfig(index=0)
40
- ring_config_1 = RingConfig(index=1)
41
-
42
- with pytest.raises(ValidationError) as excinfo:
43
- RingProgressBarConfig(rings=[ring_config_0, ring_config_1], num_bars=1)
44
- errors = excinfo.value.errors()
45
- assert len(errors) == 1
46
- assert errors[0]["type"] == "different number of configs"
47
- assert "Length of rings configuration (2) does not match the number of bars (1)." in str(
48
- excinfo.value
49
- )
50
-
51
-
52
- def test_config_validation_ring_indices_wrong_order():
53
- ring_config_0 = RingConfig(index=2)
54
- ring_config_1 = RingConfig(index=5)
55
-
56
- with pytest.raises(ValidationError) as excinfo:
57
- RingProgressBarConfig(rings=[ring_config_0, ring_config_1], num_bars=2)
58
- errors = excinfo.value.errors()
59
- assert len(errors) == 1
60
- assert errors[0]["type"] == "wrong indices"
61
- assert (
62
- "Indices of ring configurations must be unique and in order from 0 to num_bars 2."
63
- in str(excinfo.value)
64
- )
65
-
66
-
67
- def test_config_validation_ring_same_indices():
68
- ring_config_0 = RingConfig(index=0)
69
- ring_config_1 = RingConfig(index=0)
70
-
71
- with pytest.raises(ValidationError) as excinfo:
72
- RingProgressBarConfig(rings=[ring_config_0, ring_config_1], num_bars=2)
73
- errors = excinfo.value.errors()
74
- assert len(errors) == 1
75
- assert errors[0]["type"] == "wrong indices"
76
- assert (
77
- "Indices of ring configurations must be unique and in order from 0 to num_bars 2."
78
- in str(excinfo.value)
79
- )
80
-
81
-
82
- def test_config_validation_invalid_colormap():
83
- with pytest.raises(ValueError) as excinfo:
84
- RingProgressBarConfig(color_map="crazy_colors")
85
- errors = excinfo.value.errors()
86
- assert len(errors) == 1
87
- assert errors[0]["type"] == "unsupported colormap"
88
- assert "Colormap 'crazy_colors' not found in the current installation of pyqtgraph" in str(
89
- excinfo.value
90
- )
91
-
92
-
93
- def test_ring_connection_endpoint_validation():
94
- with pytest.raises(ValueError) as excinfo:
95
- ProgressbarConnections(slot="on_scan_progress", endpoint="non_existing")
96
- errors = excinfo.value.errors()
97
- assert len(errors) == 1
98
- assert errors[0]["type"] == "unsupported endpoint"
99
- assert (
100
- "For slot 'on_scan_progress', endpoint must be MessageEndpoint.scan_progress or 'scans/scan_progress'."
101
- in str(excinfo.value)
102
- )
103
-
104
- with pytest.raises(ValueError) as excinfo:
105
- ProgressbarConnections(slot="on_device_readback", endpoint="non_existing")
106
- errors = excinfo.value.errors()
107
- assert len(errors) == 1
108
- assert errors[0]["type"] == "unsupported endpoint"
109
- assert (
110
- "For slot 'on_device_readback', endpoint must be MessageEndpoint.device_readback(device) or 'internal/devices/readback/{device}'."
111
- in str(excinfo.value)
112
- )
113
-
114
-
115
- def test_bar_add_number_of_bars(ring_progress_bar):
116
- assert ring_progress_bar.config.num_bars == 1
117
-
118
- ring_progress_bar.set_number_of_bars(5)
119
- assert ring_progress_bar.config.num_bars == 5
120
-
121
- ring_progress_bar.set_number_of_bars(2)
122
- assert ring_progress_bar.config.num_bars == 2
123
-
124
-
125
- def test_add_remove_bars_individually(ring_progress_bar):
126
- ring_progress_bar.add_ring()
127
- ring_progress_bar.add_ring()
128
-
129
- assert ring_progress_bar.config.num_bars == 3
130
- assert len(ring_progress_bar.config.rings) == 3
131
-
132
- ring_progress_bar.remove_ring(1)
133
- assert ring_progress_bar.config.num_bars == 2
134
- assert len(ring_progress_bar.config.rings) == 2
135
- assert ring_progress_bar.rings[0].config.index == 0
136
- assert ring_progress_bar.rings[1].config.index == 1
137
-
138
-
139
- def test_bar_set_value(ring_progress_bar):
140
- ring_progress_bar.set_number_of_bars(5)
141
-
142
- assert ring_progress_bar.config.num_bars == 5
143
- assert len(ring_progress_bar.config.rings) == 5
144
- assert len(ring_progress_bar.rings) == 5
145
-
146
- ring_progress_bar.set_value([10, 20, 30, 40, 50])
147
- ring_values = [ring.config.value for ring in ring_progress_bar.rings]
148
- assert ring_values == [10, 20, 30, 40, 50]
149
-
150
- # update just one bar
151
- ring_progress_bar.set_value(90, 1)
152
- ring_values = [ring.config.value for ring in ring_progress_bar.rings]
153
- assert ring_values == [10, 90, 30, 40, 50]
154
-
155
-
156
- def test_bar_set_precision(ring_progress_bar):
157
- ring_progress_bar.set_number_of_bars(3)
158
-
159
- assert ring_progress_bar.config.num_bars == 3
160
- assert len(ring_progress_bar.config.rings) == 3
161
- assert len(ring_progress_bar.rings) == 3
162
-
163
- ring_progress_bar.set_precision(2)
164
- ring_precision = [ring.config.precision for ring in ring_progress_bar.rings]
165
- assert ring_precision == [2, 2, 2]
166
-
167
- ring_progress_bar.set_value([10.1234, 20.1234, 30.1234])
168
- ring_values = [ring.config.value for ring in ring_progress_bar.rings]
169
- assert ring_values == [10.12, 20.12, 30.12]
170
-
171
- ring_progress_bar.set_precision(4, 1)
172
- ring_precision = [ring.config.precision for ring in ring_progress_bar.rings]
173
- assert ring_precision == [2, 4, 2]
174
-
175
- ring_progress_bar.set_value([10.1234, 20.1234, 30.1234])
176
- ring_values = [ring.config.value for ring in ring_progress_bar.rings]
177
- assert ring_values == [10.12, 20.1234, 30.12]
178
-
179
-
180
- def test_set_min_max_value(ring_progress_bar):
181
- ring_progress_bar.set_number_of_bars(2)
182
-
183
- ring_progress_bar.set_min_max_values(0, 10)
184
- ring_min_values = [ring.config.min_value for ring in ring_progress_bar.rings]
185
- ring_max_values = [ring.config.max_value for ring in ring_progress_bar.rings]
186
-
187
- assert ring_min_values == [0, 0]
188
- assert ring_max_values == [10, 10]
189
-
190
- ring_progress_bar.set_value([5, 15])
191
- ring_values = [ring.config.value for ring in ring_progress_bar.rings]
192
- assert ring_values == [5, 10]
193
-
194
-
195
- def test_setup_colors_from_colormap(ring_progress_bar):
196
- ring_progress_bar.set_number_of_bars(5)
197
- ring_progress_bar.set_colors_from_map("viridis", "RGB")
198
-
199
- expected_colors = Colors.golden_angle_color("viridis", 5, "RGB")
200
- converted_colors = [ring.color.getRgb() for ring in ring_progress_bar.rings]
201
- ring_config_colors = [ring.config.color for ring in ring_progress_bar.rings]
202
-
203
- assert expected_colors == converted_colors
204
- assert ring_config_colors == expected_colors
205
-
206
-
207
- def get_colors_from_rings(rings):
208
- converted_colors = [ring.color.getRgb() for ring in rings]
209
- ring_config_colors = [ring.config.color for ring in rings]
210
- return converted_colors, ring_config_colors
211
-
212
-
213
- def test_set_colors_from_colormap_and_change_num_of_bars(ring_progress_bar):
214
- ring_progress_bar.set_number_of_bars(2)
215
- ring_progress_bar.set_colors_from_map("viridis", "RGB")
216
-
217
- expected_colors = Colors.golden_angle_color("viridis", 2, "RGB")
218
- converted_colors, ring_config_colors = get_colors_from_rings(ring_progress_bar.rings)
219
-
220
- assert expected_colors == converted_colors
221
- assert ring_config_colors == expected_colors
222
-
223
- # increase the number of bars to 6
224
- ring_progress_bar.set_number_of_bars(6)
225
- expected_colors = Colors.golden_angle_color("viridis", 6, "RGB")
226
- converted_colors, ring_config_colors = get_colors_from_rings(ring_progress_bar.rings)
227
-
228
- assert expected_colors == converted_colors
229
- assert ring_config_colors == expected_colors
230
-
231
- # decrease the number of bars to 3
232
- ring_progress_bar.set_number_of_bars(3)
233
- expected_colors = Colors.golden_angle_color("viridis", 3, "RGB")
234
- converted_colors, ring_config_colors = get_colors_from_rings(ring_progress_bar.rings)
235
-
236
- assert expected_colors == converted_colors
237
- assert ring_config_colors == expected_colors
238
-
239
-
240
- def test_set_colors_directly(ring_progress_bar):
241
- ring_progress_bar.set_number_of_bars(3)
242
-
243
- # setting as a list of rgb tuples
244
- colors = [(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)]
245
- ring_progress_bar.set_colors_directly(colors)
246
- converted_colors = get_colors_from_rings(ring_progress_bar.rings)[0]
247
-
248
- assert colors == converted_colors
249
-
250
- ring_progress_bar.set_colors_directly((255, 0, 0, 255), 1)
251
- converted_colors = get_colors_from_rings(ring_progress_bar.rings)[0]
252
-
253
- assert converted_colors == [(255, 0, 0, 255), (255, 0, 0, 255), (0, 0, 255, 255)]
254
-
255
-
256
- def test_set_line_width(ring_progress_bar):
257
- ring_progress_bar.set_number_of_bars(3)
258
-
259
- ring_progress_bar.set_line_widths(5)
260
- line_widths = [ring.config.line_width for ring in ring_progress_bar.rings]
261
-
262
- assert line_widths == [5, 5, 5]
263
-
264
- ring_progress_bar.set_line_widths([10, 20, 30])
265
- line_widths = [ring.config.line_width for ring in ring_progress_bar.rings]
266
-
267
- assert line_widths == [10, 20, 30]
268
-
269
- ring_progress_bar.set_line_widths(15, 1)
270
- line_widths = [ring.config.line_width for ring in ring_progress_bar.rings]
271
-
272
- assert line_widths == [10, 15, 30]
273
-
274
-
275
- def test_set_gap(ring_progress_bar):
276
- ring_progress_bar.set_number_of_bars(3)
277
- ring_progress_bar.set_gap(20)
278
-
279
- assert ring_progress_bar.config.gap == 20
280
-
281
-
282
- def test_auto_update(ring_progress_bar):
283
- ring_progress_bar.enable_auto_updates(True)
284
-
285
- scan_queue_status_scan_progress = {
286
- "queue": {
287
- "primary": {
288
- "info": [{"active_request_block": {"report_instructions": [{"scan_progress": 10}]}}]
289
- }
290
- }
291
- }
292
- meta = {}
293
-
294
- ring_progress_bar.on_scan_queue_status(scan_queue_status_scan_progress, meta)
295
-
296
- assert ring_progress_bar._auto_updates is True
297
- assert len(ring_progress_bar._rings) == 1
298
- assert ring_progress_bar._rings[0].config.connections == ProgressbarConnections(
299
- slot="on_scan_progress", endpoint=MessageEndpoints.scan_progress()
300
- )
301
-
302
- scan_queue_status_device_readback = {
303
- "queue": {
304
- "primary": {
305
- "info": [
306
- {
307
- "active_request_block": {
308
- "report_instructions": [
309
- {
310
- "readback": {
311
- "devices": ["samx", "samy"],
312
- "start": [1, 2],
313
- "end": [10, 20],
314
- }
315
- }
316
- ]
317
- }
318
- }
319
- ]
320
- }
321
- }
322
- }
323
- ring_progress_bar.on_scan_queue_status(scan_queue_status_device_readback, meta)
324
-
325
- assert ring_progress_bar._auto_updates is True
326
- assert len(ring_progress_bar._rings) == 2
327
- assert ring_progress_bar._rings[0].config.connections == ProgressbarConnections(
328
- slot="on_device_readback", endpoint=MessageEndpoints.device_readback("samx")
329
- )
330
- assert ring_progress_bar._rings[1].config.connections == ProgressbarConnections(
331
- slot="on_device_readback", endpoint=MessageEndpoints.device_readback("samy")
332
- )
333
-
334
- assert ring_progress_bar._rings[0].config.min_value == 1
335
- assert ring_progress_bar._rings[0].config.max_value == 10
336
- assert ring_progress_bar._rings[1].config.min_value == 2
337
- assert ring_progress_bar._rings[1].config.max_value == 20
@@ -1,52 +0,0 @@
1
- from bec_widgets.cli.rpc_register import RPCRegister
2
-
3
-
4
- class FakeObject:
5
- def __init__(self, gui_id):
6
- self.gui_id = gui_id
7
-
8
-
9
- def test_add_connection(rpc_register):
10
- obj1 = FakeObject("id1")
11
- obj2 = FakeObject("id2")
12
-
13
- rpc_register.add_rpc(obj1)
14
- rpc_register.add_rpc(obj2)
15
-
16
- all_connections = rpc_register.list_all_connections()
17
-
18
- assert len(all_connections) == 2
19
- assert all_connections["id1"] == obj1
20
- assert all_connections["id2"] == obj2
21
-
22
-
23
- def test_remove_connection(rpc_register):
24
-
25
- obj1 = FakeObject("id1")
26
- obj2 = FakeObject("id2")
27
-
28
- rpc_register.add_rpc(obj1)
29
- rpc_register.add_rpc(obj2)
30
-
31
- rpc_register.remove_rpc(obj1)
32
-
33
- all_connections = rpc_register.list_all_connections()
34
-
35
- assert len(all_connections) == 1
36
- assert all_connections["id2"] == obj2
37
-
38
-
39
- def test_reset_singleton(rpc_register):
40
- obj1 = FakeObject("id1")
41
- obj2 = FakeObject("id2")
42
-
43
- rpc_register.add_rpc(obj1)
44
- rpc_register.add_rpc(obj2)
45
-
46
- rpc_register.reset_singleton()
47
- rpc_register = RPCRegister()
48
-
49
- all_connections = rpc_register.list_all_connections()
50
-
51
- assert len(all_connections) == 0
52
- assert all_connections == {}
@@ -1,42 +0,0 @@
1
- from unittest import mock
2
-
3
- import pytest
4
- from bec_lib.service_config import ServiceConfig
5
-
6
- from bec_widgets.cli.server import _start_server
7
- from bec_widgets.widgets.figure import BECFigure
8
-
9
-
10
- @pytest.fixture
11
- def mocked_cli_server():
12
- with mock.patch("bec_widgets.cli.server.BECWidgetsCLIServer") as mock_server:
13
- with mock.patch("bec_widgets.cli.server.ServiceConfig") as mock_config:
14
- with mock.patch("bec_lib.logger.bec_logger.configure") as mock_logger:
15
- yield mock_server, mock_config, mock_logger
16
-
17
-
18
- def test_rpc_server_start_server_without_service_config(mocked_cli_server):
19
- """
20
- Test that the server is started with the correct arguments.
21
- """
22
- mock_server, mock_config, _ = mocked_cli_server
23
-
24
- _start_server("gui_id", BECFigure, None)
25
- mock_server.assert_called_once_with(gui_id="gui_id", config=mock_config(), gui_class=BECFigure)
26
-
27
-
28
- @pytest.mark.parametrize(
29
- "config, call_config",
30
- [
31
- ("/path/to/config.yml", {"config_path": "/path/to/config.yml"}),
32
- ({"key": "value"}, {"config": {"key": "value"}}),
33
- ],
34
- )
35
- def test_rpc_server_start_server_with_service_config(mocked_cli_server, config, call_config):
36
- """
37
- Test that the server is started with the correct arguments.
38
- """
39
- mock_server, mock_config, _ = mocked_cli_server
40
- config = mock_config(**call_config)
41
- _start_server("gui_id", BECFigure, config)
42
- mock_server.assert_called_once_with(gui_id="gui_id", config=config, gui_class=BECFigure)
@@ -1,7 +0,0 @@
1
- from bec_widgets.cli.rpc_wigdet_handler import RPCWidgetHandler
2
-
3
-
4
- def test_rpc_widget_handler():
5
- handler = RPCWidgetHandler()
6
- assert "BECFigure" in handler.widget_classes
7
- assert "RingProgressBar" in handler.widget_classes