bec-widgets 0.76.0__py3-none-any.whl → 0.77.0__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.
- CHANGELOG.md +42 -44
- PKG-INFO +2 -1
- bec_widgets/cli/client.py +73 -196
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +25 -4
- bec_widgets/utils/bec_connector.py +66 -8
- bec_widgets/utils/colors.py +38 -0
- bec_widgets/utils/generate_designer_plugin.py +15 -14
- bec_widgets/utils/yaml_dialog.py +27 -3
- bec_widgets/widgets/console/console.py +496 -0
- bec_widgets/widgets/dock/dock.py +2 -2
- bec_widgets/widgets/dock/dock_area.py +2 -2
- bec_widgets/widgets/figure/figure.py +149 -195
- bec_widgets/widgets/figure/plots/image/image.py +62 -49
- bec_widgets/widgets/figure/plots/image/image_item.py +4 -3
- bec_widgets/widgets/figure/plots/motor_map/motor_map.py +98 -29
- bec_widgets/widgets/figure/plots/plot_base.py +1 -1
- bec_widgets/widgets/figure/plots/waveform/waveform.py +7 -8
- bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +2 -2
- bec_widgets/widgets/ring_progress_bar/ring.py +3 -3
- bec_widgets/widgets/ring_progress_bar/ring_progress_bar.py +3 -3
- {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/METADATA +2 -1
- {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/RECORD +40 -38
- pyproject.toml +2 -1
- tests/end-2-end/test_bec_dock_rpc_e2e.py +16 -16
- tests/end-2-end/test_bec_figure_rpc_e2e.py +7 -7
- tests/end-2-end/test_rpc_register_e2e.py +8 -8
- tests/unit_tests/client_mocks.py +1 -0
- tests/unit_tests/test_bec_figure.py +49 -26
- tests/unit_tests/test_bec_motor_map.py +179 -41
- tests/unit_tests/test_color_validation.py +15 -0
- tests/unit_tests/test_device_input_base.py +1 -1
- tests/unit_tests/test_device_input_widgets.py +2 -0
- tests/unit_tests/test_generate_plugin.py +155 -0
- tests/unit_tests/test_motor_control.py +5 -4
- tests/unit_tests/test_plot_base.py +3 -3
- tests/unit_tests/test_waveform1d.py +18 -17
- tests/unit_tests/test_yaml_dialog.py +7 -7
- {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,100 +1,106 @@
|
|
1
|
+
import numpy as np
|
1
2
|
import pytest
|
2
3
|
|
3
4
|
from bec_widgets.widgets.figure.plots.motor_map.motor_map import BECMotorMap, MotorMapConfig
|
4
5
|
from bec_widgets.widgets.figure.plots.waveform.waveform_curve import SignalData
|
5
6
|
|
6
7
|
from .client_mocks import mocked_client
|
8
|
+
from .test_bec_figure import bec_figure
|
7
9
|
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
widget = BECMotorMap(client=mocked_client, gui_id="BECMotorMap_test")
|
12
|
-
# qtbot.addWidget(widget)
|
13
|
-
# qtbot.waitExposed(widget)
|
14
|
-
yield widget
|
11
|
+
def test_motor_map_init(bec_figure):
|
12
|
+
default_config = MotorMapConfig(widget_class="BECMotorMap")
|
15
13
|
|
14
|
+
mm = bec_figure.motor_map(config=default_config.model_dump())
|
15
|
+
default_config.gui_id = mm.gui_id
|
16
16
|
|
17
|
-
|
18
|
-
default_config = MotorMapConfig(widget_class="BECMotorMap", gui_id="BECMotorMap_test")
|
17
|
+
assert mm.config == default_config
|
19
18
|
|
20
|
-
assert bec_motor_map.config == default_config
|
21
19
|
|
20
|
+
def test_motor_map_change_motors(bec_figure):
|
21
|
+
mm = bec_figure.motor_map("samx", "samy")
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
assert mm.motor_x == "samx"
|
24
|
+
assert mm.motor_y == "samy"
|
25
|
+
assert mm.config.signals.x == SignalData(name="samx", entry="samx", limits=[-10, 10])
|
26
|
+
assert mm.config.signals.y == SignalData(name="samy", entry="samy", limits=[-5, 5])
|
25
27
|
|
26
|
-
|
27
|
-
assert bec_motor_map.config.signals.y == SignalData(name="samy", entry="samy", limits=[-5, 5])
|
28
|
+
mm.change_motors("samx", "samz")
|
28
29
|
|
30
|
+
assert mm.config.signals.x == SignalData(name="samx", entry="samx", limits=[-10, 10])
|
31
|
+
assert mm.config.signals.y == SignalData(name="samz", entry="samz", limits=[-8, 8])
|
29
32
|
|
30
|
-
|
33
|
+
|
34
|
+
def test_motor_map_get_limits(bec_figure):
|
35
|
+
mm = bec_figure.motor_map("samx", "samy")
|
31
36
|
expected_limits = {"samx": [-10, 10], "samy": [-5, 5]}
|
32
37
|
|
33
38
|
for motor_name, expected_limit in expected_limits.items():
|
34
|
-
actual_limit =
|
39
|
+
actual_limit = mm._get_motor_limit(motor_name)
|
35
40
|
assert actual_limit == expected_limit
|
36
41
|
|
37
42
|
|
38
|
-
def test_motor_map_get_init_position(
|
39
|
-
|
43
|
+
def test_motor_map_get_init_position(bec_figure):
|
44
|
+
mm = bec_figure.motor_map("samx", "samy")
|
45
|
+
mm.set_precision(2)
|
40
46
|
|
41
|
-
motor_map_dev =
|
47
|
+
motor_map_dev = mm.client.device_manager.devices
|
42
48
|
|
43
49
|
expected_positions = {
|
44
50
|
("samx", "samx"): motor_map_dev["samx"].read()["samx"]["value"],
|
45
51
|
("samy", "samy"): motor_map_dev["samy"].read()["samy"]["value"],
|
46
|
-
("aptrx", "aptrx"): motor_map_dev["aptrx"].read()["aptrx"]["value"],
|
47
|
-
("aptry", "aptry"): motor_map_dev["aptry"].read()["aptry"]["value"],
|
48
52
|
}
|
49
53
|
|
50
54
|
for (motor_name, entry), expected_position in expected_positions.items():
|
51
|
-
actual_position =
|
55
|
+
actual_position = mm._get_motor_init_position(motor_name, entry, 2)
|
52
56
|
assert actual_position == expected_position
|
53
57
|
|
54
58
|
|
55
|
-
def test_motor_movement_updates_position_and_database(
|
56
|
-
|
59
|
+
def test_motor_movement_updates_position_and_database(bec_figure):
|
60
|
+
mm = bec_figure.motor_map("samx", "samy")
|
61
|
+
motor_map_dev = mm.client.device_manager.devices
|
57
62
|
|
58
63
|
init_positions = {
|
59
64
|
"samx": [motor_map_dev["samx"].read()["samx"]["value"]],
|
60
65
|
"samy": [motor_map_dev["samy"].read()["samy"]["value"]],
|
61
66
|
}
|
62
67
|
|
63
|
-
|
68
|
+
mm.change_motors("samx", "samy")
|
64
69
|
|
65
|
-
assert
|
66
|
-
assert
|
70
|
+
assert mm.database_buffer["x"] == init_positions["samx"]
|
71
|
+
assert mm.database_buffer["y"] == init_positions["samy"]
|
67
72
|
|
68
73
|
# Simulate motor movement for 'samx' only
|
69
74
|
new_position_samx = 4.0
|
70
|
-
|
75
|
+
mm.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
|
71
76
|
|
72
77
|
init_positions["samx"].append(new_position_samx)
|
73
78
|
init_positions["samy"].append(init_positions["samy"][-1])
|
74
79
|
# Verify database update for 'samx'
|
75
|
-
assert
|
80
|
+
assert mm.database_buffer["x"] == init_positions["samx"]
|
76
81
|
|
77
82
|
# Verify 'samy' retains its last known position
|
78
|
-
assert
|
83
|
+
assert mm.database_buffer["y"] == init_positions["samy"]
|
79
84
|
|
80
85
|
|
81
|
-
def test_scatter_plot_rendering(
|
82
|
-
|
86
|
+
def test_scatter_plot_rendering(bec_figure):
|
87
|
+
mm = bec_figure.motor_map("samx", "samy")
|
88
|
+
motor_map_dev = mm.client.device_manager.devices
|
83
89
|
|
84
90
|
init_positions = {
|
85
91
|
"samx": [motor_map_dev["samx"].read()["samx"]["value"]],
|
86
92
|
"samy": [motor_map_dev["samy"].read()["samy"]["value"]],
|
87
93
|
}
|
88
94
|
|
89
|
-
|
95
|
+
mm.change_motors("samx", "samy")
|
90
96
|
|
91
97
|
# Simulate motor movement for 'samx' only
|
92
98
|
new_position_samx = 4.0
|
93
|
-
|
94
|
-
|
99
|
+
mm.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
|
100
|
+
mm._update_plot()
|
95
101
|
|
96
102
|
# Get the scatter plot item
|
97
|
-
scatter_plot_item =
|
103
|
+
scatter_plot_item = mm.plot_components["scatter"]
|
98
104
|
|
99
105
|
# Check the scatter plot item properties
|
100
106
|
assert len(scatter_plot_item.data) > 0, "Scatter plot data is empty"
|
@@ -106,16 +112,148 @@ def test_scatter_plot_rendering(bec_motor_map):
|
|
106
112
|
), "Scatter plot Y data should retain last known position"
|
107
113
|
|
108
114
|
|
109
|
-
def test_plot_visualization_consistency(
|
110
|
-
|
115
|
+
def test_plot_visualization_consistency(bec_figure):
|
116
|
+
mm = bec_figure.motor_map("samx", "samy")
|
117
|
+
mm.change_motors("samx", "samy")
|
111
118
|
# Simulate updating the plot with new data
|
112
|
-
|
113
|
-
|
114
|
-
|
119
|
+
mm.on_device_readback({"signals": {"samx": {"value": 5}}})
|
120
|
+
mm.on_device_readback({"signals": {"samy": {"value": 9}}})
|
121
|
+
mm._update_plot()
|
115
122
|
|
116
|
-
scatter_plot_item =
|
123
|
+
scatter_plot_item = mm.plot_components["scatter"]
|
117
124
|
|
118
125
|
# Check if the scatter plot reflects the new data correctly
|
119
126
|
assert (
|
120
127
|
scatter_plot_item.data["x"][-1] == 5 and scatter_plot_item.data["y"][-1] == 9
|
121
128
|
), "Plot not updated correctly with new data"
|
129
|
+
|
130
|
+
|
131
|
+
def test_change_background_value(bec_figure, qtbot):
|
132
|
+
mm = bec_figure.motor_map("samx", "samy")
|
133
|
+
|
134
|
+
assert mm.config.background_value == 25
|
135
|
+
assert np.all(mm.plot_components["limit_map"].image == 25.0)
|
136
|
+
|
137
|
+
mm.set_background_value(50)
|
138
|
+
qtbot.wait(200)
|
139
|
+
|
140
|
+
assert mm.config.background_value == 50
|
141
|
+
assert np.all(mm.plot_components["limit_map"].image == 50.0)
|
142
|
+
|
143
|
+
|
144
|
+
def test_motor_map_init_from_config(bec_figure):
|
145
|
+
config = {
|
146
|
+
"widget_class": "BECMotorMap",
|
147
|
+
"gui_id": "mm_id",
|
148
|
+
"parent_id": bec_figure.gui_id,
|
149
|
+
"row": 0,
|
150
|
+
"col": 0,
|
151
|
+
"axis": {
|
152
|
+
"title": "Motor position: (-0.0, 0.0)",
|
153
|
+
"title_size": None,
|
154
|
+
"x_label": "Motor X (samx)",
|
155
|
+
"x_label_size": None,
|
156
|
+
"y_label": "Motor Y (samy)",
|
157
|
+
"y_label_size": None,
|
158
|
+
"legend_label_size": None,
|
159
|
+
"x_scale": "linear",
|
160
|
+
"y_scale": "linear",
|
161
|
+
"x_lim": None,
|
162
|
+
"y_lim": None,
|
163
|
+
"x_grid": True,
|
164
|
+
"y_grid": True,
|
165
|
+
},
|
166
|
+
"signals": {
|
167
|
+
"source": "device_readback",
|
168
|
+
"x": {
|
169
|
+
"name": "samx",
|
170
|
+
"entry": "samx",
|
171
|
+
"unit": None,
|
172
|
+
"modifier": None,
|
173
|
+
"limits": [-10.0, 10.0],
|
174
|
+
},
|
175
|
+
"y": {
|
176
|
+
"name": "samy",
|
177
|
+
"entry": "samy",
|
178
|
+
"unit": None,
|
179
|
+
"modifier": None,
|
180
|
+
"limits": [-5.0, 5.0],
|
181
|
+
},
|
182
|
+
"z": None,
|
183
|
+
"dap": None,
|
184
|
+
},
|
185
|
+
"color": (255, 255, 255, 255),
|
186
|
+
"scatter_size": 5,
|
187
|
+
"max_points": 50,
|
188
|
+
"num_dim_points": 10,
|
189
|
+
"precision": 5,
|
190
|
+
"background_value": 50,
|
191
|
+
}
|
192
|
+
mm = bec_figure.motor_map(config=config)
|
193
|
+
config["gui_id"] = mm.gui_id
|
194
|
+
|
195
|
+
assert mm._config_dict == config
|
196
|
+
|
197
|
+
|
198
|
+
def test_motor_map_set_scatter_size(bec_figure, qtbot):
|
199
|
+
mm = bec_figure.motor_map("samx", "samy")
|
200
|
+
|
201
|
+
assert mm.config.scatter_size == 5
|
202
|
+
assert mm.plot_components["scatter"].opts["size"] == 5
|
203
|
+
|
204
|
+
mm.set_scatter_size(10)
|
205
|
+
qtbot.wait(200)
|
206
|
+
|
207
|
+
assert mm.config.scatter_size == 10
|
208
|
+
assert mm.plot_components["scatter"].opts["size"] == 10
|
209
|
+
|
210
|
+
|
211
|
+
def test_motor_map_change_precision(bec_figure):
|
212
|
+
mm = bec_figure.motor_map("samx", "samy")
|
213
|
+
|
214
|
+
assert mm.config.precision == 2
|
215
|
+
mm.set_precision(10)
|
216
|
+
assert mm.config.precision == 10
|
217
|
+
|
218
|
+
|
219
|
+
def test_motor_map_set_color(bec_figure, qtbot):
|
220
|
+
mm = bec_figure.motor_map("samx", "samy")
|
221
|
+
|
222
|
+
assert mm.config.color == (255, 255, 255, 255)
|
223
|
+
|
224
|
+
mm.set_color((0, 0, 0, 255))
|
225
|
+
qtbot.wait(200)
|
226
|
+
assert mm.config.color == (0, 0, 0, 255)
|
227
|
+
|
228
|
+
|
229
|
+
def test_motor_map_get_data_max_points(bec_figure, qtbot):
|
230
|
+
mm = bec_figure.motor_map("samx", "samy")
|
231
|
+
motor_map_dev = mm.client.device_manager.devices
|
232
|
+
|
233
|
+
init_positions = {
|
234
|
+
"samx": [motor_map_dev["samx"].read()["samx"]["value"]],
|
235
|
+
"samy": [motor_map_dev["samy"].read()["samy"]["value"]],
|
236
|
+
}
|
237
|
+
mm.on_device_readback({"signals": {"samx": {"value": 5.0}}})
|
238
|
+
mm.on_device_readback({"signals": {"samy": {"value": 9.0}}})
|
239
|
+
mm.on_device_readback({"signals": {"samx": {"value": 6.0}}})
|
240
|
+
mm.on_device_readback({"signals": {"samy": {"value": 7.0}}})
|
241
|
+
|
242
|
+
expected_x = [init_positions["samx"][-1], 5.0, 5.0, 6.0, 6.0]
|
243
|
+
expected_y = [init_positions["samy"][-1], init_positions["samy"][-1], 9.0, 9.0, 7.0]
|
244
|
+
get_data = mm.get_data()
|
245
|
+
|
246
|
+
assert mm.database_buffer["x"] == expected_x
|
247
|
+
assert mm.database_buffer["y"] == expected_y
|
248
|
+
assert get_data["x"] == expected_x
|
249
|
+
assert get_data["y"] == expected_y
|
250
|
+
|
251
|
+
mm.set_max_points(3)
|
252
|
+
qtbot.wait(200)
|
253
|
+
get_data = mm.get_data()
|
254
|
+
assert len(get_data["x"]) == 3
|
255
|
+
assert len(get_data["y"]) == 3
|
256
|
+
assert get_data["x"] == expected_x[-3:]
|
257
|
+
assert get_data["y"] == expected_y[-3:]
|
258
|
+
assert mm.database_buffer["x"] == expected_x[-3:]
|
259
|
+
assert mm.database_buffer["y"] == expected_y[-3:]
|
@@ -58,3 +58,18 @@ def test_color_validation_RGBA():
|
|
58
58
|
assert "The color values must be between 0 and 255 in RGBA format (R,G,B,A)" in str(
|
59
59
|
excinfo.value
|
60
60
|
)
|
61
|
+
|
62
|
+
|
63
|
+
def test_hex_to_rgba():
|
64
|
+
assert Colors.hex_to_rgba("#FF5733") == (255, 87, 51, 255)
|
65
|
+
assert Colors.hex_to_rgba("#FF573380") == (255, 87, 51, 128)
|
66
|
+
assert Colors.hex_to_rgba("#FF5733", 128) == (255, 87, 51, 128)
|
67
|
+
|
68
|
+
with pytest.raises(ValueError):
|
69
|
+
Colors.hex_to_rgba("#FF573")
|
70
|
+
|
71
|
+
|
72
|
+
def test_rgba_to_hex():
|
73
|
+
assert Colors.rgba_to_hex(255, 87, 51, 255) == "#FF5733FF"
|
74
|
+
assert Colors.rgba_to_hex(255, 87, 51, 128) == "#FF573380"
|
75
|
+
assert Colors.rgba_to_hex(255, 87, 51) == "#FF5733FF"
|
@@ -58,7 +58,7 @@ def test_device_input_base_set_default_device_error(device_input_base):
|
|
58
58
|
|
59
59
|
def test_device_input_base_get_device_list(device_input_base):
|
60
60
|
devices = device_input_base.get_device_list("FakePositioner")
|
61
|
-
assert devices == ["samx", "samy", "aptrx", "aptry"]
|
61
|
+
assert devices == ["samx", "samy", "samz", "aptrx", "aptry"]
|
62
62
|
|
63
63
|
|
64
64
|
def test_device_input_base_get_filters(device_input_base):
|
@@ -56,6 +56,7 @@ def test_device_input_combobox_init(device_input_combobox):
|
|
56
56
|
assert device_input_combobox.devices == [
|
57
57
|
"samx",
|
58
58
|
"samy",
|
59
|
+
"samz",
|
59
60
|
"aptrx",
|
60
61
|
"aptry",
|
61
62
|
"gauss_bpm",
|
@@ -141,6 +142,7 @@ def test_device_input_line_edit_init(device_input_line_edit):
|
|
141
142
|
assert device_input_line_edit.devices == [
|
142
143
|
"samx",
|
143
144
|
"samy",
|
145
|
+
"samz",
|
144
146
|
"aptrx",
|
145
147
|
"aptry",
|
146
148
|
"gauss_bpm",
|
@@ -0,0 +1,155 @@
|
|
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)
|
@@ -74,7 +74,7 @@ def test_motor_thread_initialization(mocked_client):
|
|
74
74
|
def test_get_all_motors_names(mocked_client):
|
75
75
|
motor_thread = MotorThread(client=mocked_client)
|
76
76
|
motor_names = motor_thread.get_all_motors_names()
|
77
|
-
expected_names = ["samx", "samy", "aptrx", "aptry"]
|
77
|
+
expected_names = ["samx", "samy", "samz", "aptrx", "aptry"]
|
78
78
|
assert sorted(motor_names) == sorted(expected_names)
|
79
79
|
assert all(name in motor_names for name in expected_names)
|
80
80
|
assert len(motor_names) == len(expected_names) # Ensure only these motors are returned
|
@@ -155,11 +155,12 @@ def motor_selection_widget(qtbot, mocked_client, motor_thread):
|
|
155
155
|
|
156
156
|
|
157
157
|
def test_initialization_and_population(motor_selection_widget):
|
158
|
-
assert motor_selection_widget.comboBox_motor_x.count() ==
|
158
|
+
assert motor_selection_widget.comboBox_motor_x.count() == 5
|
159
159
|
assert motor_selection_widget.comboBox_motor_x.itemText(0) == "samx"
|
160
160
|
assert motor_selection_widget.comboBox_motor_y.itemText(1) == "samy"
|
161
|
-
assert motor_selection_widget.
|
162
|
-
assert motor_selection_widget.
|
161
|
+
assert motor_selection_widget.comboBox_motor_y.itemText(2) == "samz"
|
162
|
+
assert motor_selection_widget.comboBox_motor_x.itemText(3) == "aptrx"
|
163
|
+
assert motor_selection_widget.comboBox_motor_y.itemText(4) == "aptry"
|
163
164
|
|
164
165
|
|
165
166
|
def test_selection_and_signal_emission(motor_selection_widget):
|
@@ -9,14 +9,14 @@ from .test_bec_figure import bec_figure
|
|
9
9
|
|
10
10
|
|
11
11
|
def test_init_plot_base(bec_figure):
|
12
|
-
plot_base = bec_figure.add_widget(widget_type="
|
12
|
+
plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
|
13
13
|
assert plot_base is not None
|
14
14
|
assert plot_base.config.widget_class == "BECPlotBase"
|
15
15
|
assert plot_base.config.gui_id == "test_plot"
|
16
16
|
|
17
17
|
|
18
18
|
def test_plot_base_axes_by_separate_methods(bec_figure):
|
19
|
-
plot_base = bec_figure.add_widget(widget_type="
|
19
|
+
plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
|
20
20
|
|
21
21
|
plot_base.set_title("Test Title")
|
22
22
|
plot_base.set_x_label("Test x Label")
|
@@ -66,7 +66,7 @@ def test_plot_base_axes_by_separate_methods(bec_figure):
|
|
66
66
|
|
67
67
|
|
68
68
|
def test_plot_base_axes_added_by_kwargs(bec_figure):
|
69
|
-
plot_base = bec_figure.add_widget(widget_type="
|
69
|
+
plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
|
70
70
|
|
71
71
|
plot_base.set(
|
72
72
|
title="Test Title",
|