bec-ipython-client 3.64.5__py3-none-any.whl → 3.84.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.

Potentially problematic release.


This version of bec-ipython-client might be problematic. Click here for more details.

@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import time
4
+ from dataclasses import dataclass
4
5
  from importlib.metadata import version
5
6
  from typing import TYPE_CHECKING, Callable, Generator
6
7
  from unittest.mock import MagicMock, patch
@@ -11,7 +12,7 @@ from bec_ipython_client.main import BECIPythonClient
11
12
  from bec_lib import messages
12
13
  from bec_lib.endpoints import MessageEndpoints
13
14
  from bec_lib.logger import bec_logger
14
- from bec_server.scan_server.procedures.constants import PROCEDURE
15
+ from bec_server.scan_server.procedures.constants import _CONTAINER, _WORKER
15
16
  from bec_server.scan_server.procedures.container_utils import get_backend
16
17
  from bec_server.scan_server.procedures.container_worker import ContainerProcedureWorker
17
18
  from bec_server.scan_server.procedures.manager import ProcedureManager
@@ -28,6 +29,15 @@ logger = bec_logger.logger
28
29
  pytestmark = pytest.mark.random_order(disabled=True)
29
30
 
30
31
 
32
+ @dataclass(frozen=True)
33
+ class PATCHED_CONSTANTS:
34
+ WORKER = _WORKER()
35
+ CONTAINER = _CONTAINER()
36
+ MANAGER_SHUTDOWN_TIMEOUT_S = 2
37
+ BEC_VERSION = version("bec_lib")
38
+ REDIS_HOST = "localhost"
39
+
40
+
31
41
  @pytest.fixture
32
42
  def client_logtool_and_manager(
33
43
  bec_ipython_client_fixture_with_logtool: tuple[BECIPythonClient, "LogTestTool"],
@@ -52,7 +62,7 @@ def _wait_while(cond: Callable[[], bool], timeout_s):
52
62
  def test_building_worker_image():
53
63
  podman_utils = get_backend()
54
64
  build = podman_utils.build_worker_image()
55
- assert len(build._command_output.splitlines()[-1]) == 64
65
+ assert len(build._command_output.splitlines()[-1]) == 64 # type: ignore
56
66
  assert podman_utils.image_exists(f"bec_procedure_worker:v{version('bec_lib')}")
57
67
 
58
68
 
@@ -62,7 +72,7 @@ def test_procedure_runner_spawns_worker(
62
72
  client_logtool_and_manager: tuple[BECIPythonClient, "LogTestTool", ProcedureManager],
63
73
  ):
64
74
  client, _, manager = client_logtool_and_manager
65
- assert manager.active_workers == {}
75
+ assert manager._active_workers == {}
66
76
  endpoint = MessageEndpoints.procedure_request()
67
77
  msg = messages.ProcedureRequestMessage(
68
78
  identifier="sleep", args_kwargs=((), {"time_s": 2}), queue="test"
@@ -77,21 +87,22 @@ def test_procedure_runner_spawns_worker(
77
87
  manager.add_callback("test", cb)
78
88
  client.connector.xadd(topic=endpoint, msg_dict=msg.model_dump())
79
89
 
80
- _wait_while(lambda: manager.active_workers == {}, 5)
81
- _wait_while(lambda: manager.active_workers != {}, 20)
90
+ _wait_while(lambda: manager._active_workers == {}, 5)
91
+ _wait_while(lambda: manager._active_workers != {}, 20)
82
92
 
83
93
  assert logs != []
84
94
 
85
95
 
86
96
  @pytest.mark.timeout(100)
87
97
  @patch("bec_server.scan_server.procedures.manager.procedure_registry.is_registered", lambda _: True)
98
+ @patch("bec_server.scan_server.procedures.container_worker.PROCEDURE", PATCHED_CONSTANTS())
88
99
  def test_happy_path_container_procedure_runner(
89
100
  client_logtool_and_manager: tuple[BECIPythonClient, "LogTestTool", ProcedureManager],
90
101
  ):
91
102
  test_args = (1, 2, 3)
92
103
  test_kwargs = {"a": "b", "c": "d"}
93
104
  client, logtool, manager = client_logtool_and_manager
94
- assert manager.active_workers == {}
105
+ assert manager._active_workers == {}
95
106
  conn = client.connector
96
107
  endpoint = MessageEndpoints.procedure_request()
97
108
  msg = messages.ProcedureRequestMessage(
@@ -99,12 +110,15 @@ def test_happy_path_container_procedure_runner(
99
110
  )
100
111
  conn.xadd(topic=endpoint, msg_dict=msg.model_dump())
101
112
 
102
- _wait_while(lambda: manager.active_workers == {}, 5)
103
- _wait_while(lambda: manager.active_workers != {}, 20)
113
+ _wait_while(lambda: manager._active_workers == {}, 5)
114
+ _wait_while(lambda: manager._active_workers != {}, 20)
104
115
 
105
116
  logtool.fetch()
106
117
  assert logtool.is_present_in_any_message("procedure accepted: True, message:")
107
- assert logtool.is_present_in_any_message("ContainerWorker started container for queue primary")
118
+ assert logtool.is_present_in_any_message(
119
+ "ContainerWorker started container for queue primary"
120
+ ), f"Log content relating to procedures: {manager._logs}"
121
+
108
122
  res, msg = logtool.are_present_in_order(
109
123
  [
110
124
  "Container worker 'primary' status update: IDLE",
@@ -114,12 +128,7 @@ def test_happy_path_container_procedure_runner(
114
128
  ]
115
129
  )
116
130
  assert res, f"failed on {msg}"
117
- res, msg = logtool.are_present_in_order(
118
- [
119
- "Container worker 'primary' status update: IDLE",
120
- f"Builtin procedure log_message_args_kwargs called with args: {test_args} and kwargs: {test_kwargs}",
121
- "Container worker 'primary' status update: IDLE",
122
- "Container worker 'primary' status update: FINISHED",
123
- ]
131
+
132
+ assert logtool.is_present_in_any_message(
133
+ f"Builtin procedure log_message_args_kwargs called with args: {test_args} and kwargs: {test_kwargs}"
124
134
  )
125
- assert res, f"failed on {msg}"
@@ -737,12 +737,12 @@ def test_update_config(bec_ipython_client_fixture):
737
737
  bec = bec_ipython_client_fixture
738
738
  bec.metadata.update({"unit_test": "test_update_config"})
739
739
  demo_config_path = os.path.join(os.path.dirname(configs.__file__), "demo_config.yaml")
740
- config = bec.config._load_config_from_file(demo_config_path)
740
+ config = bec.device_manager.config_helper._load_config_from_file(demo_config_path)
741
741
  config.pop("samx")
742
- bec.config.send_config_request(action="set", config=config)
742
+ bec.device_manager.config_helper.send_config_request(action="set", config=config)
743
743
  assert "samx" not in bec.device_manager.devices
744
- config = bec.config._load_config_from_file(demo_config_path)
745
- bec.config.send_config_request(action="set", config=config)
744
+ config = bec.device_manager.config_helper._load_config_from_file(demo_config_path)
745
+ bec.device_manager.config_helper.send_config_request(action="set", config=config)
746
746
 
747
747
 
748
748
  @pytest.mark.timeout(100)
@@ -108,12 +108,10 @@ def test_config_updates(bec_client_lib):
108
108
  assert dev.rt_controller.limits == [-50, 50]
109
109
 
110
110
  dev.rt_controller.velocity.set(10).wait()
111
+ assert dev.rt_controller.velocity.read(cached=True)["rt_controller_velocity"]["value"] == 10
111
112
  assert dev.rt_controller.velocity.read()["rt_controller_velocity"]["value"] == 10
112
- assert dev.rt_controller.velocity.read(cached=False)["rt_controller_velocity"]["value"] == 10
113
113
  assert dev.rt_controller.read_configuration()["rt_controller_velocity"]["value"] == 10
114
- assert (
115
- dev.rt_controller.read_configuration(cached=False)["rt_controller_velocity"]["value"] == 10
116
- )
114
+ assert dev.rt_controller.read_configuration()["rt_controller_velocity"]["value"] == 10
117
115
 
118
116
  dev.rt_controller.velocity.put(5)
119
117
  assert dev.rt_controller.velocity.get() == 5
@@ -324,7 +322,9 @@ def test_config_reload(
324
322
  num_devices = len(bec.device_manager.devices)
325
323
  if raises_error:
326
324
  with pytest.raises(DeviceConfigError):
327
- bec.config.update_session_with_file(runtime_config_file_path)
325
+ bec.config.update_session_with_file(
326
+ runtime_config_file_path, force=True, validate=False
327
+ )
328
328
  if deletes_config:
329
329
  assert len(bec.device_manager.devices) == 0
330
330
  elif disabled_device:
@@ -332,7 +332,7 @@ def test_config_reload(
332
332
  else:
333
333
  assert len(bec.device_manager.devices) == num_devices
334
334
  else:
335
- bec.config.update_session_with_file(runtime_config_file_path)
335
+ bec.config.update_session_with_file(runtime_config_file_path, force=True, validate=False)
336
336
  assert len(bec.device_manager.devices) == 2
337
337
  for dev in disabled_device:
338
338
  assert bec.device_manager.devices[dev].enabled is False
@@ -377,7 +377,7 @@ def test_config_reload_with_describe_failure(bec_test_config_file_path, bec_clie
377
377
  f.write(yaml.dump(config))
378
378
 
379
379
  with pytest.raises(DeviceConfigError):
380
- bec.config.update_session_with_file(runtime_config_file_path)
380
+ bec.config.update_session_with_file(runtime_config_file_path, force=True, validate=False)
381
381
 
382
382
  assert len(bec.device_manager.devices) == 2
383
383
  assert bec.device_manager.devices["eyefoc"].enabled is True
@@ -388,7 +388,7 @@ def test_config_reload_with_describe_failure(bec_test_config_file_path, bec_clie
388
388
  f"e2e_test_hexapod_fail", messages.DeviceStatusMessage(device="hexapod", status=0)
389
389
  )
390
390
 
391
- bec.config.update_session_with_file(runtime_config_file_path)
391
+ bec.config.update_session_with_file(runtime_config_file_path, force=True)
392
392
  assert len(bec.device_manager.devices) == 2
393
393
  assert bec.device_manager.devices["eyefoc"].enabled is True
394
394
  assert bec.device_manager.devices["hexapod"].enabled is True
@@ -414,13 +414,13 @@ def test_config_add_remove_device(bec_client_lib):
414
414
  "readOnly": False,
415
415
  }
416
416
  }
417
- bec.config.send_config_request(action="add", config=config)
417
+ bec.device_manager.config_helper.send_config_request(action="add", config=config)
418
418
  with pytest.raises(DeviceConfigError) as config_error:
419
- bec.config.send_config_request(action="add", config=config)
419
+ bec.device_manager.config_helper.send_config_request(action="add", config=config)
420
420
  assert config_error.match("Device new_device already exists")
421
421
  assert "new_device" in dev
422
422
 
423
- bec.config.send_config_request(action="remove", config={"new_device": {}})
423
+ bec.device_manager.config_helper.send_config_request(action="remove", config={"new_device": {}})
424
424
  assert "new_device" not in dev
425
425
 
426
426
  device_config_msg = bec.connector.get(MessageEndpoints.device_config())
@@ -431,7 +431,7 @@ def test_config_add_remove_device(bec_client_lib):
431
431
 
432
432
  config["new_device"]["deviceClass"] = "ophyd_devices.doesnt_exist"
433
433
  with pytest.raises(DeviceConfigError) as config_error:
434
- bec.config.send_config_request(action="add", config=config)
434
+ bec.device_manager.config_helper.send_config_request(action="add", config=config)
435
435
  assert config_error.match("module 'ophyd_devices' has no attribute 'doesnt_exist'")
436
436
  assert "new_device" not in dev
437
437
  assert "samx" in dev
@@ -454,7 +454,7 @@ def test_computed_signal(bec_client_lib):
454
454
  dev.pseudo_signal1.set_compute_method(compute_signal1)
455
455
  dev.pseudo_signal1.set_input_signals()
456
456
 
457
- assert dev.pseudo_signal1.read(cached=False)["pseudo_signal1"]["value"] == 5
457
+ assert dev.pseudo_signal1.read()["pseudo_signal1"]["value"] == 5
458
458
 
459
459
 
460
460
  def test_cached_device_readout(bec_client_lib):
@@ -463,26 +463,30 @@ def test_cached_device_readout(bec_client_lib):
463
463
  dev = bec.device_manager.devices
464
464
 
465
465
  dev.samx.setpoint.put(5)
466
- data = dev.samx.setpoint.get()
466
+ data = dev.samx.setpoint.get(cached=True)
467
467
  assert data == 5
468
468
 
469
- orig_velocity = dev.samx.velocity.get()
469
+ orig_velocity = dev.samx.velocity.get(cached=True)
470
470
  dev.samx.velocity.put(10)
471
- data = dev.samx.velocity.get()
471
+ data = dev.samx.velocity.get(cached=True)
472
472
  assert data == 10
473
473
 
474
- config = dev.samx.read_configuration()
474
+ config = dev.samx.read_configuration(cached=True)
475
475
  assert config["samx_velocity"]["value"] == 10
476
476
 
477
+ dev.samx.velocity.set(20).wait()
478
+ data = dev.samx.velocity.get(cached=True)
479
+ assert data == 20
480
+
477
481
  dev.samx.velocity.put(orig_velocity)
478
482
 
479
- data = dev.hexapod.x.readback.read(cached=False)
483
+ data = dev.hexapod.x.readback.read()
480
484
  timestamp = data["hexapod_x"]["timestamp"]
481
485
  data = dev.hexapod.x.readback.read(cached=True)
482
486
  assert data["hexapod_x"]["timestamp"] == timestamp
483
487
 
484
488
  # check that .get also updates the cache
485
- dev.hexapod.x.readback.get(cached=False)
489
+ dev.hexapod.x.readback.get()
486
490
  timestamp_2 = dev.hexapod.x.readback.read(cached=True)["hexapod_x"]["timestamp"]
487
491
  assert timestamp_2 != timestamp
488
492