bec-ipython-client 3.161.0__tar.gz → 3.162.0__tar.gz

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 (44) hide show
  1. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/PKG-INFO +1 -1
  2. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/callbacks/ipython_live_updates.py +29 -89
  3. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/callbacks/live_table.py +0 -9
  4. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/demo.py +0 -32
  5. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/pyproject.toml +1 -1
  6. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_ipython_live_updates.py +11 -11
  7. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/end-2-end/test_acl_e2e.py +7 -4
  8. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/end-2-end/test_scans_e2e.py +52 -102
  9. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/end-2-end/test_scans_lib_e2e.py +6 -36
  10. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/end-2-end/test_scans_v4_lib_e2e.py +5 -14
  11. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/.gitignore +0 -0
  12. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/__init__.py +0 -0
  13. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/beamline_mixin.py +0 -0
  14. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/bec_magics.py +0 -0
  15. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/bec_startup.py +0 -0
  16. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/callbacks/__init__.py +0 -0
  17. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/callbacks/device_progress.py +0 -0
  18. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/callbacks/move_device.py +0 -0
  19. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/callbacks/utils.py +0 -0
  20. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/high_level_interfaces/__init__.py +0 -0
  21. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/high_level_interfaces/bec_hli.py +0 -0
  22. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/high_level_interfaces/spec_hli.py +0 -0
  23. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/main.py +0 -0
  24. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/plugins/SLS/__init__.py +0 -0
  25. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/plugins/SLS/sls_info.py +0 -0
  26. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/plugins/XTreme/__init__.py +0 -0
  27. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/plugins/XTreme/x-treme.py +0 -0
  28. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/plugins/__init__.py +0 -0
  29. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/plugins/flomni/flomni_config.yaml +0 -0
  30. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/prettytable.py +0 -0
  31. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/progressbar.py +0 -0
  32. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/bec_ipython_client/signals.py +0 -0
  33. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/conftest.py +0 -0
  34. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_beamline_mixins.py +0 -0
  35. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_bec_client.py +0 -0
  36. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_device_progress.py +0 -0
  37. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_live_table.py +0 -0
  38. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_move_callback.py +0 -0
  39. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_pretty_table.py +0 -0
  40. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/client_tests/test_signals.py +0 -0
  41. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/conftest.py +0 -0
  42. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/end-2-end/_ensure_requirements_container.py +0 -0
  43. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/end-2-end/test_actors_e2e.py +0 -0
  44. {bec_ipython_client-3.161.0 → bec_ipython_client-3.162.0}/tests/end-2-end/test_procedures_e2e.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bec_ipython_client
3
- Version: 3.161.0
3
+ Version: 3.162.0
4
4
  Summary: BEC IPython client
5
5
  Project-URL: Bug Tracker, https://github.com/bec-project/bec/issues
6
6
  Project-URL: Homepage, https://github.com/bec-project/bec
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import collections
4
3
  import time
5
4
  from contextvars import Token
6
5
  from typing import TYPE_CHECKING, Any
@@ -41,12 +40,9 @@ class IPythonLiveUpdates:
41
40
  """
42
41
  self.client = client
43
42
  self._interrupted_request = None
44
- self._active_callback = None
45
43
  self._processed_instructions = 0
46
44
  self._active_request: messages.ScanQueueMessage | None = None
47
45
  self._user_callback = None
48
- self._request_block_index = collections.defaultdict(lambda: 0)
49
- self._request_block_id = None
50
46
  self._current_queue = None
51
47
  self._status_live: Live | None = None
52
48
 
@@ -68,9 +64,6 @@ class IPythonLiveUpdates:
68
64
  """
69
65
  if not self._active_request:
70
66
  return
71
- scan_type = self._active_request.scan_type
72
- if scan_type == "close_scan_group":
73
- return
74
67
 
75
68
  if not report_instructions:
76
69
  return
@@ -90,62 +83,33 @@ class IPythonLiveUpdates:
90
83
  instr (dict): The instruction to process.
91
84
  """
92
85
  scan_report_type = list(instr.keys())[0]
93
- scan_def_id = self.client.scans._scan_def_id
94
- interactive_scan = self.client.scans._interactive_scan
95
86
  if self._active_request is None:
96
87
  # Already checked in caller method. It is just for type checking purposes.
97
88
  return
98
- if scan_def_id is None or interactive_scan:
99
- if scan_report_type == "readback":
100
- LiveUpdatesReadbackProgressbar(
101
- self.client,
102
- report_instruction=instr,
103
- request=self._active_request,
104
- callbacks=self._user_callback,
105
- ).run()
106
- elif scan_report_type == "scan_progress":
107
- LiveUpdatesTable(
108
- self.client,
109
- report_instruction=instr,
110
- request=self._active_request,
111
- callbacks=self._user_callback,
112
- print_table_data=self.print_table_data,
113
- ).run()
114
- elif scan_report_type == "device_progress":
115
- LiveUpdatesDeviceProgress(
116
- self.client,
117
- report_instruction=instr,
118
- request=self._active_request,
119
- callbacks=self._user_callback,
120
- ).run()
121
- else:
122
- raise ValueError(f"Unknown scan report type: {scan_report_type}")
123
- else:
124
- if self._active_callback:
125
- if scan_report_type == "readback":
126
- LiveUpdatesReadbackProgressbar(
127
- self.client,
128
- report_instruction=instr,
129
- request=self._active_request,
130
- callbacks=self._user_callback,
131
- ).run()
132
- else:
133
- self._active_callback.resume(
134
- request=self._active_request,
135
- report_instruction=instr,
136
- callbacks=self._user_callback,
137
- )
138
-
139
- return
140
-
141
- self._active_callback = LiveUpdatesTable(
89
+ if scan_report_type == "readback":
90
+ LiveUpdatesReadbackProgressbar(
91
+ self.client,
92
+ report_instruction=instr,
93
+ request=self._active_request,
94
+ callbacks=self._user_callback,
95
+ ).run()
96
+ elif scan_report_type == "scan_progress":
97
+ LiveUpdatesTable(
142
98
  self.client,
143
99
  report_instruction=instr,
144
100
  request=self._active_request,
145
101
  callbacks=self._user_callback,
146
102
  print_table_data=self.print_table_data,
147
- )
148
- self._active_callback.run()
103
+ ).run()
104
+ elif scan_report_type == "device_progress":
105
+ LiveUpdatesDeviceProgress(
106
+ self.client,
107
+ report_instruction=instr,
108
+ request=self._active_request,
109
+ callbacks=self._user_callback,
110
+ ).run()
111
+ else:
112
+ raise ValueError(f"Unknown scan report type: {scan_report_type}")
149
113
 
150
114
  def _available_req_blocks(
151
115
  self, queue: QueueItem, request: messages.ScanQueueMessage
@@ -190,15 +154,14 @@ class IPythonLiveUpdates:
190
154
 
191
155
  self._current_queue = queue = scan_request.scan_queue_request.queue
192
156
  request_context.queue_status = queue.status
193
- self._request_block_id = req_id = self._active_request.metadata.get("RID")
194
157
 
195
158
  while queue.status not in ["COMPLETED", "ABORTED", "HALTED", "CANCELLED"]:
196
159
  request_context.queue_status = queue.status
197
- if self._process_queue(queue, request, req_id):
160
+ if self._process_queue(queue, request):
198
161
  break
199
162
 
200
163
  available_blocks = self._available_req_blocks(queue, request)
201
- req_block = available_blocks[self._request_block_index[req_id]]
164
+ req_block = available_blocks[0]
202
165
  report_instructions = req_block.report_instructions or []
203
166
  self._process_report_instructions(report_instructions)
204
167
 
@@ -218,15 +181,15 @@ class IPythonLiveUpdates:
218
181
  self._interrupted_request = (request,)
219
182
  if self._current_queue and self.client._service_config.abort_on_ctrl_c:
220
183
  self._wait_for_cleanup()
221
- self._reset(forced=True)
184
+ self._reset()
222
185
  raise scan_interr
223
186
  except KeyboardInterrupt as exc:
224
187
  self._stop_status_live()
225
188
  if self.client._service_config.abort_on_ctrl_c and self._abort_pending_request():
226
189
  self._wait_for_cleanup()
227
- self._reset(forced=True)
190
+ self._reset()
228
191
  raise ScanInterruption("User abort.") from exc
229
- self._reset(forced=True)
192
+ self._reset()
230
193
  raise
231
194
  finally:
232
195
  if context_token is not None:
@@ -285,16 +248,13 @@ class IPythonLiveUpdates:
285
248
  return False
286
249
  return any(queue_item.queue_id == self._current_queue.queue_id for queue_item in queue_info)
287
250
 
288
- def _process_queue(
289
- self, queue: QueueItem, request: messages.ScanQueueMessage, req_id: str
290
- ) -> bool:
251
+ def _process_queue(self, queue: QueueItem, request: messages.ScanQueueMessage) -> bool:
291
252
  """
292
253
  Process the queue and return True if the scan is completed.
293
254
 
294
255
  Args:
295
256
  queue(QueueItem): The queue item to process.
296
257
  request(messages.ScanQueueMessage): The request message.
297
- req_id(str): The request ID.
298
258
 
299
259
  Returns:
300
260
  bool: True if the scan is completed.
@@ -321,10 +281,9 @@ class IPythonLiveUpdates:
321
281
  available_blocks = self._available_req_blocks(queue, request)
322
282
  if not available_blocks:
323
283
  return False
324
- req_block = available_blocks[self._request_block_index[req_id]]
284
+ req_block = available_blocks[0]
325
285
  if req_block.msg.scan_type in [
326
- "mv",
327
- "_v4_mv",
286
+ "mv"
328
287
  ]: # TODO: make this more general for all scan types that don't have report instructions
329
288
  return True
330
289
 
@@ -333,13 +292,6 @@ class IPythonLiveUpdates:
333
292
  return False
334
293
  self._process_report_instructions(report_instructions)
335
294
 
336
- complete_rbl = len(available_blocks) == self._request_block_index[req_id] + 1
337
- if self._active_callback and complete_rbl:
338
- return True
339
-
340
- if complete_rbl and self.client.scans._interactive_scan:
341
- return True
342
-
343
295
  if not queue.active_request_block:
344
296
  return True
345
297
 
@@ -395,28 +347,16 @@ class IPythonLiveUpdates:
395
347
  self._status_live.update(Panel(message, title="[yellow]Scan Status[/yellow]"))
396
348
  return
397
349
 
398
- def _reset(self, forced=False):
399
- """Reset the active request and callback.
400
-
401
- Args:
402
- forced(bool): If True, the reset is forced.
403
- """
350
+ def _reset(self):
351
+ """Reset the active request."""
404
352
  self._stop_status_live()
405
353
  self._interrupted_request = None
406
354
 
407
355
  self._current_queue = None
408
356
  self._user_callback = None
409
357
  self._processed_instructions = 0
410
- scan_closed = forced or self._active_request is None
411
358
  self._active_request = None
412
359
 
413
- if self.client.scans._scan_def_id and not scan_closed:
414
- self._request_block_index[self._request_block_id] += 1
415
- return
416
-
417
- if scan_closed:
418
- self._active_callback = None
419
-
420
360
  def continue_request(self):
421
361
  """Continue the interrupted request."""
422
362
  if not self._interrupted_request:
@@ -97,8 +97,6 @@ class LiveUpdatesTable(LiveUpdatesBase):
97
97
  """wait for scan completion"""
98
98
  while True:
99
99
  if self.scan_item.end_time:
100
- if self.scan_item.open_queue_group:
101
- break
102
100
  if self.scan_item.queue.queue_position is None:
103
101
  break
104
102
  self.check_alarms()
@@ -110,13 +108,6 @@ class LiveUpdatesTable(LiveUpdatesBase):
110
108
  """check for alarms"""
111
109
  check_alarms(self.bec)
112
110
 
113
- def resume(self, request: messages.ScanQueueMessage, report_instruction: str, callbacks):
114
- """resume the scan after a pause"""
115
- super().__init__(
116
- self.bec, request=request, report_instruction=report_instruction, callbacks=callbacks
117
- )
118
- self.process_request()
119
-
120
111
  @property
121
112
  def devices(self):
122
113
  """get the devices for the callback"""
@@ -145,13 +145,6 @@ scans.umv(dev.samx, 5, dev.samy, 20, relative=False)
145
145
  # s = scans.line_scan(dev.samy, -5, 40, steps=10, exp_time=0.1)
146
146
  # s = scans.round_roi_scan(dev.samx, 50, dev.samy, 20, dr=2, nth=3, exp_time=0.1)
147
147
 
148
- # scan_def_id = str(uuid.uuid4())
149
- # scans.open_interactive_scan(dev.samx, dev.samy, exp_time=0.1, md={"scan_def_id": scan_def_id})
150
- # for ii in range(5):
151
- # scans.mv(dev.samx, ii, dev.samy, ii + 3, md={"scan_def_id": scan_def_id})
152
- # scans.interactive_scan_trigger(dev.samx, dev.samy, md={"scan_def_id": scan_def_id})
153
- # scans.close_interactive_scan(md={"scan_def_id": scan_def_id})
154
-
155
148
 
156
149
  # for ii in range(10):
157
150
  # scans.umv(dev.samx, ii * 10)
@@ -164,15 +157,6 @@ scans.umv(dev.samx, 5, dev.samy, 20, relative=False)
164
157
  # scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.02)
165
158
 
166
159
 
167
- # @scans.scan_group
168
- # def scan_with_decorator():
169
- # scans.umv(dev.samx, 5, relative=False)
170
- # scans.line_scan(dev.samx, -5, 5, steps=100, exp_time=0.1, relative=True)
171
- # scans.umv(dev.samx, 5, relative=False)
172
- # scans.line_scan(dev.samx, -5, 5, steps=100, exp_time=0.1, relative=True)
173
- # # scans.line_scan(dev.samx, -8, 8, steps=200, exp_time=0.1, relative=True)
174
-
175
-
176
160
  # with scans.dataset_id_on_hold:
177
161
  # scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.1, relative=True)
178
162
  # scans.line_scan(dev.samx, -8, 8, steps=10, exp_time=0.1, relative=True)
@@ -187,22 +171,6 @@ scans.umv(dev.samx, 5, dev.samy, 20, relative=False)
187
171
  # scans.umv(dev.samx, 1000)
188
172
 
189
173
 
190
- # @scans.scan_group
191
- # def alignment(*args, **kwargs):
192
- # scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.02)
193
- # scans.umv(dev.samx, 10)
194
- # scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.02)
195
- # scans.umv(dev.samx, 10)
196
- # scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.02)
197
-
198
-
199
- # with scans.scan_group:
200
- # scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.02, relative=True)
201
- # scans.umv(dev.samx, 10, relative=True)
202
-
203
- # alignment()
204
-
205
-
206
174
  # scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.02, md={"queue_group": queue_group})
207
175
  # scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.02, md={"queue_group": queue_group})
208
176
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_ipython_client"
7
- version = "3.161.0"
7
+ version = "3.162.0"
8
8
  description = "BEC IPython client"
9
9
  requires-python = ">=3.11"
10
10
  classifiers = [
@@ -107,7 +107,7 @@ def test_live_updates_process_queue_pending(ipython_live_updates_with_mocked_liv
107
107
  live_updates, "_available_req_blocks", return_value=[request_block]
108
108
  ):
109
109
  with mock.patch.object(live_updates, "_process_report_instructions") as process:
110
- res = live_updates._process_queue(queue, request_msg, "req_id")
110
+ res = live_updates._process_queue(queue, request_msg)
111
111
  # Verify Live panel was created for showing queue status
112
112
  mock_live.assert_called_once()
113
113
  mock_live.return_value.start.assert_called_once()
@@ -141,7 +141,7 @@ def test_live_updates_process_queue_running(ipython_live_updates_with_mocked_liv
141
141
  live_updates, "_available_req_blocks", return_value=[request_block]
142
142
  ):
143
143
  with mock.patch.object(live_updates, "_process_instruction") as process:
144
- res = live_updates._process_queue(queue, request_msg, "req_id")
144
+ res = live_updates._process_queue(queue, request_msg)
145
145
  mock_live.assert_not_called()
146
146
  process.assert_called_once_with({"wait_table": 10})
147
147
  assert res is True
@@ -177,7 +177,7 @@ def test_live_updates_process_queue_waiting_for_device_locks(
177
177
  ):
178
178
  queue_pos.return_value = 0
179
179
 
180
- assert live_updates._process_queue(queue, request_msg, "req_id") is False
180
+ assert live_updates._process_queue(queue, request_msg) is False
181
181
 
182
182
  process_pending.assert_called_once_with(queue)
183
183
 
@@ -214,7 +214,7 @@ def test_live_updates_process_queue_cancelled_pending_request_raises_interruptio
214
214
  mock.patch("bec_lib.queue_items.QueueItem.queue_position", new_callable=mock.PropertyMock),
215
215
  pytest.raises(ScanInterruption, match="Scan was cancelled."),
216
216
  ):
217
- live_updates._process_queue(queue, request_msg, "something")
217
+ live_updates._process_queue(queue, request_msg)
218
218
 
219
219
 
220
220
  def test_live_updates_process_queue_stopped_started_request_raises_interruption(bec_client_mock):
@@ -259,7 +259,7 @@ def test_live_updates_process_queue_stopped_started_request_raises_interruption(
259
259
  mock.patch("bec_lib.queue_items.QueueItem.queue_position", new_callable=mock.PropertyMock),
260
260
  pytest.raises(ScanInterruption, match="Scan 1 was aborted by user."),
261
261
  ):
262
- live_updates._process_queue(queue, request_msg, "something")
262
+ live_updates._process_queue(queue, request_msg)
263
263
 
264
264
 
265
265
  def test_live_updates_process_queue_stopped_restart_without_restart_message_waits_nonblocking(
@@ -300,7 +300,7 @@ def test_live_updates_process_queue_stopped_restart_without_restart_message_wait
300
300
  return_value=mock.MagicMock(status="aborted", restarted_msg=None),
301
301
  ),
302
302
  ):
303
- assert live_updates._process_queue(queue, request_msg, "something") is False
303
+ assert live_updates._process_queue(queue, request_msg) is False
304
304
 
305
305
 
306
306
  def test_process_request_repeats_on_ScanRestart_error(
@@ -485,7 +485,7 @@ def test_process_request_keyboard_interrupt_pending_request_raises_scan_interrup
485
485
 
486
486
  abort_pending.assert_called_once()
487
487
  wait_for_cleanup.assert_called_once()
488
- reset.assert_called_once_with(forced=True)
488
+ reset.assert_called_once_with()
489
489
 
490
490
 
491
491
  @pytest.mark.parametrize("queue_status", ["RUNNING", "LOCKED"])
@@ -515,7 +515,7 @@ def test_process_request_keyboard_interrupt_pending_request_aborts_local_request
515
515
 
516
516
  request_abort.assert_called_once_with(request_id="something")
517
517
  wait_for_cleanup.assert_called_once()
518
- reset.assert_called_once_with(forced=True)
518
+ reset.assert_called_once_with()
519
519
 
520
520
 
521
521
  def test_process_request_keyboard_interrupt_non_pending_re_raises(
@@ -543,7 +543,7 @@ def test_process_request_keyboard_interrupt_non_pending_re_raises(
543
543
 
544
544
  abort_pending.assert_called_once()
545
545
  wait_for_cleanup.assert_not_called()
546
- reset.assert_called_once_with(forced=True)
546
+ reset.assert_called_once_with()
547
547
 
548
548
 
549
549
  @pytest.mark.timeout(20)
@@ -552,7 +552,7 @@ def test_live_updates_process_queue_without_status(bec_client_mock, queue_elemen
552
552
  live_updates = IPythonLiveUpdates(client)
553
553
  queue, _, request_msg = queue_elements
554
554
  with mock.patch.object(queue, "_update_with_buffer"):
555
- assert live_updates._process_queue(queue, request_msg, "req_id") is False
555
+ assert live_updates._process_queue(queue, request_msg) is False
556
556
 
557
557
 
558
558
  @pytest.mark.timeout(20)
@@ -574,7 +574,7 @@ def test_live_updates_process_queue_without_queue_number(bec_client_mock, queue_
574
574
  )
575
575
  queue_pos.return_value = None
576
576
  with mock.patch.object(queue, "_update_with_buffer"):
577
- assert live_updates._process_queue(queue, request_msg, "req_id") is False
577
+ assert live_updates._process_queue(queue, request_msg) is False
578
578
 
579
579
 
580
580
  @pytest.mark.timeout(20)
@@ -12,6 +12,9 @@ from bec_lib.tests.utils import wait_for_empty_queue
12
12
  from bec_lib.utils.user_acls_test import BECAccessDemo
13
13
  from bec_server.bec_server_utils.service_handler import ServiceHandler
14
14
 
15
+ CLIENT_SHUTDOWN_TIMEOUT_S = 10
16
+ SERVICE_STOP_TIMEOUT_S = 20
17
+
15
18
 
16
19
  @pytest.fixture
17
20
  def acl_enabled_bec_services(
@@ -61,7 +64,7 @@ def acl_enabled_bec_services(
61
64
  yield bec_services_config_file_path
62
65
  finally:
63
66
  if processes is not None:
64
- service_handler.stop(processes)
67
+ service_handler.stop(processes, timeout_s=SERVICE_STOP_TIMEOUT_S)
65
68
  restore_connector = RedisConnector(redis_url)
66
69
  try:
67
70
  BECAccessDemo(restore_connector).reset()
@@ -77,7 +80,7 @@ def test_acl_admin_server_allows_default_user_scan(acl_enabled_bec_services):
77
80
  try:
78
81
  admin_client.config.load_demo_config(force=True)
79
82
  finally:
80
- admin_client.shutdown()
83
+ admin_client.shutdown(per_thread_timeout_s=CLIENT_SHUTDOWN_TIMEOUT_S)
81
84
  admin_client._client._reset_singleton()
82
85
 
83
86
  user_config = ServiceConfig(acl_enabled_bec_services, acl={"env_file": "", "user": "user"})
@@ -97,7 +100,7 @@ def test_acl_admin_server_allows_default_user_scan(acl_enabled_bec_services):
97
100
 
98
101
  assert status.scan.num_points == 3
99
102
  finally:
100
- user_client.shutdown()
103
+ user_client.shutdown(per_thread_timeout_s=CLIENT_SHUTDOWN_TIMEOUT_S)
101
104
  user_client._client._reset_singleton()
102
105
 
103
106
 
@@ -136,5 +139,5 @@ def test_acl_account_endpoint_allows_user_read_but_admin_only_write(acl_enabled_
136
139
  assert user_client.username == "user"
137
140
  assert user_client.connector.get_last(account_endpoint, "data") == updated_account_msg
138
141
  finally:
139
- user_client.shutdown()
142
+ user_client.shutdown(per_thread_timeout_s=CLIENT_SHUTDOWN_TIMEOUT_S)
140
143
  user_client._client._reset_singleton()
@@ -31,16 +31,13 @@ if TYPE_CHECKING: # pragma: no cover
31
31
 
32
32
 
33
33
  @pytest.mark.timeout(100)
34
- @pytest.mark.parametrize("scan_name", ["grid_scan", "_v4_grid_scan"])
35
- def test_grid_scan(capsys, bec_ipython_client_fixture, scan_name):
34
+ def test_grid_scan(capsys, bec_ipython_client_fixture):
36
35
  bec = bec_ipython_client_fixture
37
36
  scans = bec.scans
38
37
  bec.metadata.update({"unit_test": "test_grid_scan"})
39
38
  dev = bec.device_manager.devices
40
39
  scans.umv(dev.samx, 0, dev.samy, 0, relative=False)
41
- status = getattr(scans, scan_name)(
42
- dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True
43
- )
40
+ status = scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True)
44
41
  assert len(status.scan.live_data) == 100
45
42
  assert status.scan.num_points == 100
46
43
  captured = capsys.readouterr()
@@ -48,13 +45,12 @@ def test_grid_scan(capsys, bec_ipython_client_fixture, scan_name):
48
45
 
49
46
 
50
47
  @pytest.mark.timeout(100)
51
- @pytest.mark.parametrize("scan_name", ["fermat_scan", "_v4_fermat_scan"])
52
- def test_fermat_scan(capsys, bec_ipython_client_fixture, scan_name):
48
+ def test_fermat_scan(capsys, bec_ipython_client_fixture):
53
49
  bec = bec_ipython_client_fixture
54
50
  scans = bec.scans
55
51
  bec.metadata.update({"unit_test": "test_fermat_scan"})
56
52
  dev = bec.device_manager.devices
57
- status = getattr(scans, scan_name)(
53
+ status = scans.fermat_scan(
58
54
  dev.samx,
59
55
  -5,
60
56
  5,
@@ -66,25 +62,19 @@ def test_fermat_scan(capsys, bec_ipython_client_fixture, scan_name):
66
62
  relative=True,
67
63
  optim_trajectory="corridor",
68
64
  )
69
- if scan_name == "_v4_fermat_scan":
70
- # NOTE: v4 scan calculates the angle more accurately, which results in a slightly different number of points
71
- assert len(status.scan.live_data) == 400
72
- assert status.scan.num_points == 400
73
- else:
74
- assert len(status.scan.live_data) == 393
75
- assert status.scan.num_points == 393
65
+ assert len(status.scan.live_data) == 400
66
+ assert status.scan.num_points == 400
76
67
  captured = capsys.readouterr()
77
68
  assert "finished. Scan ID" in captured.out
78
69
 
79
70
 
80
71
  @pytest.mark.timeout(100)
81
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
82
- def test_line_scan(capsys, bec_ipython_client_fixture, scan_name):
72
+ def test_line_scan(capsys, bec_ipython_client_fixture):
83
73
  bec = bec_ipython_client_fixture
84
74
  scans = bec.scans
85
75
  bec.metadata.update({"unit_test": "test_line_scan"})
86
76
  dev = bec.device_manager.devices
87
- status = getattr(scans, scan_name)(
77
+ status = scans.line_scan(
88
78
  dev.samx, -5, 5, dev.samy, -5, 5, steps=10, exp_time=0.01, relative=True
89
79
  )
90
80
  assert len(status.scan.live_data) == 10
@@ -95,13 +85,12 @@ def test_line_scan(capsys, bec_ipython_client_fixture, scan_name):
95
85
 
96
86
  @pytest.mark.flaky # marked as flaky as the simulation might return a new readback value within the tolerance
97
87
  @pytest.mark.timeout(100)
98
- @pytest.mark.parametrize("scan_name", [("mv", "umv"), ("_v4_mv", "_v4_umv")])
99
- def test_mv_scan(capsys, bec_ipython_client_fixture, scan_name):
88
+ def test_mv_scan(capsys, bec_ipython_client_fixture):
100
89
  bec = bec_ipython_client_fixture
101
90
  scans = bec.scans
102
91
  bec.metadata.update({"unit_test": "test_mv_scan"})
103
92
  dev = bec.device_manager.devices
104
- getattr(scans, scan_name[0])(dev.samx, 10, dev.samy, 20, relative=False).wait()
93
+ scans.mv(dev.samx, 10, dev.samy, 20, relative=False).wait()
105
94
  current_pos_samx = dev.samx.read(cached=True)["samx"]["value"]
106
95
  current_pos_samy = dev.samy.read(cached=True)["samy"]["value"]
107
96
  assert np.isclose(
@@ -110,7 +99,7 @@ def test_mv_scan(capsys, bec_ipython_client_fixture, scan_name):
110
99
  assert np.isclose(
111
100
  current_pos_samy, 20, atol=dev.samy._config["deviceConfig"].get("tolerance", 0.05)
112
101
  )
113
- getattr(scans, scan_name[1])(dev.samx, 10, dev.samy, 20, relative=False)
102
+ scans.umv(dev.samx, 10, dev.samy, 20, relative=False)
114
103
  current_pos_samx = dev.samx.read(cached=True)["samx"]["value"]
115
104
  current_pos_samy = dev.samy.read(cached=True)["samy"]["value"]
116
105
  captured = capsys.readouterr()
@@ -122,13 +111,12 @@ def test_mv_scan(capsys, bec_ipython_client_fixture, scan_name):
122
111
 
123
112
  @pytest.mark.flaky # marked as flaky as the simulation might return a new readback value within the tolerance
124
113
  @pytest.mark.timeout(100)
125
- @pytest.mark.parametrize("scan_name", [("mv", "umv"), ("_v4_mv", "_v4_umv")])
126
- def test_mv_scan_nested_device(capsys, bec_ipython_client_fixture, scan_name):
114
+ def test_mv_scan_nested_device(capsys, bec_ipython_client_fixture):
127
115
  bec = bec_ipython_client_fixture
128
116
  scans = bec.scans
129
117
  bec.metadata.update({"unit_test": "test_mv_scan_nested_device"})
130
118
  dev = bec.device_manager.devices
131
- getattr(scans, scan_name[0])(dev.hexapod.x, 10, dev.hexapod.y, 20, relative=False).wait()
119
+ scans.mv(dev.hexapod.x, 10, dev.hexapod.y, 20, relative=False).wait()
132
120
  if not bec.connector._managed_connection._message_callbacks_queue.empty():
133
121
  print("Waiting for messages to be processed")
134
122
  time.sleep(0.5)
@@ -140,7 +128,7 @@ def test_mv_scan_nested_device(capsys, bec_ipython_client_fixture, scan_name):
140
128
  assert np.isclose(
141
129
  current_pos_hexapod_y, 20, atol=dev.hexapod._config["deviceConfig"].get("tolerance", 0.5)
142
130
  )
143
- getattr(scans, scan_name[1])(dev.hexapod.x, 10, dev.hexapod.y, 20, relative=False)
131
+ scans.umv(dev.hexapod.x, 10, dev.hexapod.y, 20, relative=False)
144
132
  if not bec.connector._managed_connection._message_callbacks_queue.empty():
145
133
  print("Waiting for messages to be processed")
146
134
  time.sleep(0.5)
@@ -159,8 +147,7 @@ def test_mv_scan_nested_device(capsys, bec_ipython_client_fixture, scan_name):
159
147
 
160
148
 
161
149
  @pytest.mark.timeout(100)
162
- @pytest.mark.parametrize("scan_name", [("umv", "grid_scan"), ("_v4_umv", "_v4_grid_scan")])
163
- def test_mv_scan_mv(bec_ipython_client_fixture, scan_name):
150
+ def test_mv_scan_mv(bec_ipython_client_fixture):
164
151
  bec = bec_ipython_client_fixture
165
152
  scans = bec.scans
166
153
  bec.metadata.update({"unit_test": "test_mv_scan_mv"})
@@ -169,7 +156,7 @@ def test_mv_scan_mv(bec_ipython_client_fixture, scan_name):
169
156
 
170
157
  dev.samx.limits = [-50, 50]
171
158
  dev.samy.limits = [-50, 50]
172
- getattr(scans, scan_name[0])(dev.samx, 10, dev.samy, 20, relative=False)
159
+ scans.umv(dev.samx, 10, dev.samy, 20, relative=False)
173
160
  tolerance_samx = dev.samx._config["deviceConfig"].get("tolerance", 0.05)
174
161
  tolerance_samy = dev.samy._config["deviceConfig"].get("tolerance", 0.05)
175
162
  current_pos_samx = dev.samx.read()["samx"]["value"]
@@ -179,9 +166,7 @@ def test_mv_scan_mv(bec_ipython_client_fixture, scan_name):
179
166
  assert np.isclose(current_pos_samx, 10, atol=tolerance_samx)
180
167
  assert np.isclose(current_pos_samy, 20, atol=tolerance_samy)
181
168
 
182
- status = getattr(scans, scan_name[1])(
183
- dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True
184
- )
169
+ status = scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True)
185
170
 
186
171
  # make sure the scan completed the expected number of positions
187
172
  assert len(status.scan.live_data) == 100
@@ -201,7 +186,7 @@ def test_mv_scan_mv(bec_ipython_client_fixture, scan_name):
201
186
  assert np.isclose(current_pos_samx, 10, atol=tolerance_samx * 2)
202
187
  assert np.isclose(current_pos_samy, 20, atol=tolerance_samy * 2)
203
188
 
204
- getattr(scans, scan_name[0])(dev.samx, 20, dev.samy, -20, relative=False)
189
+ scans.umv(dev.samx, 20, dev.samy, -20, relative=False)
205
190
  current_pos_samx = dev.samx.read()["samx"]["value"]
206
191
  current_pos_samy = dev.samy.read()["samy"]["value"]
207
192
 
@@ -209,7 +194,7 @@ def test_mv_scan_mv(bec_ipython_client_fixture, scan_name):
209
194
  assert np.isclose(current_pos_samx, 20, atol=tolerance_samx)
210
195
  assert np.isclose(current_pos_samy, -20, atol=tolerance_samy)
211
196
 
212
- status = getattr(scans, scan_name[1])(
197
+ status = scans.grid_scan(
213
198
  dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=False
214
199
  )
215
200
 
@@ -226,8 +211,7 @@ def test_mv_scan_mv(bec_ipython_client_fixture, scan_name):
226
211
 
227
212
 
228
213
  @pytest.mark.timeout(100)
229
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
230
- def test_scan_abort(bec_ipython_client_fixture: BECIPythonClient, scan_name: str):
214
+ def test_scan_abort(bec_ipython_client_fixture: BECIPythonClient):
231
215
  def send_abort(bec):
232
216
  while True:
233
217
  current_scan_info = bec.queue.scan_storage.current_scan_info
@@ -256,7 +240,7 @@ def test_scan_abort(bec_ipython_client_fixture: BECIPythonClient, scan_name: str
256
240
  aborted_scan = False
257
241
  try:
258
242
  threading.Thread(target=send_abort, args=(bec,), daemon=True).start()
259
- getattr(scans, scan_name)(dev.samx, -5, 5, steps=200, exp_time=0.1, relative=True)
243
+ scans.line_scan(dev.samx, -5, 5, steps=200, exp_time=0.1, relative=True)
260
244
  except ScanInterruption:
261
245
  logger.info("Raised ScanInterruption")
262
246
  time.sleep(2)
@@ -273,7 +257,7 @@ def test_scan_abort(bec_ipython_client_fixture: BECIPythonClient, scan_name: str
273
257
 
274
258
  assert len(bec.queue.scan_storage.storage[-1].live_data) < 200
275
259
 
276
- getattr(scans, scan_name)(dev.samx, -5, 5, steps=10, exp_time=0.1, relative=True)
260
+ scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.1, relative=True)
277
261
  scan_number_end = bec.queue.next_scan_number
278
262
  assert scan_number_end == scan_number_start + 2
279
263
 
@@ -319,8 +303,8 @@ def test_umv_ctrl_c_stops_motion(bec_ipython_client_fixture: BECIPythonClient):
319
303
  dev.samx.velocity.set(original_velocity).wait()
320
304
 
321
305
 
322
- @pytest.mark.parametrize("scan_name", [("line_scan", "umv"), ("_v4_line_scan", "_v4_umv")])
323
- def test_limit_error(bec_ipython_client_fixture, scan_name):
306
+ @pytest.mark.timeout(100)
307
+ def test_limit_error(bec_ipython_client_fixture):
324
308
  bec = bec_ipython_client_fixture
325
309
  bec.metadata.update({"unit_test": "test_limit_error"})
326
310
  scan_number_start = bec.queue.next_scan_number
@@ -329,7 +313,7 @@ def test_limit_error(bec_ipython_client_fixture, scan_name):
329
313
  aborted_scan = False
330
314
  dev.samx.limits = [-50, 50]
331
315
  try:
332
- getattr(scans, scan_name[0])(dev.samx, -520, 5, steps=200, exp_time=0.1, relative=False)
316
+ scans.line_scan(dev.samx, -520, 5, steps=200, exp_time=0.1, relative=False)
333
317
  except AlarmBase as alarm:
334
318
  assert alarm.alarm_type == "LimitError"
335
319
  aborted_scan = True
@@ -339,7 +323,7 @@ def test_limit_error(bec_ipython_client_fixture, scan_name):
339
323
  aborted_scan = False
340
324
  dev.samx.limits = [-50, 50]
341
325
  try:
342
- getattr(scans, scan_name[1])(dev.samx, 500, relative=False)
326
+ scans.umv(dev.samx, 500, relative=False)
343
327
  except AlarmBase as alarm:
344
328
  assert alarm.alarm_type == "LimitError"
345
329
  aborted_scan = True
@@ -350,17 +334,16 @@ def test_limit_error(bec_ipython_client_fixture, scan_name):
350
334
 
351
335
 
352
336
  @pytest.mark.timeout(100)
353
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
354
- def test_queued_scan(bec_ipython_client_fixture, scan_name):
337
+ def test_queued_scan(bec_ipython_client_fixture):
355
338
  bec = bec_ipython_client_fixture
356
339
  bec.metadata.update({"unit_test": "test_queued_scan"})
357
340
  scan_number_start = bec.queue.next_scan_number
358
341
  scans = bec.scans
359
342
  dev = bec.device_manager.devices
360
- scan1 = getattr(scans, scan_name)(
343
+ scan1 = scans.line_scan(
361
344
  dev.samx, -5, 5, steps=100, exp_time=0.1, hide_report=True, relative=True
362
345
  )
363
- scan2 = getattr(scans, scan_name)(
346
+ scan2 = scans.line_scan(
364
347
  dev.samx, -5, 5, steps=50, exp_time=0.1, hide_report=True, relative=True
365
348
  )
366
349
 
@@ -394,8 +377,7 @@ def test_fly_scan(bec_ipython_client_fixture):
394
377
 
395
378
 
396
379
  @pytest.mark.timeout(100)
397
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
398
- def test_scan_restart(bec_ipython_client_fixture, scan_name):
380
+ def test_scan_restart(bec_ipython_client_fixture):
399
381
  bec = bec_ipython_client_fixture
400
382
  bec.metadata.update({"unit_test": "test_scan_restart"})
401
383
  scans = bec.scans
@@ -417,12 +399,10 @@ def test_scan_restart(bec_ipython_client_fixture, scan_name):
417
399
 
418
400
  # We start two scans to ensure that the scan restart logic works correctly in a queued scenario
419
401
  # The first scan is started without printout to allow us to submit the second scan immediately after
420
- getattr(scans, scan_name)(
421
- dev.samx, -5, 5, steps=50, exp_time=0.1, hide_report=True, relative=True
422
- )
402
+ scans.line_scan(dev.samx, -5, 5, steps=50, exp_time=0.1, hide_report=True, relative=True)
423
403
 
424
404
  # The second scan is using the live table printout. It should properly continue after the restart
425
- scan2 = getattr(scans, scan_name)(dev.samx, -5, 5, steps=50, exp_time=0.1, relative=True)
405
+ scan2 = scans.line_scan(dev.samx, -5, 5, steps=50, exp_time=0.1, relative=True)
426
406
 
427
407
  scan2.wait()
428
408
 
@@ -435,8 +415,7 @@ def test_scan_restart(bec_ipython_client_fixture, scan_name):
435
415
 
436
416
 
437
417
  @pytest.mark.timeout(100)
438
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
439
- def test_scan_observer_repeat_queued(bec_ipython_client_fixture: BECIPythonClient, scan_name):
418
+ def test_scan_observer_repeat_queued(bec_ipython_client_fixture: BECIPythonClient):
440
419
  bec = bec_ipython_client_fixture
441
420
  bec.metadata.update({"unit_test": "test_scan_observer_repeat_queued"})
442
421
  scans = bec.scans
@@ -458,10 +437,10 @@ def test_scan_observer_repeat_queued(bec_ipython_client_fixture: BECIPythonClien
458
437
  # start repeat thread
459
438
  threading.Thread(target=send_repeat, args=(bec,), daemon=True).start()
460
439
  # start scan
461
- scan1 = getattr(scans, scan_name)(
440
+ scan1 = scans.line_scan(
462
441
  dev.samx, -5, 5, steps=100, exp_time=0.1, hide_report=True, relative=True
463
442
  )
464
- scan2 = getattr(scans, scan_name)(
443
+ scan2 = scans.line_scan(
465
444
  dev.samx, -5, 5, steps=100, exp_time=0.1, hide_report=True, relative=True
466
445
  )
467
446
 
@@ -476,8 +455,7 @@ def test_scan_observer_repeat_queued(bec_ipython_client_fixture: BECIPythonClien
476
455
 
477
456
 
478
457
  @pytest.mark.timeout(100)
479
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
480
- def test_scan_observer_repeat(bec_ipython_client_fixture, scan_name):
458
+ def test_scan_observer_repeat(bec_ipython_client_fixture):
481
459
  bec = bec_ipython_client_fixture
482
460
  bec.metadata.update({"unit_test": "test_scan_observer_repeat"})
483
461
  scans = bec.scans
@@ -497,7 +475,7 @@ def test_scan_observer_repeat(bec_ipython_client_fixture, scan_name):
497
475
  threading.Thread(target=send_repeat, args=(bec,), daemon=True).start()
498
476
  # start scan
499
477
  with pytest.raises(ScanAbortion):
500
- scan1 = getattr(scans, scan_name)(
478
+ scan1 = scans.line_scan(
501
479
  dev.samx, -5, 5, steps=50, exp_time=0.1, hide_report=True, relative=True
502
480
  )
503
481
  scan1.wait()
@@ -512,8 +490,7 @@ def test_scan_observer_repeat(bec_ipython_client_fixture, scan_name):
512
490
 
513
491
 
514
492
  @pytest.mark.timeout(100)
515
- @pytest.mark.parametrize("scan_name", ["grid_scan", "_v4_grid_scan"])
516
- def test_file_writer(bec_ipython_client_fixture, scan_name):
493
+ def test_file_writer(bec_ipython_client_fixture):
517
494
  bec = bec_ipython_client_fixture
518
495
  bec.metadata.update({"unit_test": "test_file_writer"})
519
496
  scans = bec.scans
@@ -523,7 +500,7 @@ def test_file_writer(bec_ipython_client_fixture, scan_name):
523
500
  dev.samx.velocity.set(98).wait()
524
501
  dev.samy.velocity.set(101).wait()
525
502
 
526
- scan = getattr(scans, scan_name)(
503
+ scan = scans.grid_scan(
527
504
  dev.samx,
528
505
  -5,
529
506
  5,
@@ -576,37 +553,21 @@ def test_file_writer(bec_ipython_client_fixture, scan_name):
576
553
 
577
554
 
578
555
  @pytest.mark.timeout(100)
579
- def test_group_def(bec_ipython_client_fixture):
580
- bec = bec_ipython_client_fixture
581
- bec.metadata.update({"unit_test": "test_group_def"})
582
- scans = bec.scans
583
- dev = bec.device_manager.devices
584
- scan_number = bec.queue.next_scan_number
585
- with scans.scan_group:
586
- scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.1, relative=False)
587
- scans.umv(dev.samy, 5, relative=False)
588
- scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.1, relative=False)
589
-
590
- assert scan_number == bec.queue.next_scan_number - 2
591
-
592
-
593
- @pytest.mark.timeout(100)
594
- @pytest.mark.parametrize("scan_name", ["list_scan", "_v4_list_scan"])
595
- def test_list_scan(bec_ipython_client_fixture, scan_name):
556
+ def test_list_scan(bec_ipython_client_fixture):
596
557
  bec = bec_ipython_client_fixture
597
558
  bec.metadata.update({"unit_test": "test_list_scan"})
598
559
  scans = bec.scans
599
560
  dev = bec.device_manager.devices
600
561
 
601
- status = getattr(scans, scan_name)(
562
+ status = scans.list_scan(
602
563
  dev.samx, [0, 1, 2, 3, 4], dev.samy, [0, 1, 2, 3, 4], exp_time=0.1, relative=False
603
564
  )
604
565
  assert len(status.scan.live_data) == 5
605
566
 
606
- status = getattr(scans, scan_name)(dev.samx, [0, 1, 2, 3, 4, 5], exp_time=0.1, relative=False)
567
+ status = scans.list_scan(dev.samx, [0, 1, 2, 3, 4, 5], exp_time=0.1, relative=False)
607
568
  assert len(status.scan.live_data) == 6
608
569
 
609
- status = getattr(scans, scan_name)(
570
+ status = scans.list_scan(
610
571
  dev.samx,
611
572
  [0, 1, 2, 3],
612
573
  dev.samy,
@@ -624,7 +585,7 @@ def test_time_scan(bec_ipython_client_fixture):
624
585
  bec = bec_ipython_client_fixture
625
586
  bec.metadata.update({"unit_test": "test_time_scan"})
626
587
  scans = bec.scans
627
- status = scans.time_scan(points=5, interval=0.5, exp_time=0.1, relative=False)
588
+ status = scans.time_scan(points=5, interval=0.5, exp_time=0.1)
628
589
  assert len(status.scan.live_data) == 5
629
590
 
630
591
 
@@ -881,8 +842,7 @@ def test_grid_scan_secondary_queue(capsys, bec_ipython_client_fixture):
881
842
 
882
843
 
883
844
  @pytest.mark.timeout(100)
884
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
885
- def test_scan_after_scan_lock(capsys, bec_ipython_client_fixture, scan_name):
845
+ def test_scan_after_scan_lock(capsys, bec_ipython_client_fixture):
886
846
  """
887
847
  Test that pending scans are properly executed after a scan lock is released.
888
848
  """
@@ -891,10 +851,8 @@ def test_scan_after_scan_lock(capsys, bec_ipython_client_fixture, scan_name):
891
851
  bec.metadata.update({"unit_test": "test_scan_after_scan_lock"})
892
852
  dev = bec.device_manager.devices
893
853
  bec.queue.add_queue_lock(queue="primary", reason="unit_test_scan_lock", lock_id="test_lock")
894
- getattr(scans, scan_name)(
895
- dev.samx, -5, 5, steps=10, exp_time=0.01, relative=True, hide_report=True
896
- )
897
- scan2 = getattr(scans, scan_name)(
854
+ scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.01, relative=True, hide_report=True)
855
+ scan2 = scans.line_scan(
898
856
  dev.samx, -5, 5, steps=10, exp_time=0.01, relative=True, hide_report=True
899
857
  )
900
858
 
@@ -908,8 +866,7 @@ def test_scan_after_scan_lock(capsys, bec_ipython_client_fixture, scan_name):
908
866
 
909
867
 
910
868
  @pytest.mark.timeout(100)
911
- @pytest.mark.parametrize("scan_name", ["line_scan", "_v4_line_scan"])
912
- def test_scan_repeat_decorator(bec_ipython_client_fixture, scan_name):
869
+ def test_scan_repeat_decorator(bec_ipython_client_fixture):
913
870
  """
914
871
  Test the scan_repeat decorator by simulating a communication failure during a scan.
915
872
  The scan should be retried according to the specified max_repeats and exc_handler.
@@ -953,9 +910,7 @@ def test_scan_repeat_decorator(bec_ipython_client_fixture, scan_name):
953
910
 
954
911
  @scan_repeat(max_repeats=2, exc_handler=exc_handler)
955
912
  def my_scan():
956
- getattr(scans, scan_name)(
957
- dev.positioner_with_failure, -5, 5, steps=10, exp_time=0.01, relative=True
958
- )
913
+ scans.line_scan(dev.positioner_with_failure, -5, 5, steps=10, exp_time=0.01, relative=True)
959
914
 
960
915
  my_scan()
961
916
 
@@ -965,10 +920,7 @@ def test_scan_repeat_decorator(bec_ipython_client_fixture, scan_name):
965
920
 
966
921
 
967
922
  @pytest.mark.timeout(100)
968
- @pytest.mark.parametrize(
969
- "scan_name", [("grid_scan", "line_scan"), ("_v4_grid_scan", "_v4_line_scan")]
970
- )
971
- def test_scan_set_completed(bec_ipython_client_fixture, scan_name):
923
+ def test_scan_set_completed(bec_ipython_client_fixture):
972
924
  """
973
925
  Test that a scan can be manually set to completed.
974
926
  """
@@ -988,9 +940,7 @@ def test_scan_set_completed(bec_ipython_client_fixture, scan_name):
988
940
 
989
941
  threading.Thread(target=_set_scan_completed, args=(bec,), daemon=True).start()
990
942
 
991
- getattr(scans, scan_name[0])(
992
- dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True
993
- )
943
+ scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True)
994
944
 
995
945
  # Now add a second scan to ensure scans can continue after setting completed
996
- getattr(scans, scan_name[1])(dev.samx, -5, 5, steps=10, exp_time=0.01, relative=True)
946
+ scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.01, relative=True)
@@ -16,31 +16,25 @@ logger = bec_logger.logger
16
16
 
17
17
 
18
18
  @pytest.mark.timeout(100)
19
- @pytest.mark.parametrize("scan_name", [("umv", "grid_scan"), ("_v4_umv", "_v4_grid_scan")])
20
- def test_grid_scan_lib(bec_client_lib, scan_name):
19
+ def test_grid_scan_lib(bec_client_lib):
21
20
  bec = bec_client_lib
22
21
  scans = bec.scans
23
22
  bec.metadata.update({"unit_test": "test_grid_scan_bec_client_lib"})
24
23
  dev = bec.device_manager.devices
25
- getattr(scans, scan_name[0])(dev.samx, 0, dev.samy, 0, relative=False)
26
- status = getattr(scans, scan_name[1])(
27
- dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True
28
- )
24
+ scans.umv(dev.samx, 0, dev.samy, 0, relative=False)
25
+ status = scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=0.01, relative=True)
29
26
  status.wait(num_points=True, file_written=True)
30
27
  assert len(status.scan.live_data) == 100
31
28
  assert status.scan.num_points == 100
32
29
 
33
30
 
34
31
  @pytest.mark.timeout(100)
35
- @pytest.mark.parametrize("scan_name", ["grid_scan", "_v4_grid_scan"])
36
- def test_grid_scan_lib_cancel(bec_client_lib, scan_name):
32
+ def test_grid_scan_lib_cancel(bec_client_lib):
37
33
  bec = bec_client_lib
38
34
  scans = bec.scans
39
35
  bec.metadata.update({"unit_test": "test_grid_scan_bec_client_lib"})
40
36
  dev = bec.device_manager.devices
41
- status = getattr(scans, scan_name)(
42
- dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=1, relative=False
43
- )
37
+ status = scans.grid_scan(dev.samx, -5, 5, 10, dev.samy, -5, 5, 10, exp_time=1, relative=False)
44
38
  time.sleep(0.5)
45
39
  status.cancel()
46
40
 
@@ -352,6 +346,7 @@ def test_dap_fit(bec_client_lib):
352
346
  "invalid_device_class",
353
347
  ],
354
348
  )
349
+ @pytest.mark.timeout(100)
355
350
  def test_config_reload(
356
351
  bec_test_config_file_path, bec_client_lib, config, raises_error, deletes_config, disabled_device
357
352
  ):
@@ -550,31 +545,6 @@ def test_cached_device_readout(bec_client_lib):
550
545
  assert timestamp_3 == timestamp_2
551
546
 
552
547
 
553
- @pytest.mark.timeout(100)
554
- @pytest.mark.skip(reason="Interactive scans are currently not supported in v4 scans.")
555
- def test_interactive_scan(bec_client_lib):
556
- bec = bec_client_lib
557
- bec.metadata.update({"unit_test": "test_interactive_scan"})
558
- dev = bec.device_manager.devices
559
- scans = bec.scans
560
-
561
- with scans.interactive_scan(monitored=[dev.samx, dev.samy], exp_time=0.1) as scan:
562
- for ii in range(10):
563
- samx_status = dev.samx.set(ii)
564
- samy_status = dev.samy.set(ii)
565
- samx_status.wait()
566
- samy_status.wait()
567
- scan.trigger()
568
- scan.read_monitored_devices(devices=[dev.samx, dev.samy])
569
- report = scan.status
570
-
571
- report.wait()
572
-
573
- while len(report.scan.live_data) != 10:
574
- time.sleep(0.1)
575
- assert len(report.scan.live_data.samx.samx.val) == 10
576
-
577
-
578
548
  @pytest.mark.timeout(100)
579
549
  def test_bl_state(bec_client_lib):
580
550
  bec = bec_client_lib
@@ -16,7 +16,7 @@ from bec_server.scan_server.scans import position_generators
16
16
 
17
17
 
18
18
  def _get_v4_scan_runner(bec, scan_name: str):
19
- return getattr(bec.scans, f"_v4_{scan_name}")
19
+ return getattr(bec.scans, scan_name)
20
20
 
21
21
 
22
22
  def _run_v4_scan(
@@ -69,15 +69,6 @@ def _wait_for_live_data_count(bec, status, expected_count: int, timeout: float =
69
69
  time.sleep(0.1)
70
70
 
71
71
 
72
- def _wait_for_scan_status(status, expected_status: str, timeout: float = 10):
73
- deadline = time.time() + timeout
74
- while time.time() < deadline:
75
- if status.status == expected_status:
76
- return
77
- time.sleep(0.1)
78
- raise TimeoutError(f"Timed out waiting for scan status {expected_status!r}.")
79
-
80
-
81
72
  def _wait_for_queue_status(bec, queue_name: str, expected_status: str, timeout: float = 10):
82
73
  deadline = time.time() + timeout
83
74
  while time.time() < deadline:
@@ -240,7 +231,7 @@ def test_v4_fixed_point_scans_lib(
240
231
 
241
232
 
242
233
  @pytest.mark.timeout(120)
243
- def test_v4_mv_scan_lib(bec_client_lib):
234
+ def test_mv_scan_lib(bec_client_lib):
244
235
  bec = bec_client_lib
245
236
  dev = bec.device_manager.devices
246
237
 
@@ -252,7 +243,7 @@ def test_v4_mv_scan_lib(bec_client_lib):
252
243
 
253
244
 
254
245
  @pytest.mark.timeout(120)
255
- def test_v4_umv_scan_lib(bec_client_lib):
246
+ def test_umv_scan_lib(bec_client_lib):
256
247
  bec = bec_client_lib
257
248
  dev = bec.device_manager.devices
258
249
 
@@ -264,7 +255,7 @@ def test_v4_umv_scan_lib(bec_client_lib):
264
255
 
265
256
 
266
257
  @pytest.mark.timeout(120)
267
- def test_v4_cont_line_scan_lib(bec_client_lib):
258
+ def test_cont_line_scan_lib(bec_client_lib):
268
259
  bec = bec_client_lib
269
260
  dev = bec.device_manager.devices
270
261
  original_velocity = dev.samx.velocity.get()
@@ -282,7 +273,7 @@ def test_v4_cont_line_scan_lib(bec_client_lib):
282
273
 
283
274
 
284
275
  @pytest.mark.timeout(120)
285
- def test_v4_line_sweep_scan_lib(bec_client_lib):
276
+ def test_line_sweep_scan_lib(bec_client_lib):
286
277
  bec = bec_client_lib
287
278
  dev = bec.device_manager.devices
288
279
  scans = bec.scans