bec-ipython-client 3.70.0__py3-none-any.whl → 3.86.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bec-ipython-client might be problematic. Click here for more details.
- .gitignore +3 -0
- PKG-INFO +1 -1
- bec_ipython_client/callbacks/device_progress.py +11 -6
- bec_ipython_client/callbacks/ipython_live_updates.py +46 -18
- bec_ipython_client/callbacks/live_table.py +36 -11
- bec_ipython_client/callbacks/move_device.py +121 -59
- bec_ipython_client/callbacks/utils.py +5 -23
- bec_ipython_client/main.py +71 -6
- bec_ipython_client/signals.py +9 -3
- {bec_ipython_client-3.70.0.dist-info → bec_ipython_client-3.86.1.dist-info}/METADATA +1 -1
- bec_ipython_client-3.86.1.dist-info/RECORD +44 -0
- {bec_ipython_client-3.70.0.dist-info → bec_ipython_client-3.86.1.dist-info}/WHEEL +1 -1
- demo.py +2 -1
- pyproject.toml +1 -1
- tests/client_tests/conftest.py +19 -0
- tests/client_tests/test_bec_client.py +31 -0
- tests/client_tests/test_ipython_live_updates.py +259 -68
- tests/client_tests/test_live_table.py +0 -1
- tests/client_tests/test_move_callback.py +112 -70
- tests/end-2-end/_ensure_requirements_container.py +3 -3
- tests/end-2-end/test_procedures_e2e.py +26 -17
- tests/end-2-end/test_scans_e2e.py +19 -13
- tests/end-2-end/test_scans_lib_e2e.py +18 -12
- bec_ipython_client-3.70.0.dist-info/RECORD +0 -43
- {bec_ipython_client-3.70.0.dist-info → bec_ipython_client-3.86.1.dist-info}/entry_points.txt +0 -0
|
@@ -7,34 +7,94 @@ from bec_lib import messages
|
|
|
7
7
|
from bec_lib.queue_items import QueueItem
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
@pytest.
|
|
11
|
-
def
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def queue_elements(bec_client_mock):
|
|
12
12
|
client = bec_client_mock
|
|
13
|
-
live_updates = IPythonLiveUpdates(client)
|
|
14
13
|
request_msg = messages.ScanQueueMessage(
|
|
15
14
|
scan_type="grid_scan",
|
|
16
15
|
parameter={"args": {"samx": (-5, 5, 3)}, "kwargs": {}},
|
|
17
16
|
queue="primary",
|
|
18
17
|
metadata={"RID": "something"},
|
|
19
18
|
)
|
|
19
|
+
request_block = messages.RequestBlock(
|
|
20
|
+
msg=request_msg,
|
|
21
|
+
RID="req_id",
|
|
22
|
+
scan_motors=["samx"],
|
|
23
|
+
report_instructions=[],
|
|
24
|
+
readout_priority={"monitored": ["samx"]},
|
|
25
|
+
is_scan=True,
|
|
26
|
+
scan_number=1,
|
|
27
|
+
scan_id="scan_id",
|
|
28
|
+
)
|
|
20
29
|
queue = QueueItem(
|
|
21
30
|
scan_manager=client.queue,
|
|
22
31
|
queue_id="queue_id",
|
|
23
|
-
request_blocks=[
|
|
32
|
+
request_blocks=[request_block],
|
|
24
33
|
status="PENDING",
|
|
25
34
|
active_request_block={},
|
|
26
35
|
scan_id=["scan_id"],
|
|
27
36
|
)
|
|
28
|
-
|
|
37
|
+
return queue, request_block, request_msg
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.fixture
|
|
41
|
+
def sample_request_msg():
|
|
42
|
+
return messages.ScanQueueMessage(
|
|
43
|
+
scan_type="grid_scan",
|
|
44
|
+
parameter={"args": {"samx": (-5, 5, 3)}, "kwargs": {}},
|
|
45
|
+
queue="primary",
|
|
46
|
+
metadata={"RID": "something"},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.fixture
|
|
51
|
+
def sample_request_block(sample_request_msg):
|
|
52
|
+
return messages.RequestBlock(
|
|
53
|
+
msg=sample_request_msg,
|
|
54
|
+
RID="req_id",
|
|
55
|
+
scan_motors=["samx"],
|
|
56
|
+
report_instructions=[],
|
|
57
|
+
readout_priority={"monitored": ["samx"]},
|
|
58
|
+
is_scan=True,
|
|
59
|
+
scan_number=1,
|
|
60
|
+
scan_id="scan_id",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.fixture
|
|
65
|
+
def sample_queue_info_entry(sample_request_block):
|
|
66
|
+
return messages.QueueInfoEntry(
|
|
67
|
+
queue_id="test_queue_id",
|
|
68
|
+
scan_id=["scan_id"],
|
|
69
|
+
is_scan=[True],
|
|
70
|
+
request_blocks=[sample_request_block],
|
|
71
|
+
scan_number=[1],
|
|
72
|
+
status="RUNNING",
|
|
73
|
+
active_request_block=None,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.fixture
|
|
78
|
+
def sample_scan_queue_status(sample_queue_info_entry):
|
|
79
|
+
return messages.ScanQueueStatus(info=[sample_queue_info_entry], status="RUNNING")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@pytest.mark.timeout(20)
|
|
83
|
+
def test_live_updates_process_queue_pending(bec_client_mock, queue_elements):
|
|
84
|
+
client = bec_client_mock
|
|
85
|
+
live_updates = IPythonLiveUpdates(client)
|
|
86
|
+
queue, request_block, request_msg = queue_elements
|
|
87
|
+
|
|
88
|
+
client.queue.queue_storage.current_scan_queue = {
|
|
89
|
+
"primary": messages.ScanQueueStatus(info=[], status="RUNNING")
|
|
90
|
+
}
|
|
29
91
|
with mock.patch.object(queue, "_update_with_buffer"):
|
|
30
92
|
with mock.patch(
|
|
31
93
|
"bec_lib.queue_items.QueueItem.queue_position", new_callable=mock.PropertyMock
|
|
32
94
|
) as queue_pos:
|
|
33
95
|
queue_pos.return_value = 2
|
|
34
96
|
with mock.patch.object(
|
|
35
|
-
live_updates,
|
|
36
|
-
"_available_req_blocks",
|
|
37
|
-
return_value=[{"report_instructions": [], "content": {"scan_type": "grid_scan"}}],
|
|
97
|
+
live_updates, "_available_req_blocks", return_value=[request_block]
|
|
38
98
|
):
|
|
39
99
|
with mock.patch.object(live_updates, "_process_report_instructions") as process:
|
|
40
100
|
with mock.patch("builtins.print") as prt:
|
|
@@ -45,39 +105,30 @@ def test_live_updates_process_queue_pending(bec_client_mock):
|
|
|
45
105
|
|
|
46
106
|
|
|
47
107
|
@pytest.mark.timeout(20)
|
|
48
|
-
def test_live_updates_process_queue_running(bec_client_mock):
|
|
108
|
+
def test_live_updates_process_queue_running(bec_client_mock, queue_elements):
|
|
49
109
|
client = bec_client_mock
|
|
50
110
|
live_updates = IPythonLiveUpdates(client)
|
|
51
|
-
request_msg =
|
|
52
|
-
scan_type="grid_scan",
|
|
53
|
-
parameter={"args": {"samx": (-5, 5, 3)}, "kwargs": {}},
|
|
54
|
-
queue="primary",
|
|
55
|
-
metadata={"RID": "something"},
|
|
56
|
-
)
|
|
111
|
+
_, request_block, request_msg = queue_elements
|
|
57
112
|
queue = QueueItem(
|
|
58
113
|
scan_manager=client.queue,
|
|
59
114
|
queue_id="queue_id",
|
|
60
|
-
request_blocks=[
|
|
115
|
+
request_blocks=[request_block],
|
|
61
116
|
status="RUNNING",
|
|
62
117
|
active_request_block={},
|
|
63
118
|
scan_id=["scan_id"],
|
|
64
119
|
)
|
|
65
120
|
live_updates._active_request = request_msg
|
|
66
|
-
|
|
121
|
+
request_block.report_instructions = [{"wait_table": 10}]
|
|
122
|
+
client.queue.queue_storage.current_scan_queue = {
|
|
123
|
+
"primary": messages.ScanQueueStatus(info=[], status="RUNNING")
|
|
124
|
+
}
|
|
67
125
|
with mock.patch.object(queue, "_update_with_buffer"):
|
|
68
126
|
with mock.patch(
|
|
69
127
|
"bec_lib.queue_items.QueueItem.queue_position", new_callable=mock.PropertyMock
|
|
70
128
|
) as queue_pos:
|
|
71
129
|
queue_pos.return_value = 2
|
|
72
130
|
with mock.patch.object(
|
|
73
|
-
live_updates,
|
|
74
|
-
"_available_req_blocks",
|
|
75
|
-
return_value=[
|
|
76
|
-
{
|
|
77
|
-
"report_instructions": [{"wait_table": 10}],
|
|
78
|
-
"content": {"scan_type": "grid_scan"},
|
|
79
|
-
}
|
|
80
|
-
],
|
|
131
|
+
live_updates, "_available_req_blocks", return_value=[request_block]
|
|
81
132
|
):
|
|
82
133
|
with mock.patch.object(live_updates, "_process_instruction") as process:
|
|
83
134
|
with mock.patch("builtins.print") as prt:
|
|
@@ -88,37 +139,19 @@ def test_live_updates_process_queue_running(bec_client_mock):
|
|
|
88
139
|
|
|
89
140
|
|
|
90
141
|
@pytest.mark.timeout(20)
|
|
91
|
-
def test_live_updates_process_queue_without_status(bec_client_mock):
|
|
142
|
+
def test_live_updates_process_queue_without_status(bec_client_mock, queue_elements):
|
|
92
143
|
client = bec_client_mock
|
|
93
144
|
live_updates = IPythonLiveUpdates(client)
|
|
94
|
-
request_msg =
|
|
95
|
-
scan_type="grid_scan",
|
|
96
|
-
parameter={"args": {"samx": (-5, 5, 3)}, "kwargs": {}},
|
|
97
|
-
queue="primary",
|
|
98
|
-
metadata={"RID": "something"},
|
|
99
|
-
)
|
|
100
|
-
queue = QueueItem(
|
|
101
|
-
scan_manager=client.queue,
|
|
102
|
-
queue_id="queue_id",
|
|
103
|
-
request_blocks=[request_msg],
|
|
104
|
-
status=None,
|
|
105
|
-
active_request_block={},
|
|
106
|
-
scan_id=["scan_id"],
|
|
107
|
-
)
|
|
145
|
+
queue, _, request_msg = queue_elements
|
|
108
146
|
with mock.patch.object(queue, "_update_with_buffer"):
|
|
109
147
|
assert live_updates._process_queue(queue, request_msg, "req_id") is False
|
|
110
148
|
|
|
111
149
|
|
|
112
150
|
@pytest.mark.timeout(20)
|
|
113
|
-
def test_live_updates_process_queue_without_queue_number(bec_client_mock):
|
|
151
|
+
def test_live_updates_process_queue_without_queue_number(bec_client_mock, queue_elements):
|
|
114
152
|
client = bec_client_mock
|
|
115
153
|
live_updates = IPythonLiveUpdates(client)
|
|
116
|
-
request_msg =
|
|
117
|
-
scan_type="grid_scan",
|
|
118
|
-
parameter={"args": {"samx": (-5, 5, 3)}, "kwargs": {}},
|
|
119
|
-
queue="primary",
|
|
120
|
-
metadata={"RID": "something"},
|
|
121
|
-
)
|
|
154
|
+
queue, _, request_msg = queue_elements
|
|
122
155
|
|
|
123
156
|
with mock.patch(
|
|
124
157
|
"bec_lib.queue_items.QueueItem.queue_position", new_callable=mock.PropertyMock
|
|
@@ -136,24 +169,182 @@ def test_live_updates_process_queue_without_queue_number(bec_client_mock):
|
|
|
136
169
|
assert live_updates._process_queue(queue, request_msg, "req_id") is False
|
|
137
170
|
|
|
138
171
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
#
|
|
150
|
-
|
|
151
|
-
#
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
172
|
+
@pytest.mark.timeout(20)
|
|
173
|
+
def test_available_req_blocks(bec_client_mock, queue_elements):
|
|
174
|
+
client = bec_client_mock
|
|
175
|
+
live_updates = IPythonLiveUpdates(client)
|
|
176
|
+
queue, request_block, request_msg = queue_elements
|
|
177
|
+
|
|
178
|
+
# Test with matching RID
|
|
179
|
+
available_blocks = live_updates._available_req_blocks(queue, request_msg)
|
|
180
|
+
assert (
|
|
181
|
+
len(available_blocks) == 0
|
|
182
|
+
) # request_block.RID is "req_id", request_msg.metadata["RID"] is "something"
|
|
183
|
+
|
|
184
|
+
# Test with correct RID
|
|
185
|
+
request_block.RID = "something"
|
|
186
|
+
available_blocks = live_updates._available_req_blocks(queue, request_msg)
|
|
187
|
+
assert len(available_blocks) == 1
|
|
188
|
+
assert available_blocks[0] == request_block
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@pytest.mark.timeout(20)
|
|
192
|
+
def test_available_req_blocks_multiple_blocks(bec_client_mock):
|
|
193
|
+
client = bec_client_mock
|
|
194
|
+
live_updates = IPythonLiveUpdates(client)
|
|
195
|
+
|
|
196
|
+
request_msg = messages.ScanQueueMessage(
|
|
197
|
+
scan_type="grid_scan",
|
|
198
|
+
parameter={"args": {"samx": (-5, 5, 3)}, "kwargs": {}},
|
|
199
|
+
queue="primary",
|
|
200
|
+
metadata={"RID": "test_rid"},
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
request_block1 = messages.RequestBlock(
|
|
204
|
+
msg=request_msg,
|
|
205
|
+
RID="test_rid",
|
|
206
|
+
scan_motors=["samx"],
|
|
207
|
+
report_instructions=[],
|
|
208
|
+
readout_priority={"monitored": ["samx"]},
|
|
209
|
+
is_scan=True,
|
|
210
|
+
scan_number=1,
|
|
211
|
+
scan_id="scan_id_1",
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
request_block2 = messages.RequestBlock(
|
|
215
|
+
msg=request_msg,
|
|
216
|
+
RID="test_rid",
|
|
217
|
+
scan_motors=["samy"],
|
|
218
|
+
report_instructions=[],
|
|
219
|
+
readout_priority={"monitored": ["samy"]},
|
|
220
|
+
is_scan=True,
|
|
221
|
+
scan_number=2,
|
|
222
|
+
scan_id="scan_id_2",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
request_block3 = messages.RequestBlock(
|
|
226
|
+
msg=request_msg,
|
|
227
|
+
RID="different_rid",
|
|
228
|
+
scan_motors=["samz"],
|
|
229
|
+
report_instructions=[],
|
|
230
|
+
readout_priority={"monitored": ["samz"]},
|
|
231
|
+
is_scan=True,
|
|
232
|
+
scan_number=3,
|
|
233
|
+
scan_id="scan_id_3",
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
queue = QueueItem(
|
|
237
|
+
scan_manager=client.queue,
|
|
238
|
+
queue_id="queue_id",
|
|
239
|
+
request_blocks=[request_block1, request_block2, request_block3],
|
|
240
|
+
status="RUNNING",
|
|
241
|
+
active_request_block={},
|
|
242
|
+
scan_id=["scan_id_1", "scan_id_2", "scan_id_3"],
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
available_blocks = live_updates._available_req_blocks(queue, request_msg)
|
|
246
|
+
assert len(available_blocks) == 2
|
|
247
|
+
assert request_block1 in available_blocks
|
|
248
|
+
assert request_block2 in available_blocks
|
|
249
|
+
assert request_block3 not in available_blocks
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@pytest.mark.timeout(20)
|
|
253
|
+
def test_element_in_queue_no_queue(bec_client_mock):
|
|
254
|
+
client = bec_client_mock
|
|
255
|
+
live_updates = IPythonLiveUpdates(client)
|
|
256
|
+
|
|
257
|
+
# Test when client.queue is None
|
|
258
|
+
client.queue = None
|
|
259
|
+
assert live_updates._element_in_queue() is False
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
@pytest.mark.timeout(20)
|
|
263
|
+
def test_element_in_queue_no_current_scan_queue(bec_client_mock):
|
|
264
|
+
client = bec_client_mock
|
|
265
|
+
live_updates = IPythonLiveUpdates(client)
|
|
266
|
+
|
|
267
|
+
# Test when current_scan_queue is None
|
|
268
|
+
client.queue.queue_storage.current_scan_queue = None
|
|
269
|
+
assert live_updates._element_in_queue() is False
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
@pytest.mark.timeout(20)
|
|
273
|
+
def test_element_in_queue_no_primary_queue(bec_client_mock):
|
|
274
|
+
client = bec_client_mock
|
|
275
|
+
live_updates = IPythonLiveUpdates(client)
|
|
276
|
+
|
|
277
|
+
# Test when primary queue doesn't exist
|
|
278
|
+
scan_queue_status = messages.ScanQueueStatus(info=[], status="RUNNING")
|
|
279
|
+
client.queue.queue_storage.current_scan_queue = {"secondary": scan_queue_status}
|
|
280
|
+
assert live_updates._element_in_queue() is False
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
@pytest.mark.timeout(20)
|
|
284
|
+
def test_element_in_queue_no_queue_info(bec_client_mock):
|
|
285
|
+
client = bec_client_mock
|
|
286
|
+
live_updates = IPythonLiveUpdates(client)
|
|
287
|
+
|
|
288
|
+
# Test when queue_info is empty
|
|
289
|
+
scan_queue_status = messages.ScanQueueStatus(info=[], status="RUNNING")
|
|
290
|
+
client.queue.queue_storage.current_scan_queue = {"primary": scan_queue_status}
|
|
291
|
+
assert live_updates._element_in_queue() is False
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@pytest.mark.timeout(20)
|
|
295
|
+
def test_element_in_queue_no_current_queue(bec_client_mock, sample_scan_queue_status):
|
|
296
|
+
client = bec_client_mock
|
|
297
|
+
live_updates = IPythonLiveUpdates(client)
|
|
298
|
+
|
|
299
|
+
# Test when _current_queue is None
|
|
300
|
+
live_updates._current_queue = None
|
|
301
|
+
client.queue.queue_storage.current_scan_queue = {"primary": sample_scan_queue_status}
|
|
302
|
+
assert live_updates._element_in_queue() is False
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@pytest.mark.timeout(20)
|
|
306
|
+
def test_element_in_queue_queue_id_not_in_info(bec_client_mock, sample_request_block):
|
|
307
|
+
client = bec_client_mock
|
|
308
|
+
live_updates = IPythonLiveUpdates(client)
|
|
309
|
+
|
|
310
|
+
# Test when queue_id is not in info
|
|
311
|
+
current_queue = mock.MagicMock()
|
|
312
|
+
current_queue.queue_id = "my_queue_id"
|
|
313
|
+
live_updates._current_queue = current_queue
|
|
314
|
+
|
|
315
|
+
queue_info_entry = messages.QueueInfoEntry(
|
|
316
|
+
queue_id="different_queue_id",
|
|
317
|
+
scan_id=["scan_id"],
|
|
318
|
+
is_scan=[True],
|
|
319
|
+
request_blocks=[sample_request_block],
|
|
320
|
+
scan_number=[1],
|
|
321
|
+
status="RUNNING",
|
|
322
|
+
active_request_block=None,
|
|
323
|
+
)
|
|
324
|
+
scan_queue_status = messages.ScanQueueStatus(info=[queue_info_entry], status="RUNNING")
|
|
325
|
+
client.queue.queue_storage.current_scan_queue = {"primary": scan_queue_status}
|
|
326
|
+
assert live_updates._element_in_queue() is False
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@pytest.mark.timeout(20)
|
|
330
|
+
def test_element_in_queue_queue_id_in_info(bec_client_mock, sample_request_block):
|
|
331
|
+
client = bec_client_mock
|
|
332
|
+
live_updates = IPythonLiveUpdates(client)
|
|
333
|
+
|
|
334
|
+
# Test when queue_id is in info (should return True)
|
|
335
|
+
current_queue = mock.MagicMock()
|
|
336
|
+
current_queue.queue_id = "my_queue_id"
|
|
337
|
+
live_updates._current_queue = current_queue
|
|
338
|
+
|
|
339
|
+
queue_info_entry = messages.QueueInfoEntry(
|
|
340
|
+
queue_id="my_queue_id",
|
|
341
|
+
scan_id=["scan_id"],
|
|
342
|
+
is_scan=[True],
|
|
343
|
+
request_blocks=[sample_request_block],
|
|
344
|
+
scan_number=[1],
|
|
345
|
+
status="RUNNING",
|
|
346
|
+
active_request_block=None,
|
|
347
|
+
)
|
|
348
|
+
scan_queue_status = messages.ScanQueueStatus(info=[queue_info_entry], status="RUNNING")
|
|
349
|
+
client.queue.queue_storage.current_scan_queue = {"primary": scan_queue_status}
|
|
350
|
+
assert live_updates._element_in_queue() is True
|
|
@@ -107,7 +107,6 @@ class TestLiveTable:
|
|
|
107
107
|
)
|
|
108
108
|
def test_get_devices_from_scan_data(self, bec_client_mock, request_msg, scan_report_devices):
|
|
109
109
|
client = bec_client_mock
|
|
110
|
-
client.start()
|
|
111
110
|
data = messages.ScanMessage(
|
|
112
111
|
point_id=0, scan_id="", data={}, metadata={"scan_report_devices": scan_report_devices}
|
|
113
112
|
)
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import collections
|
|
2
|
+
import time
|
|
2
3
|
from unittest import mock
|
|
3
4
|
|
|
4
5
|
import pytest
|
|
5
6
|
|
|
6
7
|
from bec_ipython_client.callbacks.move_device import (
|
|
7
8
|
LiveUpdatesReadbackProgressbar,
|
|
8
|
-
|
|
9
|
+
ReadbackDataHandler,
|
|
9
10
|
)
|
|
10
11
|
from bec_lib import messages
|
|
11
12
|
from bec_lib.endpoints import MessageEndpoints
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
@pytest.fixture
|
|
15
|
-
def
|
|
16
|
-
with mock.patch.object(bec_client_mock.device_manager, "connector"):
|
|
17
|
-
yield
|
|
16
|
+
def readback_data_handler(bec_client_mock, connected_connector):
|
|
17
|
+
with mock.patch.object(bec_client_mock.device_manager, "connector", connected_connector):
|
|
18
|
+
yield ReadbackDataHandler(
|
|
19
|
+
bec_client_mock.device_manager, ["samx", "samy"], request_id="something"
|
|
20
|
+
)
|
|
18
21
|
|
|
19
22
|
|
|
20
23
|
def test_move_callback(bec_client_mock):
|
|
@@ -33,30 +36,25 @@ def test_move_callback(bec_client_mock):
|
|
|
33
36
|
return readback[0]
|
|
34
37
|
|
|
35
38
|
req_done = collections.deque()
|
|
36
|
-
|
|
37
|
-
device="samx", success=True, metadata={"RID": "something"}
|
|
38
|
-
)
|
|
39
|
-
req_done.extend([[None], [None], [None], [msg_acc]])
|
|
39
|
+
req_done.extend([{"samx": (False, False)}, {"samx": (False, False)}, {"samx": (True, True)}])
|
|
40
40
|
|
|
41
41
|
def mock_req_msg(*args):
|
|
42
42
|
if len(req_done) > 1:
|
|
43
43
|
return req_done.popleft()
|
|
44
44
|
return req_done[0]
|
|
45
45
|
|
|
46
|
-
with mock.patch("bec_ipython_client.callbacks.move_device.check_alarms")
|
|
47
|
-
with mock.patch.object(
|
|
48
|
-
with mock.patch.object(
|
|
46
|
+
with mock.patch("bec_ipython_client.callbacks.move_device.check_alarms"):
|
|
47
|
+
with mock.patch.object(LiveUpdatesReadbackProgressbar, "wait_for_request_acceptance"):
|
|
48
|
+
with mock.patch.object(
|
|
49
|
+
LiveUpdatesReadbackProgressbar, "_print_client_msgs_asap"
|
|
50
|
+
) as mock_client_msgs:
|
|
49
51
|
with mock.patch.object(
|
|
50
|
-
LiveUpdatesReadbackProgressbar, "
|
|
51
|
-
) as
|
|
52
|
-
with mock.patch.object(
|
|
53
|
-
|
|
54
|
-
) as mock_client_msgs_all:
|
|
55
|
-
with mock.patch.object(
|
|
56
|
-
ReadbackDataMixin, "get_device_values", mock_readback
|
|
57
|
-
):
|
|
52
|
+
LiveUpdatesReadbackProgressbar, "_print_client_msgs_all"
|
|
53
|
+
) as mock_client_msgs_all:
|
|
54
|
+
with mock.patch.object(ReadbackDataHandler, "get_device_values", mock_readback):
|
|
55
|
+
with mock.patch.object(ReadbackDataHandler, "device_states", mock_req_msg):
|
|
58
56
|
with mock.patch.object(
|
|
59
|
-
|
|
57
|
+
ReadbackDataHandler, "done", side_effect=[False, False, True]
|
|
60
58
|
):
|
|
61
59
|
LiveUpdatesReadbackProgressbar(bec=client, request=request).run()
|
|
62
60
|
assert mock_client_msgs.called is True
|
|
@@ -82,28 +80,21 @@ def test_move_callback_with_report_instruction(bec_client_mock):
|
|
|
82
80
|
return readback[0]
|
|
83
81
|
|
|
84
82
|
req_done = collections.deque()
|
|
85
|
-
|
|
86
|
-
device="samx", success=True, metadata={"RID": "something"}
|
|
87
|
-
)
|
|
88
|
-
req_done.extend([[None], [None], [None], [msg_acc]])
|
|
83
|
+
req_done.extend([{"samx": (False, False)}, {"samx": (False, False)}, {"samx": (True, True)}])
|
|
89
84
|
|
|
90
85
|
def mock_req_msg(*args):
|
|
91
86
|
if len(req_done) > 1:
|
|
92
87
|
return req_done.popleft()
|
|
93
88
|
return req_done[0]
|
|
94
89
|
|
|
95
|
-
with mock.patch("bec_ipython_client.callbacks.move_device.check_alarms")
|
|
96
|
-
with mock.patch.object(
|
|
97
|
-
with mock.patch.object(LiveUpdatesReadbackProgressbar, "
|
|
98
|
-
with mock.patch.object(LiveUpdatesReadbackProgressbar, "
|
|
99
|
-
with mock.patch.object(
|
|
100
|
-
|
|
101
|
-
):
|
|
102
|
-
with mock.patch.object(
|
|
103
|
-
ReadbackDataMixin, "get_device_values", mock_readback
|
|
104
|
-
):
|
|
90
|
+
with mock.patch("bec_ipython_client.callbacks.move_device.check_alarms"):
|
|
91
|
+
with mock.patch.object(LiveUpdatesReadbackProgressbar, "wait_for_request_acceptance"):
|
|
92
|
+
with mock.patch.object(LiveUpdatesReadbackProgressbar, "_print_client_msgs_asap"):
|
|
93
|
+
with mock.patch.object(LiveUpdatesReadbackProgressbar, "_print_client_msgs_all"):
|
|
94
|
+
with mock.patch.object(ReadbackDataHandler, "get_device_values", mock_readback):
|
|
95
|
+
with mock.patch.object(ReadbackDataHandler, "device_states", mock_req_msg):
|
|
105
96
|
with mock.patch.object(
|
|
106
|
-
|
|
97
|
+
ReadbackDataHandler, "done", side_effect=[False, False, False, True]
|
|
107
98
|
):
|
|
108
99
|
LiveUpdatesReadbackProgressbar(
|
|
109
100
|
bec=client,
|
|
@@ -112,70 +103,121 @@ def test_move_callback_with_report_instruction(bec_client_mock):
|
|
|
112
103
|
).run()
|
|
113
104
|
|
|
114
105
|
|
|
115
|
-
def
|
|
116
|
-
|
|
117
|
-
messages.DeviceMessage(
|
|
106
|
+
def test_readback_data_handler(readback_data_handler):
|
|
107
|
+
readback_data_handler.data = {
|
|
108
|
+
"samx": messages.DeviceMessage(
|
|
118
109
|
signals={"samx": {"value": 10}, "samx_setpoint": {"value": 20}},
|
|
119
110
|
metadata={"device": "samx"},
|
|
120
111
|
),
|
|
121
|
-
messages.DeviceMessage(
|
|
112
|
+
"samy": messages.DeviceMessage(
|
|
122
113
|
signals={"samy": {"value": 10}, "samy_setpoint": {"value": 20}},
|
|
123
114
|
metadata={"device": "samy"},
|
|
124
115
|
),
|
|
125
|
-
|
|
126
|
-
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
res = readback_data_handler.get_device_values()
|
|
127
119
|
assert res == [10, 10]
|
|
128
120
|
|
|
129
121
|
|
|
130
|
-
def
|
|
131
|
-
|
|
122
|
+
def test_readback_data_handler_multiple_hints(readback_data_handler):
|
|
123
|
+
readback_data_handler.device_manager.devices.samx._info["hints"]["fields"] = [
|
|
132
124
|
"samx_setpoint",
|
|
133
125
|
"samx",
|
|
134
126
|
]
|
|
135
|
-
|
|
136
|
-
messages.DeviceMessage(
|
|
127
|
+
readback_data_handler.data = {
|
|
128
|
+
"samx": messages.DeviceMessage(
|
|
137
129
|
signals={"samx": {"value": 10}, "samx_setpoint": {"value": 20}},
|
|
138
130
|
metadata={"device": "samx"},
|
|
139
131
|
),
|
|
140
|
-
messages.DeviceMessage(
|
|
132
|
+
"samy": messages.DeviceMessage(
|
|
141
133
|
signals={"samy": {"value": 10}, "samy_setpoint": {"value": 20}},
|
|
142
134
|
metadata={"device": "samy"},
|
|
143
135
|
),
|
|
144
|
-
|
|
145
|
-
res =
|
|
136
|
+
}
|
|
137
|
+
res = readback_data_handler.get_device_values()
|
|
146
138
|
assert res == [20, 10]
|
|
147
139
|
|
|
148
140
|
|
|
149
|
-
def
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
messages.DeviceMessage(
|
|
141
|
+
def test_readback_data_handler_multiple_no_hints(readback_data_handler):
|
|
142
|
+
readback_data_handler.device_manager.devices.samx._info["hints"]["fields"] = []
|
|
143
|
+
readback_data_handler.data = {
|
|
144
|
+
"samx": messages.DeviceMessage(
|
|
153
145
|
signals={"samx": {"value": 10}, "samx_setpoint": {"value": 20}},
|
|
154
146
|
metadata={"device": "samx"},
|
|
155
147
|
),
|
|
156
|
-
messages.DeviceMessage(
|
|
148
|
+
"samy": messages.DeviceMessage(
|
|
157
149
|
signals={"samy": {"value": 10}, "samy_setpoint": {"value": 20}},
|
|
158
150
|
metadata={"device": "samy"},
|
|
159
151
|
),
|
|
160
|
-
|
|
161
|
-
res =
|
|
152
|
+
}
|
|
153
|
+
res = readback_data_handler.get_device_values()
|
|
162
154
|
assert res == [10, 10]
|
|
163
155
|
|
|
164
156
|
|
|
165
|
-
def
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
)
|
|
173
|
-
|
|
157
|
+
def test_readback_data_handler_init(readback_data_handler):
|
|
158
|
+
"""
|
|
159
|
+
Test that the ReadbackDataHandler is initialized correctly.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
# Initial state
|
|
163
|
+
assert readback_data_handler._devices_done_state == {
|
|
164
|
+
"samx": (False, False),
|
|
165
|
+
"samy": (False, False),
|
|
166
|
+
}
|
|
167
|
+
assert readback_data_handler._devices_received == {"samx": False, "samy": False}
|
|
168
|
+
assert readback_data_handler.data == {}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_readback_data_handler_readback_callbacks(readback_data_handler):
|
|
172
|
+
"""
|
|
173
|
+
Test that the readback callback properly updates the readback data.
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
# Submit readback for samx
|
|
177
|
+
msg = messages.DeviceMessage(
|
|
178
|
+
signals={"samx": {"value": 15}}, metadata={"device": "samx", "RID": "something"}
|
|
174
179
|
)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
readback_data_handler.connector.set_and_publish(MessageEndpoints.device_readback("samx"), msg)
|
|
181
|
+
|
|
182
|
+
msg_old = messages.DeviceMessage(
|
|
183
|
+
signals={"samy": {"value": 10}}, metadata={"device": "samx", "RID": "something_else"}
|
|
184
|
+
)
|
|
185
|
+
readback_data_handler.connector.set_and_publish(
|
|
186
|
+
MessageEndpoints.device_readback("samy"), msg_old
|
|
187
|
+
)
|
|
188
|
+
while (
|
|
189
|
+
not readback_data_handler._devices_received["samx"]
|
|
190
|
+
or "samx" not in readback_data_handler.data
|
|
191
|
+
):
|
|
192
|
+
time.sleep(0.01)
|
|
193
|
+
assert readback_data_handler.data["samx"].signals["samx"]["value"] == 15
|
|
194
|
+
dev_data = readback_data_handler.get_device_values()
|
|
195
|
+
assert dev_data[0] == 15
|
|
196
|
+
assert dev_data[1] == 10 # samy remains unchanged
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def test_readback_data_handler_request_done_callbacks(readback_data_handler):
|
|
200
|
+
"""
|
|
201
|
+
Test that the request done callback properly updates the device done state.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
# Submit request done for samx
|
|
205
|
+
msg = messages.DeviceReqStatusMessage(device="samx", success=True, request_id="something")
|
|
206
|
+
readback_data_handler.connector.xadd(
|
|
207
|
+
MessageEndpoints.device_req_status("something"), {"data": msg}
|
|
208
|
+
)
|
|
209
|
+
while not readback_data_handler._devices_done_state["samx"][0]:
|
|
210
|
+
time.sleep(0.01)
|
|
211
|
+
assert readback_data_handler._devices_done_state["samx"] == (True, True)
|
|
212
|
+
|
|
213
|
+
assert readback_data_handler.done() is False
|
|
214
|
+
|
|
215
|
+
# Submit request done for samy
|
|
216
|
+
msg = messages.DeviceReqStatusMessage(device="samy", success=False, request_id="something")
|
|
217
|
+
readback_data_handler.connector.xadd(
|
|
218
|
+
MessageEndpoints.device_req_status("something"), {"data": msg}
|
|
181
219
|
)
|
|
220
|
+
while not readback_data_handler._devices_done_state["samy"][0]:
|
|
221
|
+
time.sleep(0.01)
|
|
222
|
+
assert readback_data_handler._devices_done_state["samy"] == (True, False)
|
|
223
|
+
assert readback_data_handler.done() is True
|