bec-widgets 0.44.5__py3-none-any.whl → 0.45.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.
@@ -2,7 +2,7 @@
2
2
  from unittest.mock import MagicMock, patch
3
3
 
4
4
  import pytest
5
- from bec_lib.device import Positioner
5
+ from bec_lib.devicemanager import DeviceContainer
6
6
 
7
7
  from bec_widgets.examples import (
8
8
  MotorControlApp,
@@ -20,6 +20,8 @@ from bec_widgets.widgets import (
20
20
  )
21
21
  from bec_widgets.widgets.motor_control.motor_control import MotorActions
22
22
 
23
+ from .client_mocks import mocked_client
24
+
23
25
  CONFIG_DEFAULT = {
24
26
  "motor_control": {
25
27
  "motor_x": "samx",
@@ -52,81 +54,6 @@ CONFIG_DEFAULT = {
52
54
  ],
53
55
  }
54
56
 
55
- #######################################################
56
- # Client and devices fixture
57
- #######################################################
58
-
59
-
60
- class FakeDevice:
61
- """Fake minimal positioner class for testing."""
62
-
63
- def __init__(self, name, enabled=True, limits=None, read_value=1.0):
64
- super().__init__()
65
- self.name = name
66
- self.enabled = enabled
67
- self.read_value = read_value
68
- self.limits = limits or (-100, 100) # Default limits if not provided
69
-
70
- def read(self):
71
- """Simulates reading the current position of the device."""
72
- return {self.name: {"value": self.read_value}}
73
-
74
- def move(self, value, relative=False):
75
- """Simulates moving the device to a new position."""
76
- if relative:
77
- self.read_value += value
78
- else:
79
- self.read_value = value
80
- # Respect the limits
81
- self.read_value = max(min(self.read_value, self.limits[1]), self.limits[0])
82
-
83
- @property
84
- def readback(self):
85
- return MagicMock(get=MagicMock(return_value=self.read_value))
86
-
87
- def describe(self):
88
- """Describes the device."""
89
- return {self.name: {"source": self.name, "dtype": "number", "shape": []}}
90
-
91
-
92
- @pytest.fixture
93
- def mocked_client():
94
- client = MagicMock()
95
-
96
- # Setup the fake devices
97
- motors = {
98
- "samx": FakeDevice("samx", limits=[-10, 10], read_value=2.0),
99
- "samy": FakeDevice("samy", limits=[-5, 5], read_value=3.0),
100
- "aptrx": FakeDevice("aptrx", read_value=4.0),
101
- "aptry": FakeDevice("aptry", read_value=5.0),
102
- }
103
-
104
- client.device_manager.devices = MagicMock()
105
- client.device_manager.devices.__getitem__.side_effect = lambda x: motors.get(x, FakeDevice(x))
106
- client.device_manager.devices.enabled_devices = list(motors.values())
107
-
108
- # Mock the scans.mv method
109
- def mock_mv(*args, relative=False):
110
- # Extracting motor and value pairs
111
- for i in range(0, len(args), 2):
112
- motor = args[i]
113
- value = args[i + 1]
114
- motor.move(value, relative=relative)
115
- return MagicMock(wait=MagicMock()) # Simulate wait method of the move status object
116
-
117
- client.scans = MagicMock(mv=mock_mv)
118
-
119
- # Ensure isinstance check for Positioner passes
120
- original_isinstance = isinstance
121
-
122
- def isinstance_mock(obj, class_info):
123
- if class_info == Positioner:
124
- return True
125
- return original_isinstance(obj, class_info)
126
-
127
- with patch("builtins.isinstance", new=isinstance_mock):
128
- yield client
129
-
130
57
 
131
58
  #######################################################
132
59
  # Motor Thread
@@ -140,7 +67,7 @@ def motor_thread(mocked_client):
140
67
  def test_motor_thread_initialization(mocked_client):
141
68
  motor_thread = MotorThread(client=mocked_client)
142
69
  assert motor_thread.client == mocked_client
143
- assert isinstance(motor_thread.dev, MagicMock)
70
+ assert isinstance(motor_thread.dev, DeviceContainer)
144
71
 
145
72
 
146
73
  def test_get_all_motors_names(mocked_client):
@@ -175,12 +102,16 @@ def test_move_motor_absolute_by_run(mocked_client):
175
102
 
176
103
  def test_move_motor_relative_by_run(mocked_client):
177
104
  motor_thread = MotorThread(client=mocked_client)
105
+
106
+ initial_value = motor_thread.dev["samx"].read()["samx"]["value"]
107
+ move_value = 2.0
108
+ expected_value = initial_value + move_value
178
109
  motor_thread.motor = "samx"
179
- motor_thread.value = 2.0
110
+ motor_thread.value = move_value
180
111
  motor_thread.action = MotorActions.MOVE_RELATIVE
181
112
  motor_thread.run()
182
113
 
183
- assert mocked_client.device_manager.devices["samx"].read_value == 4.0
114
+ assert mocked_client.device_manager.devices["samx"].read_value == expected_value
184
115
 
185
116
 
186
117
  def test_motor_thread_move_absolute(motor_thread):
@@ -291,8 +222,12 @@ def test_absolute_initialization(motor_absolute_widget):
291
222
 
292
223
 
293
224
  def test_absolute_save_current_coordinates(motor_absolute_widget):
294
- motor_absolute_widget.client.device_manager["samx"].set_value(2.0)
295
- motor_absolute_widget.client.device_manager["samy"].set_value(3.0)
225
+ motor_x_value = motor_absolute_widget.client.device_manager.devices["samx"].read()["samx"][
226
+ "value"
227
+ ]
228
+ motor_y_value = motor_absolute_widget.client.device_manager.devices["samy"].read()["samy"][
229
+ "value"
230
+ ]
296
231
  motor_absolute_widget.change_motors("samx", "samy")
297
232
 
298
233
  emitted_coordinates = []
@@ -305,8 +240,7 @@ def test_absolute_save_current_coordinates(motor_absolute_widget):
305
240
  # Trigger saving current coordinates
306
241
  motor_absolute_widget.pushButton_save.click()
307
242
 
308
- # Default position of samx and samy are 2.0 and 3.0 respectively
309
- assert emitted_coordinates == [(2.0, 3.0)]
243
+ assert emitted_coordinates == [(motor_x_value, motor_y_value)]
310
244
 
311
245
 
312
246
  def test_absolute_set_absolute_coordinates(motor_absolute_widget):
tests/test_motor_map.py CHANGED
@@ -5,6 +5,8 @@ import pytest
5
5
 
6
6
  from bec_widgets.widgets import MotorMap
7
7
 
8
+ from .client_mocks import mocked_client
9
+
8
10
  CONFIG_DEFAULT = {
9
11
  "plot_settings": {
10
12
  "colormap": "Greys",
@@ -61,68 +63,6 @@ CONFIG_ONE_DEVICE = {
61
63
  }
62
64
 
63
65
 
64
- class FakeDevice:
65
- """Fake minimal positioner class for testing."""
66
-
67
- def __init__(self, name, enabled=True, limits=None, read_value=1.0):
68
- self.name = name
69
- self.enabled = enabled
70
- self.signals = {self.name: {"value": 1.0}}
71
- self.description = {self.name: {"source": self.name}}
72
- self.limits = limits if limits is not None else [0, 0]
73
- self.read_value = read_value
74
-
75
- def set_read_value(self, value):
76
- self.read_value = value
77
-
78
- def read(self):
79
- return {self.name: {"value": self.read_value}}
80
-
81
- def set_limits(self, limits):
82
- self.limits = limits
83
-
84
- def __contains__(self, item):
85
- return item == self.name
86
-
87
- @property
88
- def _hints(self):
89
- return [self.name]
90
-
91
- def set_value(self, fake_value: float = 1.0) -> None:
92
- """
93
- Setup fake value for device readout
94
- Args:
95
- fake_value(float): Desired fake value
96
- """
97
- self.signals[self.name]["value"] = fake_value
98
-
99
- def describe(self) -> dict:
100
- """
101
- Get the description of the device
102
- Returns:
103
- dict: Description of the device
104
- """
105
- return self.description
106
-
107
-
108
- @pytest.fixture
109
- def mocked_client():
110
- client = MagicMock()
111
-
112
- # Mocking specific motors with their limits
113
- motors = {
114
- "samx": FakeDevice("samx", limits=[-10, 10], read_value=2.0),
115
- "samy": FakeDevice("samy", limits=[-5, 5], read_value=3.0),
116
- "aptrx": FakeDevice("aptrx", read_value=4.0),
117
- "aptry": FakeDevice("aptry", read_value=5.0),
118
- }
119
-
120
- client.device_manager.devices = MagicMock()
121
- client.device_manager.devices.__getitem__.side_effect = lambda x: motors.get(x, FakeDevice(x))
122
-
123
- return client
124
-
125
-
126
66
  @pytest.fixture(scope="function")
127
67
  def motor_map(qtbot, mocked_client):
128
68
  widget = MotorMap(client=mocked_client)
@@ -144,12 +84,15 @@ def test_motor_limits_initialization(motor_map):
144
84
 
145
85
  def test_motor_initial_position(motor_map):
146
86
  motor_map.precision = 2
87
+
88
+ motor_map_dev = motor_map.client.device_manager.devices
89
+
147
90
  # Example test to check if motor initial positions are correctly initialized
148
91
  expected_positions = {
149
- ("samx", "samx"): 2.0,
150
- ("samy", "samy"): 3.0,
151
- ("aptrx", "aptrx"): 4.0,
152
- ("aptry", "aptry"): 5.0,
92
+ ("samx", "samx"): motor_map_dev["samx"].read()["samx"]["value"],
93
+ ("samy", "samy"): motor_map_dev["samy"].read()["samy"]["value"],
94
+ ("aptrx", "aptrx"): motor_map_dev["aptrx"].read()["aptrx"]["value"],
95
+ ("aptry", "aptry"): motor_map_dev["aptry"].read()["aptry"]["value"],
153
96
  }
154
97
  for (motor_name, entry), expected_position in expected_positions.items():
155
98
  actual_position = motor_map._get_motor_init_position(motor_name, entry)
tests/test_waveform1d.py CHANGED
@@ -81,8 +81,20 @@ def test_create_waveform1D_by_config(bec_figure):
81
81
  "source": "scan_segment",
82
82
  "signals": {
83
83
  "source": "scan_segment",
84
- "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None},
85
- "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None},
84
+ "x": {
85
+ "name": "samx",
86
+ "entry": "samx",
87
+ "unit": None,
88
+ "modifier": None,
89
+ "limits": None,
90
+ },
91
+ "y": {
92
+ "name": "bpm4i",
93
+ "entry": "bpm4i",
94
+ "unit": None,
95
+ "modifier": None,
96
+ "limits": None,
97
+ },
86
98
  },
87
99
  },
88
100
  "curve-custom": {
@@ -218,8 +230,8 @@ def test_change_curve_appearance_methods(bec_figure, qtbot):
218
230
  assert c1.config.source == "scan_segment"
219
231
  assert c1.config.signals.model_dump() == {
220
232
  "source": "scan_segment",
221
- "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None},
222
- "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None},
233
+ "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
234
+ "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None, "limits": None},
223
235
  }
224
236
 
225
237
 
@@ -246,8 +258,8 @@ def test_change_curve_appearance_args(bec_figure):
246
258
  assert c1.config.source == "scan_segment"
247
259
  assert c1.config.signals.model_dump() == {
248
260
  "source": "scan_segment",
249
- "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None},
250
- "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None},
261
+ "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
262
+ "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None, "limits": None},
251
263
  }
252
264
 
253
265
 
@@ -339,8 +351,14 @@ def test_curve_add_by_config(bec_figure):
339
351
  "source": "scan_segment",
340
352
  "signals": {
341
353
  "source": "scan_segment",
342
- "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None},
343
- "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None},
354
+ "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
355
+ "y": {
356
+ "name": "bpm4i",
357
+ "entry": "bpm4i",
358
+ "unit": None,
359
+ "modifier": None,
360
+ "limits": None,
361
+ },
344
362
  },
345
363
  }
346
364