bec-lib 3.151.2__tar.gz → 3.152.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.
- {bec_lib-3.151.2 → bec_lib-3.152.0}/PKG-INFO +1 -1
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/devicemanager.py +3 -1
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/messages.py +4 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/queue_items.py +40 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/redis_connector/managed_redis_connection.py +13 -4
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_input_validator.py +1 -1
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scans.py +17 -3
- {bec_lib-3.151.2 → bec_lib-3.152.0}/pyproject.toml +1 -1
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_queue_items.py +67 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_redis_connector_fakeredis.py +29 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_object.py +10 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/.gitignore +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/README.md +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/_print_versions.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/acl_login.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/actors.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/alarm_handler.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/atlas_models.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/bec_errors.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/bec_service.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/bec_yaml_loader.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/bl_state_manager.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/bl_states.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/builtin_actor_hli.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/callback_handler.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/channel_monitor.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/client.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/codecs.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/config_helper.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/config_values.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/configs/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/configs/demo_config.yaml +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/configs/openapi_schema.json +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/connector.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/dap_plugin_objects.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/dap_plugins.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/device.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/endpoints.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/file_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/live_scan_data.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/lmfit_serializer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/logger.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/macro_update_handler.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/messaging_hooks.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/messaging_services.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/metadata_schema.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/numpy_encoder.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/observer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/pdf_writer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/plugin_helper.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/procedures/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/procedures/helper.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/procedures/hli.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/procedures/status.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/redis_connector/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/redis_connector/constants.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/redis_connector/hli.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/redis_connector/streams.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/redis_connector/validation.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/request_context.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/request_items.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_args.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_data_container.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_history.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_items.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_manager.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_number_container.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_repeat.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scan_report.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/scibec_validator.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/script_executor.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/serialization.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/serialization_registry.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/service_config.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/signature_serializer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/tests/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/tests/fixtures.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/tests/test_config.yaml +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/tests/test_service_config.yaml +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/tests/utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/user_macros.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/copier_jinja_filters.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/import_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/json_extended.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/_constants.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/_util.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/create/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/create/device.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/create/scan.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/create/templates/v4_scan.py.jinja +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/main.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/proxy.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/pydantic_pretty_print.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/rpc_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/scan_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/threading_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/user_acls_test.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/__init__.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/_additional_for_signature_serializer_test.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/conftest.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_acl_login.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_alarm_handler.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_atlas_models.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_beamline_states.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_bec_logger.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_bec_messages.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_bec_service.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_callback_handler.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_channel_monitor.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_client.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_config_helper.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_core_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_dap_plugins.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_data_container.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_device_hashing.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_device_manager.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_devices.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_file_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_hli_connector_fakeredis.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_hli_redis_connector.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_import_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_jinja_plugins.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_lmfit_serializer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_managed_config_values.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_managed_redis_connection.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_messaging_hooks.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_messaging_service.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_metadata_schema.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_observer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_pdf_writer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_plugin_helper.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_plugin_manager.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_plugin_system.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_pydantic_pretty_print.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_context.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_data.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_history.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_items.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_manager.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_repeat.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scan_report.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_scibec_validator.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_script_executor.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_serializer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_signature_serializer.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_signature_serializer_with_future_import.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_stream_subs.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_user_macros.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_utils.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/tests/test_yaml_loader.py +0 -0
- {bec_lib-3.151.2 → bec_lib-3.152.0}/util_scripts/init_config.py +0 -0
|
@@ -315,7 +315,9 @@ class DeviceContainer(dict):
|
|
|
315
315
|
return list(tags)
|
|
316
316
|
|
|
317
317
|
def get_software_triggered_devices(self) -> list:
|
|
318
|
-
"""
|
|
318
|
+
"""
|
|
319
|
+
Get a list of all enabled devices that should receive a software trigger during a scan.
|
|
320
|
+
"""
|
|
319
321
|
# pylint: disable=protected-access
|
|
320
322
|
devices = [
|
|
321
323
|
dev for _, dev in self.items() if dev._config.get("softwareTrigger", False) is True
|
|
@@ -415,6 +415,8 @@ class RequestBlock(BaseModel):
|
|
|
415
415
|
scan_number (int | None): Scan number if applicable
|
|
416
416
|
scan_id (str | None): Scan ID if applicable
|
|
417
417
|
report_instructions (list[dict] | None): List of report instructions for the scan, if any
|
|
418
|
+
owned_device_locks (list[str]): List of device locks owned by the request
|
|
419
|
+
pending_device_locks (list[str]): List of device locks pending for the request
|
|
418
420
|
|
|
419
421
|
"""
|
|
420
422
|
|
|
@@ -427,6 +429,8 @@ class RequestBlock(BaseModel):
|
|
|
427
429
|
scan_number: int | None
|
|
428
430
|
scan_id: str | None
|
|
429
431
|
report_instructions: list[dict] | None = None
|
|
432
|
+
owned_device_locks: list[str] = Field(default_factory=list)
|
|
433
|
+
pending_device_locks: list[str] = Field(default_factory=list)
|
|
430
434
|
|
|
431
435
|
|
|
432
436
|
class QueueInfoEntry(BaseModel):
|
|
@@ -54,6 +54,7 @@ class QueueItem:
|
|
|
54
54
|
self.active_request_block = active_request_block
|
|
55
55
|
self.scan_ids = scan_id
|
|
56
56
|
self.reason = reason
|
|
57
|
+
self._lock = threading.RLock()
|
|
57
58
|
if client_messages is None:
|
|
58
59
|
client_messages = []
|
|
59
60
|
self.client_messages = client_messages
|
|
@@ -85,6 +86,44 @@ class QueueItem:
|
|
|
85
86
|
def status(self):
|
|
86
87
|
return self._status
|
|
87
88
|
|
|
89
|
+
@threadlocked
|
|
90
|
+
def _get_device_lock_state(self) -> tuple[list[str], list[str]]:
|
|
91
|
+
"""
|
|
92
|
+
Return a snapshot of owned and pending device locks.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
tuple[list[str], list[str]]: A tuple containing two lists:
|
|
96
|
+
- The first list contains the names of devices whose locks are currently owned.
|
|
97
|
+
- The second list contains the names of devices whose locks are pending.
|
|
98
|
+
"""
|
|
99
|
+
owned_device_locks = sorted(
|
|
100
|
+
{
|
|
101
|
+
device
|
|
102
|
+
for request_block in self.request_blocks
|
|
103
|
+
for device in request_block.owned_device_locks
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
pending_device_locks = sorted(
|
|
107
|
+
{
|
|
108
|
+
device
|
|
109
|
+
for request_block in self.request_blocks
|
|
110
|
+
for device in request_block.pending_device_locks
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
return owned_device_locks, pending_device_locks
|
|
114
|
+
|
|
115
|
+
def get_device_lock_state(self) -> tuple[list[str], list[str]]:
|
|
116
|
+
"""
|
|
117
|
+
Refresh and return a consistent snapshot of device-lock state.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
tuple[list[str], list[str]]: A tuple containing two lists:
|
|
121
|
+
- The first list contains the names of devices whose locks are currently owned.
|
|
122
|
+
- The second list contains the names of devices whose locks are pending.
|
|
123
|
+
"""
|
|
124
|
+
self._update_with_buffer()
|
|
125
|
+
return self._get_device_lock_state()
|
|
126
|
+
|
|
88
127
|
def _update_with_buffer(self):
|
|
89
128
|
current_queue = self.scan_manager.queue_storage.current_scan_queue
|
|
90
129
|
if not current_queue:
|
|
@@ -103,6 +142,7 @@ class QueueItem:
|
|
|
103
142
|
self.update_queue_item(queue_item.info)
|
|
104
143
|
return
|
|
105
144
|
|
|
145
|
+
@threadlocked
|
|
106
146
|
def update_queue_item(self, queue_item: messages.QueueInfoEntry):
|
|
107
147
|
"""update the queue item"""
|
|
108
148
|
self.request_blocks = queue_item.request_blocks
|
|
@@ -595,7 +595,9 @@ class ManagedRedisConnection:
|
|
|
595
595
|
unsubscribe_list = []
|
|
596
596
|
with self._topics_cb_lock:
|
|
597
597
|
for topic in topics:
|
|
598
|
-
topics_cb = self._topics_cb
|
|
598
|
+
topics_cb = self._topics_cb.get(topic)
|
|
599
|
+
if topics_cb is None:
|
|
600
|
+
continue
|
|
599
601
|
# remove callback from list
|
|
600
602
|
self._topics_cb[topic] = list(
|
|
601
603
|
filter(lambda item: cb and item[0]() != cb, topics_cb)
|
|
@@ -631,9 +633,16 @@ class ManagedRedisConnection:
|
|
|
631
633
|
self._pubsub_conn.unsubscribe(unsubscribe_list)
|
|
632
634
|
else:
|
|
633
635
|
with self._topics_cb_lock:
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
636
|
+
registered_topics = list(self._topics_cb.keys())
|
|
637
|
+
direct_topics = [
|
|
638
|
+
topic for topic in registered_topics if not set("*?[]").intersection(topic)
|
|
639
|
+
]
|
|
640
|
+
pattern_topics = [topic for topic in registered_topics if topic not in direct_topics]
|
|
641
|
+
if direct_topics:
|
|
642
|
+
self.unregister(topics=direct_topics, cb=cb)
|
|
643
|
+
if pattern_topics:
|
|
644
|
+
self.unregister(patterns=pattern_topics, cb=cb)
|
|
645
|
+
self.unregister(topics=self._stream_subs.all_topics, cb=cb)
|
|
637
646
|
|
|
638
647
|
def _unregister_stream(self, topics: list[str], cb: Callable | None = None) -> bool:
|
|
639
648
|
"""Unregister callbacks from a list of topics. Returns true if any were removed"""
|
|
@@ -13,7 +13,7 @@ from bec_lib.scan_args import ScanArgument
|
|
|
13
13
|
from bec_lib.signature_serializer import deserialize_dtype, dict_to_signature
|
|
14
14
|
|
|
15
15
|
# Internal scan kwargs that are automatically added to the scan request
|
|
16
|
-
INTERNAL_SCAN_KWARGS = {"user_metadata", "system_config", "scan_queue"}
|
|
16
|
+
INTERNAL_SCAN_KWARGS = {"user_metadata", "system_config", "scan_queue", "monitored", "on_request"}
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class ScanInputValidator:
|
|
@@ -58,6 +58,7 @@ class ScanObject:
|
|
|
58
58
|
hide_report: bool = False,
|
|
59
59
|
metadata: dict | None = None,
|
|
60
60
|
monitored: list[str | DeviceBase] | None = None,
|
|
61
|
+
on_request: list[str | DeviceBase] | None = None,
|
|
61
62
|
file_suffix: str | None = None,
|
|
62
63
|
file_directory: str | None = None,
|
|
63
64
|
scan_queue: str | None = None,
|
|
@@ -72,7 +73,8 @@ class ScanObject:
|
|
|
72
73
|
async_callback: Asynchronous callback function
|
|
73
74
|
hide_report: Hide the report
|
|
74
75
|
metadata: Metadata dictionary
|
|
75
|
-
monitored: List of monitored
|
|
76
|
+
monitored: List of devices to be put on the readout priority `monitored`
|
|
77
|
+
on_request: List of devices to be put on the readout priority `on_request`
|
|
76
78
|
file_suffix: File suffix for the scan data
|
|
77
79
|
file_directory: File directory for the scan data
|
|
78
80
|
scan_queue: Scan queue name. If None, the default queue will be used.
|
|
@@ -110,13 +112,25 @@ class ScanObject:
|
|
|
110
112
|
monitored = [monitored]
|
|
111
113
|
for mon_device in monitored:
|
|
112
114
|
if isinstance(mon_device, str):
|
|
113
|
-
|
|
114
|
-
if not
|
|
115
|
+
mon_device_obj = self.client.device_manager.devices.get(mon_device)
|
|
116
|
+
if not mon_device_obj:
|
|
115
117
|
raise RuntimeError(
|
|
116
118
|
f"Specified monitored device {mon_device} does not exist in the current device configuration."
|
|
117
119
|
)
|
|
118
120
|
kwargs["monitored"] = monitored
|
|
119
121
|
|
|
122
|
+
if on_request is not None:
|
|
123
|
+
if not isinstance(on_request, list):
|
|
124
|
+
on_request = [on_request]
|
|
125
|
+
for or_device in on_request:
|
|
126
|
+
if isinstance(or_device, str):
|
|
127
|
+
or_device_obj = self.client.device_manager.devices.get(or_device)
|
|
128
|
+
if not or_device_obj:
|
|
129
|
+
raise RuntimeError(
|
|
130
|
+
f"Specified on_request device {or_device} does not exist in the current device configuration."
|
|
131
|
+
)
|
|
132
|
+
kwargs["on_request"] = on_request
|
|
133
|
+
|
|
120
134
|
sys_config = sys_config.model_dump()
|
|
121
135
|
# pylint: disable=protected-access
|
|
122
136
|
if scans._scan_group:
|
|
@@ -520,6 +520,73 @@ def test_queue_item_status_property(queue_item, scan_queue_status_message):
|
|
|
520
520
|
assert queue_item._status == "pending"
|
|
521
521
|
|
|
522
522
|
|
|
523
|
+
def test_queue_item_device_lock_properties(queue_item):
|
|
524
|
+
queue_item.request_blocks = [
|
|
525
|
+
messages.RequestBlock(
|
|
526
|
+
msg=messages.ScanQueueMessage(
|
|
527
|
+
queue="primary",
|
|
528
|
+
scan_type="step",
|
|
529
|
+
parameter={"args": {}, "kwargs": {}},
|
|
530
|
+
metadata={"RID": "rid_1"},
|
|
531
|
+
),
|
|
532
|
+
RID="rid_1",
|
|
533
|
+
readout_priority={"monitored": []},
|
|
534
|
+
is_scan=True,
|
|
535
|
+
scan_number=1,
|
|
536
|
+
scan_id="scan_1",
|
|
537
|
+
owned_device_locks=["samx", "samy"],
|
|
538
|
+
pending_device_locks=["bpm4i"],
|
|
539
|
+
),
|
|
540
|
+
messages.RequestBlock(
|
|
541
|
+
msg=messages.ScanQueueMessage(
|
|
542
|
+
queue="primary",
|
|
543
|
+
scan_type="step",
|
|
544
|
+
parameter={"args": {}, "kwargs": {}},
|
|
545
|
+
metadata={"RID": "rid_2"},
|
|
546
|
+
),
|
|
547
|
+
RID="rid_2",
|
|
548
|
+
readout_priority={"monitored": []},
|
|
549
|
+
is_scan=True,
|
|
550
|
+
scan_number=2,
|
|
551
|
+
scan_id="scan_2",
|
|
552
|
+
owned_device_locks=["samy", "samz"],
|
|
553
|
+
pending_device_locks=["bpm4i", "bpm5i"],
|
|
554
|
+
),
|
|
555
|
+
]
|
|
556
|
+
queue_item.scan_manager.queue_storage.current_scan_queue = None
|
|
557
|
+
|
|
558
|
+
owned_device_locks, pending_device_locks = queue_item.get_device_lock_state()
|
|
559
|
+
|
|
560
|
+
assert owned_device_locks == ["samx", "samy", "samz"]
|
|
561
|
+
assert pending_device_locks == ["bpm4i", "bpm5i"]
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
def test_queue_item_get_device_lock_state(queue_item):
|
|
565
|
+
queue_item.request_blocks = [
|
|
566
|
+
messages.RequestBlock(
|
|
567
|
+
msg=messages.ScanQueueMessage(
|
|
568
|
+
queue="primary",
|
|
569
|
+
scan_type="step",
|
|
570
|
+
parameter={"args": {}, "kwargs": {}},
|
|
571
|
+
metadata={"RID": "rid_1"},
|
|
572
|
+
),
|
|
573
|
+
RID="rid_1",
|
|
574
|
+
readout_priority={"monitored": []},
|
|
575
|
+
is_scan=True,
|
|
576
|
+
scan_number=1,
|
|
577
|
+
scan_id="scan_1",
|
|
578
|
+
owned_device_locks=["samx", "samy"],
|
|
579
|
+
pending_device_locks=["bpm4i"],
|
|
580
|
+
)
|
|
581
|
+
]
|
|
582
|
+
queue_item.scan_manager.queue_storage.current_scan_queue = None
|
|
583
|
+
|
|
584
|
+
owned_device_locks, pending_device_locks = queue_item.get_device_lock_state()
|
|
585
|
+
|
|
586
|
+
assert owned_device_locks == ["samx", "samy"]
|
|
587
|
+
assert pending_device_locks == ["bpm4i"]
|
|
588
|
+
|
|
589
|
+
|
|
523
590
|
def test_queue_item_scans_property(queue_item, scan_queue_status_message):
|
|
524
591
|
"""Test scans property retrieves scan items."""
|
|
525
592
|
queue_item.scan_ids = ["scan_1", "scan_2"]
|
|
@@ -148,6 +148,35 @@ def test_redis_connector_unregister(connected_connector):
|
|
|
148
148
|
assert len(connector._topics_cb) == 0
|
|
149
149
|
|
|
150
150
|
|
|
151
|
+
def test_redis_connector_unregister_all_for_callback(connected_connector):
|
|
152
|
+
connector = connected_connector
|
|
153
|
+
cb_mock = mock.Mock(spec=[])
|
|
154
|
+
|
|
155
|
+
connector.register(topics=["topic1"], cb=cb_mock, start_thread=False)
|
|
156
|
+
connector.register(patterns=["topic2:*"], cb=cb_mock, start_thread=False)
|
|
157
|
+
connector.register(TestStreamEndpoint, cb=cb_mock, start_thread=False)
|
|
158
|
+
|
|
159
|
+
connector.send("topic1", TestMessage(msg="topic1"))
|
|
160
|
+
connector.poll_messages(timeout=1)
|
|
161
|
+
connector.send("topic2:a", TestMessage(msg="topic2"))
|
|
162
|
+
connector.poll_messages(timeout=1)
|
|
163
|
+
connector.xadd("test", {"data": 1})
|
|
164
|
+
connector.poll_messages(timeout=1)
|
|
165
|
+
assert cb_mock.call_count == 3
|
|
166
|
+
|
|
167
|
+
cb_mock.reset_mock()
|
|
168
|
+
connector.unregister(cb=cb_mock)
|
|
169
|
+
|
|
170
|
+
connector.send("topic1", TestMessage(msg="topic1"))
|
|
171
|
+
connector.send("topic2:a", TestMessage(msg="topic2"))
|
|
172
|
+
connector.xadd("test", {"data": 2})
|
|
173
|
+
with pytest.raises(TimeoutError):
|
|
174
|
+
connector.poll_messages(timeout=1)
|
|
175
|
+
assert cb_mock.call_count == 0
|
|
176
|
+
assert len(connector._topics_cb) == 0
|
|
177
|
+
assert connector._stream_subs.all_topics == []
|
|
178
|
+
|
|
179
|
+
|
|
151
180
|
def test_redis_connector_register_identical(connected_connector):
|
|
152
181
|
connector = connected_connector
|
|
153
182
|
|
|
@@ -115,6 +115,16 @@ def test_scan_object_v4_rejects_additional_kwargs(scan_obj_no_args, dev):
|
|
|
115
115
|
assert "Unknown keyword argument(s) for scan: 'additional_device'" in str(exc.value)
|
|
116
116
|
|
|
117
117
|
|
|
118
|
+
def test_scan_object_v4_accepts_monitored_kwarg(scan_obj_no_args):
|
|
119
|
+
scan_obj_no_args.scan_info["base_class"] = "ScanBaseV4"
|
|
120
|
+
|
|
121
|
+
with mock.patch.object(scan_obj_no_args, "_send_scan_request") as send_scan_request:
|
|
122
|
+
scan_obj_no_args._run(points=10, interval=1.5, monitored=["samx"])
|
|
123
|
+
|
|
124
|
+
sent_msg = send_scan_request.call_args.args[0]
|
|
125
|
+
assert sent_msg.parameter["kwargs"]["monitored"] == ["samx"]
|
|
126
|
+
|
|
127
|
+
|
|
118
128
|
def test_scan_object_raises_signature_kwargs_type_for_arg_input_scan(scan_obj, dev):
|
|
119
129
|
with pytest.raises(ScanInputValidationError, match="step': .*float or int"):
|
|
120
130
|
scan_obj._run(dev.samx, -5, 5, dev.samy, -5, 5, step="bad", exp_time=0.1, relative=False)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bec_lib-3.151.2 → bec_lib-3.152.0}/bec_lib/utils/plugin_manager/create/templates/v4_scan.py.jinja
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|