bec-server 4.1.7__tar.gz → 4.2.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_server-4.1.7 → bec_server-4.2.0}/PKG-INFO +2 -2
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/device_server.py +64 -10
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/direct_scan_worker.py +12 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/scan_actions.py +20 -1
- {bec_server-4.1.7 → bec_server-4.2.0}/pyproject.toml +2 -2
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_device_server.py +187 -2
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_scan_actions.py +50 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_direct_scan_worker.py +17 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/.gitignore +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/.zed/debug.json +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/README.md +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/actors/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/actors/actor.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/actors/builtin_actor_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/actors/manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/actors/scan_interlock.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/actors/worker.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/bec_server_utils/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/bec_server_utils/launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/bec_server_utils/service_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/bec_server_utils/subprocess_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/bec_server_utils/tmux_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/data_processing/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/data_processing/cli/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/data_processing/cli/launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/data_processing/dap_server.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/data_processing/dap_service.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/data_processing/dap_service_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/data_processing/lmfit1d_service.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/bec_message_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/cli/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/cli/launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/devices/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/devices/config_update_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/devices/device_serializer.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/devices/devicemanager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/friendly_device_exceptions.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/ophyd_callback_monitor.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/rpc_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/tests/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/tests/utils.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/async_writer.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/cli/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/cli/launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/default_writer.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/file_writer.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/file_writer_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/file_writer/merged_dicts.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/Containerfile.bec_linux_base +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/Containerfile.requirements +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/Containerfile.worker +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/_dev_runner.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/builtin_procedures.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/constants.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/container_utils.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/container_worker.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/oop_worker_base.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/procedure_registry.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/protocol.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/subprocess_worker.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/procedures/worker_base.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_bundler/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_bundler/bec_emitter.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_bundler/cli/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_bundler/cli/launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_bundler/emitter.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_bundler/scan_bundler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/beamline_state_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/cli/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/cli/launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/device_lock_registry.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/errors.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/instruction_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scan_assembler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scan_guard.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scan_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scan_queue.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scan_server.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scan_worker.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/acquire.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/cont_line_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/device_rpc.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/fermat_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/grid_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/hexagonal_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/line_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/line_sweep_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/list_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/log_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/move.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/multi_region_grid_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/multi_region_line_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/path_optimization.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/position_generators.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/round_roi_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/round_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/scan_argument_modifier.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/scan_base.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/scan_components.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/scan_modifier.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/scan_status.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/time_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/scans/updated_move.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/tests/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/tests/fixtures.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/tests/scan_fixtures.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/tests/scan_hook_tests.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scan_server/tests/utils.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/atlas/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/atlas/atlas_active_client_emitter.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/atlas/atlas_connector.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/atlas/atlas_forwarder.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/atlas/atlas_metadata_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/atlas/atlas_plugin_repo_emitter.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/atlas/config_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/cli/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/cli/launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/scihub.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/service_handler/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/scihub/service_handler/service_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/test/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/test/actor_test_utils.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/bec_server/test/helpers.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_actors/test_actors.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_bec_server_utils/test_main.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_bec_server_utils/test_service_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_bec_server_utils/test_subprocess_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_bec_server_utils/test_tmux_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_data_processing/conftest.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_data_processing/test_dap_cli_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_data_processing/test_dap_server.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_data_processing/test_dap_service_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_data_processing/test_lmfit1d_service.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/conftest.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_config_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_device_instructions.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_device_manager_ds.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_device_serializer.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_device_server_cli_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_ophyd_callback_monitor.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_device_server/test_rpc_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_file_writer/conftest.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_file_writer/test_async_file_writer.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_file_writer/test_file_writer.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_file_writer/test_file_writer_cli_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_file_writer/test_file_writer_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_bundler/conftest.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_bundler/test_bec_emitter.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_bundler/test_scan_bundler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_bundler/test_scan_bundler_cli_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/conftest.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/__init__.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_acquire.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_cont_line_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_device_rpc_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_fermat_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_grid_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_hexagonal_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_line_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_line_sweep_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_list_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_log_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_move_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_multi_region_grid_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_multi_region_line_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_position_generators.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_relative_scan_return_to_start.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_round_roi_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_round_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_scan_components.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_scan_status.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_time_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/scans/test_updated_move_scan.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_beamline_state_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_builtin_actor_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_container_utils.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_device_lock_registry.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_instruction_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_path_optimization.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_procedure_container_worker.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_procedures.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_argument_modifier.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_assembler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_fixture_imports.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_guard.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_interlock.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_modifier.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_server_cli_launch.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_server_queue.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_server_scan_manager.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scan_server/test_scan_worker.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/conftest.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/test_atlas_active_client_emitter.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/test_atlas_config_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/test_atlas_connector.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/test_atlas_forwarder.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/test_atlas_metadata_handler.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/test_atlas_plugin_repo_emitter.py +0 -0
- {bec_server-4.1.7 → bec_server-4.2.0}/tests/tests_scihub/test_scihub_cli_launch.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: bec-server
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: BEC server
|
|
5
5
|
Project-URL: Bug Tracker, https://github.com/bec-project/bec/issues
|
|
6
6
|
Project-URL: Homepage, https://github.com/bec-project/bec
|
|
@@ -14,7 +14,7 @@ Requires-Dist: libtmux~=0.37
|
|
|
14
14
|
Requires-Dist: lmfit>=1.3.3,~=1.3
|
|
15
15
|
Requires-Dist: msgpack~=1.0
|
|
16
16
|
Requires-Dist: numpy<3.0,>=1.24
|
|
17
|
-
Requires-Dist: ophyd-devices>=1.
|
|
17
|
+
Requires-Dist: ophyd-devices>=1.51.0
|
|
18
18
|
Requires-Dist: ophyd~=1.9
|
|
19
19
|
Requires-Dist: podman>=5.4
|
|
20
20
|
Requires-Dist: psutil
|
|
@@ -10,7 +10,7 @@ from concurrent.futures import ThreadPoolExecutor
|
|
|
10
10
|
from typing import TYPE_CHECKING, Any
|
|
11
11
|
|
|
12
12
|
import ophyd
|
|
13
|
-
from ophyd import DeviceStatus, Kind, OphydObject, Staged, StatusBase
|
|
13
|
+
from ophyd import Device, DeviceStatus, Kind, OphydObject, Staged, StatusBase
|
|
14
14
|
from ophyd.utils import errors as ophyd_errors
|
|
15
15
|
|
|
16
16
|
from bec_lib import messages
|
|
@@ -23,7 +23,7 @@ from bec_lib.logger import bec_logger
|
|
|
23
23
|
from bec_lib.messages import BECStatus
|
|
24
24
|
from bec_lib.serialization import json_ext
|
|
25
25
|
from bec_lib.utils.rpc_utils import rgetattr
|
|
26
|
-
from bec_server.device_server.devices.devicemanager import DeviceManagerDS
|
|
26
|
+
from bec_server.device_server.devices.devicemanager import BECMessageSignal, DeviceManagerDS
|
|
27
27
|
from bec_server.device_server.friendly_device_exceptions import reformat_known_device_exceptions
|
|
28
28
|
from bec_server.device_server.ophyd_callback_monitor import OphydCallbackMonitor
|
|
29
29
|
from bec_server.device_server.rpc_handler import RPCHandler
|
|
@@ -566,11 +566,14 @@ class DeviceServer(BECService):
|
|
|
566
566
|
|
|
567
567
|
"""
|
|
568
568
|
action = None
|
|
569
|
+
instructions = msg
|
|
569
570
|
try:
|
|
570
|
-
|
|
571
|
+
action = instructions.content["action"]
|
|
572
|
+
if action == "broadcast_scan_device_info" and not instructions.content["device"]:
|
|
573
|
+
self._broadcast_scan_device_info(instructions)
|
|
574
|
+
return
|
|
571
575
|
if not instructions.content["device"]:
|
|
572
576
|
return
|
|
573
|
-
action = instructions.content["action"]
|
|
574
577
|
self.assert_device_is_valid(instructions)
|
|
575
578
|
if action != "rpc":
|
|
576
579
|
# rpc has its own error handling
|
|
@@ -595,6 +598,8 @@ class DeviceServer(BECService):
|
|
|
595
598
|
self._unstage_device(instructions)
|
|
596
599
|
elif action == "pre_scan":
|
|
597
600
|
self._pre_scan(instructions)
|
|
601
|
+
elif action == "broadcast_scan_device_info":
|
|
602
|
+
self._broadcast_scan_device_info(instructions)
|
|
598
603
|
else:
|
|
599
604
|
logger.warning(f"Received unknown device instruction: {instructions}")
|
|
600
605
|
except ophyd_errors.LimitError as limit_error:
|
|
@@ -606,10 +611,10 @@ class DeviceServer(BECService):
|
|
|
606
611
|
exception_type=limit_error.__class__.__name__,
|
|
607
612
|
device=self.get_device_from_exception(limit_error),
|
|
608
613
|
)
|
|
614
|
+
|
|
609
615
|
self._ensure_request_registered(instructions)
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
)
|
|
616
|
+
if diid := instructions.metadata.get("device_instr_id"):
|
|
617
|
+
self.requests_handler.set_finished(diid, success=False, error_info=error_info)
|
|
613
618
|
|
|
614
619
|
logger.error(content)
|
|
615
620
|
except Exception as exc: # pylint: disable=broad-except
|
|
@@ -631,9 +636,9 @@ class DeviceServer(BECService):
|
|
|
631
636
|
self.rpc_handler.send_rpc_exception(exc, instructions)
|
|
632
637
|
else:
|
|
633
638
|
logger.error(content)
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
639
|
+
|
|
640
|
+
if diid := instructions.metadata.get("device_instr_id"):
|
|
641
|
+
self.requests_handler.set_finished(diid, success=False, error_info=error_info)
|
|
637
642
|
|
|
638
643
|
@staticmethod
|
|
639
644
|
def get_device_from_exception(exc: Exception) -> str | None:
|
|
@@ -1123,3 +1128,52 @@ class DeviceServer(BECService):
|
|
|
1123
1128
|
self.requests_handler.add_status_object(instr.metadata["device_instr_id"], status)
|
|
1124
1129
|
|
|
1125
1130
|
self.requests_handler.patch_num_status_objects(instr, num_status_objects)
|
|
1131
|
+
|
|
1132
|
+
def _broadcast_scan_device_info(self, instr: messages.DeviceInstructionMessage) -> None:
|
|
1133
|
+
"""
|
|
1134
|
+
Broadcast a snapshot of device runtime information for the scan.
|
|
1135
|
+
|
|
1136
|
+
Args:
|
|
1137
|
+
instr (messages.DeviceInstructionMessage): The request containing the devices
|
|
1138
|
+
and scan ID.
|
|
1139
|
+
"""
|
|
1140
|
+
instr_id = instr.metadata["device_instr_id"]
|
|
1141
|
+
self.requests_handler.add_request(instr, num_status_objects=0)
|
|
1142
|
+
|
|
1143
|
+
devices = instr.content["device"]
|
|
1144
|
+
if not isinstance(devices, list):
|
|
1145
|
+
devices = [devices]
|
|
1146
|
+
|
|
1147
|
+
device_info: dict[str, messages.DeviceRuntimeInfo] = {}
|
|
1148
|
+
scan_id = instr.parameter.get("scan_id")
|
|
1149
|
+
if scan_id is None:
|
|
1150
|
+
self.requests_handler.set_finished(instr_id, success=True)
|
|
1151
|
+
return
|
|
1152
|
+
|
|
1153
|
+
for dev in devices:
|
|
1154
|
+
if dev not in self.device_manager.devices:
|
|
1155
|
+
logger.warning(f"Device {dev} not found in device manager. Skipping.")
|
|
1156
|
+
continue
|
|
1157
|
+
obj = self.device_manager.devices.get(dev).obj
|
|
1158
|
+
|
|
1159
|
+
signal_info: dict[str, messages.SignalInfo] = {}
|
|
1160
|
+
if isinstance(obj, Device):
|
|
1161
|
+
for _, sub_name, item in obj.walk_signals():
|
|
1162
|
+
if not isinstance(item, BECMessageSignal):
|
|
1163
|
+
continue
|
|
1164
|
+
signal_info[sub_name] = item.signal_info
|
|
1165
|
+
|
|
1166
|
+
if not signal_info:
|
|
1167
|
+
continue
|
|
1168
|
+
device_info[dev] = messages.DeviceRuntimeInfo(signal_info=signal_info)
|
|
1169
|
+
|
|
1170
|
+
self.connector.xadd(
|
|
1171
|
+
MessageEndpoints.scan_device_info(),
|
|
1172
|
+
{
|
|
1173
|
+
"data": messages.ScanDeviceInfoMessage(
|
|
1174
|
+
devices=device_info, scan_id=scan_id, metadata=instr.metadata
|
|
1175
|
+
)
|
|
1176
|
+
},
|
|
1177
|
+
max_size=10,
|
|
1178
|
+
)
|
|
1179
|
+
self.requests_handler.set_finished(instr_id, success=True)
|
|
@@ -87,6 +87,7 @@ class DirectScanWorker:
|
|
|
87
87
|
raise ScanAbortion(f"Scan is missing required method: {step}")
|
|
88
88
|
self.check_for_interruption()
|
|
89
89
|
method()
|
|
90
|
+
self.run_post_scan_step(step, scan)
|
|
90
91
|
except ScanAbortion as exc:
|
|
91
92
|
if not self._prepare_exception_cleanup(queue, exc):
|
|
92
93
|
return
|
|
@@ -272,3 +273,14 @@ class DirectScanWorker:
|
|
|
272
273
|
self.worker.parent.queue_manager.queues[self.worker.queue_name].abort()
|
|
273
274
|
self.reset()
|
|
274
275
|
self.worker.status = InstructionQueueStatus.RUNNING
|
|
276
|
+
|
|
277
|
+
def run_post_scan_step(self, step: str, scan: ScanBase) -> None:
|
|
278
|
+
"""
|
|
279
|
+
Run the post-scan step for the given scan step.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
step (str): The scan step to run the post-scan method for.
|
|
283
|
+
scan (ScanBase): The scan object to run the post-scan method on.
|
|
284
|
+
"""
|
|
285
|
+
if step == "stage":
|
|
286
|
+
scan.actions._broadcast_scan_device_info()
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
4
|
import os
|
|
5
|
-
import time
|
|
6
5
|
import uuid
|
|
7
6
|
from collections.abc import Iterable
|
|
8
7
|
from string import Template
|
|
@@ -1529,3 +1528,23 @@ class ScanActions:
|
|
|
1529
1528
|
raise ValueError(
|
|
1530
1529
|
f"Invalid template variable: {exc} in the file base path. Please check your service config."
|
|
1531
1530
|
) from exc
|
|
1531
|
+
|
|
1532
|
+
def _broadcast_scan_device_info(self) -> None:
|
|
1533
|
+
"""
|
|
1534
|
+
Emit a device instruction to capture runtime information for this scan.
|
|
1535
|
+
All currently locked devices will be included in this update.
|
|
1536
|
+
|
|
1537
|
+
Note that this is an internal method and should not be called directly by scan implementations.
|
|
1538
|
+
"""
|
|
1539
|
+
devices = self.get_owned_device_locks()
|
|
1540
|
+
if not self._scan.is_scan or self._scan.scan_info.scan_id is None:
|
|
1541
|
+
return
|
|
1542
|
+
status = self._create_status(name="broadcast_scan_device_info")
|
|
1543
|
+
instr = messages.DeviceInstructionMessage(
|
|
1544
|
+
device=devices,
|
|
1545
|
+
action="broadcast_scan_device_info",
|
|
1546
|
+
parameter={"scan_id": self._scan.scan_info.scan_id},
|
|
1547
|
+
metadata={"device_instr_id": status._device_instr_id},
|
|
1548
|
+
)
|
|
1549
|
+
self._send(instr)
|
|
1550
|
+
status.wait()
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bec-server"
|
|
7
|
-
version = "4.
|
|
7
|
+
version = "4.2.0"
|
|
8
8
|
description = "BEC server"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
classifiers = [
|
|
@@ -20,7 +20,7 @@ dependencies = [
|
|
|
20
20
|
"msgpack~=1.0",
|
|
21
21
|
"numpy>=1.24, <3.0",
|
|
22
22
|
"ophyd~=1.9",
|
|
23
|
-
"ophyd_devices>=1.
|
|
23
|
+
"ophyd_devices>=1.51.0",
|
|
24
24
|
"podman>=5.4",
|
|
25
25
|
"psutil",
|
|
26
26
|
"pydantic~=2.8",
|
|
@@ -7,9 +7,10 @@ from unittest.mock import ANY, patch
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pytest
|
|
9
9
|
from loguru import logger
|
|
10
|
-
from ophyd import
|
|
10
|
+
from ophyd import Component as Cpt
|
|
11
|
+
from ophyd import Device, DeviceStatus, Kind, Signal, Staged
|
|
11
12
|
from ophyd.utils import errors as ophyd_errors
|
|
12
|
-
from ophyd_devices import StatusBase
|
|
13
|
+
from ophyd_devices import PreviewSignal, StatusBase
|
|
13
14
|
|
|
14
15
|
from bec_lib import messages
|
|
15
16
|
from bec_lib.alarm_handler import Alarms
|
|
@@ -1026,6 +1027,190 @@ def test_handle_device_instructions_rpc(device_server_mock, instructions):
|
|
|
1026
1027
|
update_device_metadata_mock.assert_called_once_with(instructions)
|
|
1027
1028
|
|
|
1028
1029
|
|
|
1030
|
+
@pytest.mark.parametrize("device", ["samx", []])
|
|
1031
|
+
def test_handle_device_instructions_broadcast_scan_device_info(device_server_mock, device):
|
|
1032
|
+
instructions = messages.DeviceInstructionMessage(
|
|
1033
|
+
device=device,
|
|
1034
|
+
action="broadcast_scan_device_info",
|
|
1035
|
+
parameter={"scan_id": "scan-id-1"},
|
|
1036
|
+
metadata={"RID": "rid-1", "device_instr_id": "broadcast-diid"},
|
|
1037
|
+
)
|
|
1038
|
+
|
|
1039
|
+
with mock.patch.object(
|
|
1040
|
+
device_server_mock,
|
|
1041
|
+
"assert_device_is_valid",
|
|
1042
|
+
wraps=device_server_mock.assert_device_is_valid,
|
|
1043
|
+
) as valid_mock:
|
|
1044
|
+
with mock.patch.object(
|
|
1045
|
+
device_server_mock,
|
|
1046
|
+
"assert_device_is_enabled",
|
|
1047
|
+
wraps=device_server_mock.assert_device_is_enabled,
|
|
1048
|
+
) as enabled_mock:
|
|
1049
|
+
with mock.patch.object(
|
|
1050
|
+
device_server_mock, "_broadcast_scan_device_info"
|
|
1051
|
+
) as broadcast_mock:
|
|
1052
|
+
device_server_mock.handle_device_instructions(instructions)
|
|
1053
|
+
|
|
1054
|
+
broadcast_mock.assert_called_once_with(instructions)
|
|
1055
|
+
if device:
|
|
1056
|
+
valid_mock.assert_called_once_with(instructions)
|
|
1057
|
+
enabled_mock.assert_called_once_with(instructions)
|
|
1058
|
+
else:
|
|
1059
|
+
valid_mock.assert_not_called()
|
|
1060
|
+
enabled_mock.assert_not_called()
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
def test_broadcast_scan_device_info_publishes_device_records(device_server_mock):
|
|
1064
|
+
class Detector(Device):
|
|
1065
|
+
preview = Cpt(PreviewSignal, ndim=2)
|
|
1066
|
+
plain = Cpt(Signal, value=0)
|
|
1067
|
+
|
|
1068
|
+
detector = Detector(name="eiger")
|
|
1069
|
+
detector.preview.signal_info.acquisition_group = "fly-scan"
|
|
1070
|
+
detector.preview.signal_info.use_alias = True
|
|
1071
|
+
detector.preview.signal_info.signal_metadata["processing"] = {"rotation": 90}
|
|
1072
|
+
expected_info = detector.preview.signal_info
|
|
1073
|
+
|
|
1074
|
+
device_server_mock.device_manager.devices = {
|
|
1075
|
+
"eiger": SimpleNamespace(obj=detector),
|
|
1076
|
+
"samx": SimpleNamespace(obj=Signal(name="samx", value=0)),
|
|
1077
|
+
}
|
|
1078
|
+
device_server_mock.connector.xadd = mock.MagicMock()
|
|
1079
|
+
instructions = messages.DeviceInstructionMessage(
|
|
1080
|
+
device=["eiger", "samx"],
|
|
1081
|
+
action="broadcast_scan_device_info",
|
|
1082
|
+
parameter={"scan_id": "scan-id-1"},
|
|
1083
|
+
metadata={"RID": "rid-1", "device_instr_id": "broadcast-diid"},
|
|
1084
|
+
)
|
|
1085
|
+
|
|
1086
|
+
with mock.patch.object(device_server_mock.connector, "send") as send_mock:
|
|
1087
|
+
device_server_mock._broadcast_scan_device_info(instructions)
|
|
1088
|
+
|
|
1089
|
+
device_server_mock.connector.xadd.assert_called_once()
|
|
1090
|
+
endpoint, payload = device_server_mock.connector.xadd.call_args.args
|
|
1091
|
+
msg = payload["data"]
|
|
1092
|
+
assert endpoint == MessageEndpoints.scan_device_info()
|
|
1093
|
+
assert device_server_mock.connector.xadd.call_args.kwargs == {"max_size": 10}
|
|
1094
|
+
assert msg == messages.ScanDeviceInfoMessage(
|
|
1095
|
+
scan_id="scan-id-1",
|
|
1096
|
+
devices={"eiger": messages.DeviceRuntimeInfo(signal_info={"preview": expected_info})},
|
|
1097
|
+
metadata={"RID": "rid-1", "device_instr_id": "broadcast-diid"},
|
|
1098
|
+
)
|
|
1099
|
+
responses = [call.args[1] for call in send_mock.call_args_list]
|
|
1100
|
+
assert [response.status for response in responses] == ["running", "completed"]
|
|
1101
|
+
assert all(response.instruction_id == "broadcast-diid" for response in responses)
|
|
1102
|
+
assert all(response.instruction == instructions for response in responses)
|
|
1103
|
+
assert device_server_mock.requests_handler.get_request("broadcast-diid") is None
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
def test_broadcast_scan_device_info_uses_runtime_metadata(device_server_mock):
|
|
1107
|
+
class SubDetector(Device):
|
|
1108
|
+
preview = Cpt(PreviewSignal, ndim=2)
|
|
1109
|
+
|
|
1110
|
+
class Detector(Device):
|
|
1111
|
+
sub = Cpt(SubDetector)
|
|
1112
|
+
plain = Cpt(Signal, value=0)
|
|
1113
|
+
|
|
1114
|
+
detector = Detector(name="eiger")
|
|
1115
|
+
signal = detector.sub.preview
|
|
1116
|
+
runtime_info = messages.SignalInfo(
|
|
1117
|
+
saved=False,
|
|
1118
|
+
ndim=2,
|
|
1119
|
+
role="preview",
|
|
1120
|
+
enabled=False,
|
|
1121
|
+
use_alias=True,
|
|
1122
|
+
signals=[("image", Kind.hinted.value)],
|
|
1123
|
+
signal_metadata={"units": "counts", "processing": {"rotation": 90}},
|
|
1124
|
+
correlation_group="fly-scan",
|
|
1125
|
+
)
|
|
1126
|
+
signal.signal_info = runtime_info
|
|
1127
|
+
signal.describe = mock.Mock(side_effect=AssertionError("Use the live signal_info model"))
|
|
1128
|
+
|
|
1129
|
+
device_server_mock.device_manager.devices = {"eiger": SimpleNamespace(obj=detector)}
|
|
1130
|
+
device_server_mock.connector.xadd = mock.MagicMock()
|
|
1131
|
+
instructions = messages.DeviceInstructionMessage(
|
|
1132
|
+
device="eiger",
|
|
1133
|
+
action="broadcast_scan_device_info",
|
|
1134
|
+
parameter={"scan_id": "scan-id-1"},
|
|
1135
|
+
metadata={"device_instr_id": "broadcast-diid"},
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
device_server_mock._broadcast_scan_device_info(instructions)
|
|
1139
|
+
|
|
1140
|
+
msg = device_server_mock.connector.xadd.call_args.args[1]["data"]
|
|
1141
|
+
snapshot = msg.devices["eiger"].signal_info["sub.preview"]
|
|
1142
|
+
assert snapshot == runtime_info
|
|
1143
|
+
assert snapshot is runtime_info
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
@pytest.mark.parametrize("devices", [[], ["samx"], ["samx", "empty"]])
|
|
1147
|
+
def test_broadcast_scan_device_info_omits_empty_devices(device_server_mock, devices):
|
|
1148
|
+
class EmptyDetector(Device):
|
|
1149
|
+
plain = Cpt(Signal, value=0)
|
|
1150
|
+
|
|
1151
|
+
device_server_mock.device_manager.devices = {
|
|
1152
|
+
"samx": SimpleNamespace(obj=Signal(name="samx", value=0), enabled=True),
|
|
1153
|
+
"empty": SimpleNamespace(obj=EmptyDetector(name="empty"), enabled=True),
|
|
1154
|
+
}
|
|
1155
|
+
device_server_mock.connector.xadd = mock.MagicMock()
|
|
1156
|
+
instructions = messages.DeviceInstructionMessage(
|
|
1157
|
+
device=devices,
|
|
1158
|
+
action="broadcast_scan_device_info",
|
|
1159
|
+
parameter={"scan_id": "scan-id-1"},
|
|
1160
|
+
metadata={"RID": "rid-1", "device_instr_id": "broadcast-diid"},
|
|
1161
|
+
)
|
|
1162
|
+
|
|
1163
|
+
with mock.patch.object(device_server_mock.connector, "send") as send_mock:
|
|
1164
|
+
device_server_mock.handle_device_instructions(instructions)
|
|
1165
|
+
|
|
1166
|
+
device_server_mock.connector.xadd.assert_called_once()
|
|
1167
|
+
endpoint, payload = device_server_mock.connector.xadd.call_args.args
|
|
1168
|
+
assert endpoint == MessageEndpoints.scan_device_info()
|
|
1169
|
+
assert payload["data"] == messages.ScanDeviceInfoMessage(
|
|
1170
|
+
scan_id="scan-id-1", devices={}, metadata=instructions.metadata
|
|
1171
|
+
)
|
|
1172
|
+
assert [call.args[1].status for call in send_mock.call_args_list] == ["running", "completed"]
|
|
1173
|
+
assert device_server_mock.requests_handler.get_request("broadcast-diid") is None
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
def test_broadcast_scan_device_info_resolves_failure_when_publish_raises(device_server_mock):
|
|
1177
|
+
instructions = messages.DeviceInstructionMessage(
|
|
1178
|
+
device=[],
|
|
1179
|
+
action="broadcast_scan_device_info",
|
|
1180
|
+
parameter={"scan_id": "scan-id-1"},
|
|
1181
|
+
metadata={"RID": "rid-1", "device_instr_id": "broadcast-diid"},
|
|
1182
|
+
)
|
|
1183
|
+
device_server_mock.connector.xadd = mock.MagicMock(side_effect=RuntimeError("publish failed"))
|
|
1184
|
+
|
|
1185
|
+
with mock.patch.object(device_server_mock.connector, "send") as send_mock:
|
|
1186
|
+
device_server_mock.handle_device_instructions(instructions)
|
|
1187
|
+
|
|
1188
|
+
responses = [call.args[1] for call in send_mock.call_args_list]
|
|
1189
|
+
assert [response.status for response in responses] == ["running", "error"]
|
|
1190
|
+
assert responses[-1].error_info.exception_type == "RuntimeError"
|
|
1191
|
+
assert device_server_mock.requests_handler.get_request("broadcast-diid") is None
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
def test_broadcast_scan_device_info_skips_without_scan_id(device_server_mock):
|
|
1195
|
+
device_server_mock.connector.xadd = mock.MagicMock()
|
|
1196
|
+
instructions = messages.DeviceInstructionMessage(
|
|
1197
|
+
device="samx",
|
|
1198
|
+
action="broadcast_scan_device_info",
|
|
1199
|
+
parameter={},
|
|
1200
|
+
metadata={"RID": "rid-1", "device_instr_id": "broadcast-diid"},
|
|
1201
|
+
)
|
|
1202
|
+
|
|
1203
|
+
with mock.patch.object(device_server_mock.connector, "send") as send_mock:
|
|
1204
|
+
device_server_mock._broadcast_scan_device_info(instructions)
|
|
1205
|
+
|
|
1206
|
+
device_server_mock.connector.xadd.assert_not_called()
|
|
1207
|
+
responses = [call.args[1] for call in send_mock.call_args_list]
|
|
1208
|
+
assert [response.status for response in responses] == ["running", "completed"]
|
|
1209
|
+
assert all(response.instruction_id == "broadcast-diid" for response in responses)
|
|
1210
|
+
assert all(response.instruction == instructions for response in responses)
|
|
1211
|
+
assert device_server_mock.requests_handler.get_request("broadcast-diid") is None
|
|
1212
|
+
|
|
1213
|
+
|
|
1029
1214
|
@pytest.mark.parametrize(
|
|
1030
1215
|
"instructions",
|
|
1031
1216
|
[
|
|
@@ -442,6 +442,56 @@ def test_device_instruction_actions_emit_expected_messages(action_context):
|
|
|
442
442
|
assert unstage_msg.metadata["device_instr_id"] == unstage_status._device_instr_id
|
|
443
443
|
|
|
444
444
|
|
|
445
|
+
def test_broadcast_scan_device_info_emits_owned_devices(action_context):
|
|
446
|
+
ctx = action_context()
|
|
447
|
+
ctx.scan.scan_info.metadata["RID"] = "rid-123"
|
|
448
|
+
ctx.device_manager.parent.device_lock_registry = mock.MagicMock()
|
|
449
|
+
ctx.device_manager.parent.device_lock_registry.get_owned_devices.return_value = ["samy", "samx"]
|
|
450
|
+
status = mock.MagicMock(_device_instr_id="diid-123")
|
|
451
|
+
ctx.actions._create_status = mock.MagicMock(return_value=status)
|
|
452
|
+
|
|
453
|
+
ctx.actions._broadcast_scan_device_info()
|
|
454
|
+
|
|
455
|
+
msg = _last_device_instruction(ctx, "broadcast_scan_device_info")
|
|
456
|
+
assert msg.device == ["samx", "samy"]
|
|
457
|
+
assert msg.parameter == {"scan_id": "scan-id-test"}
|
|
458
|
+
assert msg.metadata["device_instr_id"] == "diid-123"
|
|
459
|
+
assert msg.metadata["RID"] == "rid-123"
|
|
460
|
+
assert msg.metadata["scan_id"] == "scan-id-test"
|
|
461
|
+
status.wait.assert_called_once_with()
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def test_broadcast_scan_device_info_emits_without_owned_devices(action_context):
|
|
465
|
+
ctx = action_context()
|
|
466
|
+
ctx.scan.scan_info.metadata["RID"] = "rid-123"
|
|
467
|
+
ctx.device_manager.parent.device_lock_registry = mock.MagicMock()
|
|
468
|
+
ctx.device_manager.parent.device_lock_registry.get_owned_devices.return_value = []
|
|
469
|
+
status = mock.MagicMock(_device_instr_id="diid-empty")
|
|
470
|
+
ctx.actions._create_status = mock.MagicMock(return_value=status)
|
|
471
|
+
|
|
472
|
+
ctx.actions._broadcast_scan_device_info()
|
|
473
|
+
|
|
474
|
+
msg = _last_device_instruction(ctx, "broadcast_scan_device_info")
|
|
475
|
+
assert msg.device == []
|
|
476
|
+
assert msg.parameter == {"scan_id": "scan-id-test"}
|
|
477
|
+
assert msg.metadata["device_instr_id"] == "diid-empty"
|
|
478
|
+
status.wait.assert_called_once_with()
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
@pytest.mark.parametrize(("is_scan", "scan_id"), [(False, "scan-id-test"), (True, None)])
|
|
482
|
+
def test_broadcast_scan_device_info_skips_when_not_scan_or_missing_scan_id(
|
|
483
|
+
action_context, is_scan, scan_id
|
|
484
|
+
):
|
|
485
|
+
ctx = action_context()
|
|
486
|
+
ctx.scan.is_scan = is_scan
|
|
487
|
+
ctx.scan.scan_info.scan_id = scan_id
|
|
488
|
+
ctx.actions._send = mock.MagicMock()
|
|
489
|
+
|
|
490
|
+
ctx.actions._broadcast_scan_device_info()
|
|
491
|
+
|
|
492
|
+
ctx.actions._send.assert_not_called()
|
|
493
|
+
|
|
494
|
+
|
|
445
495
|
def test_device_instruction_actions_use_dotted_name_for_nested_devices(action_context):
|
|
446
496
|
ctx = action_context()
|
|
447
497
|
setpoint = ctx.device_manager.devices.samx.setpoint
|
|
@@ -173,6 +173,7 @@ def make_scan(direct_worker_context):
|
|
|
173
173
|
scan.scan_info.metadata["RID"] = "rid-1"
|
|
174
174
|
scan.actions._send_scan_status = mock.MagicMock()
|
|
175
175
|
scan.actions.send_client_info = mock.MagicMock()
|
|
176
|
+
scan.actions._broadcast_scan_device_info = mock.MagicMock()
|
|
176
177
|
scan._shutdown_event = mock.MagicMock()
|
|
177
178
|
return scan
|
|
178
179
|
|
|
@@ -301,6 +302,22 @@ def test_run_executes_full_scan_sequence_in_order(direct_worker_context, make_sc
|
|
|
301
302
|
assert direct_worker_context.direct_worker.scan is None
|
|
302
303
|
|
|
303
304
|
|
|
305
|
+
def test_run_broadcasts_scan_device_info_after_stage(direct_worker_context, make_scan):
|
|
306
|
+
called_steps = []
|
|
307
|
+
scan = make_scan(called_steps=called_steps)
|
|
308
|
+
direct_worker_context.queue.active_scan = scan
|
|
309
|
+
direct_worker_context.scan_worker.current_instruction_queue_item = direct_worker_context.queue
|
|
310
|
+
direct_worker_context.device_manager._rpc_method = mock.MagicMock(return_value=mock.MagicMock())
|
|
311
|
+
scan.actions._broadcast_scan_device_info = mock.MagicMock(
|
|
312
|
+
side_effect=lambda: called_steps.append("broadcast_scan_device_info")
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
direct_worker_context.direct_worker.run(scan)
|
|
316
|
+
|
|
317
|
+
scan.actions._broadcast_scan_device_info.assert_called_once_with()
|
|
318
|
+
assert called_steps[:4] == ["prepare_scan", "open_scan", "stage", "broadcast_scan_device_info"]
|
|
319
|
+
|
|
320
|
+
|
|
304
321
|
def test_run_initializes_scan_before_scan_sequence(direct_worker_context, make_scan):
|
|
305
322
|
called_steps = []
|
|
306
323
|
scan = make_scan(called_steps=called_steps)
|
|
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_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/devices/config_update_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bec_server-4.1.7 → bec_server-4.2.0}/bec_server/device_server/friendly_device_exceptions.py
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
|