bec-server 4.4.2__tar.gz → 4.5.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.4.2 → bec_server-4.5.0}/PKG-INFO +1 -1
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/direct_scan_worker.py +10 -3
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scan_guard.py +14 -22
- bec_server-4.5.0/bec_server/scan_server/scan_hook_broadcaster.py +114 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scan_queue.py +25 -5
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/scan_actions.py +95 -5
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/scan_modifier.py +7 -2
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/scan_status.py +131 -29
- {bec_server-4.4.2 → bec_server-4.5.0}/pyproject.toml +1 -1
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_scan_actions.py +399 -0
- bec_server-4.5.0/tests/tests_scan_server/scans/test_scan_status.py +501 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_direct_scan_worker.py +113 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_guard.py +103 -6
- bec_server-4.5.0/tests/tests_scan_server/test_scan_hook_broadcaster.py +216 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_modifier.py +98 -1
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_server_queue.py +80 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_worker.py +2 -1
- bec_server-4.4.2/tests/tests_scan_server/scans/test_scan_status.py +0 -146
- {bec_server-4.4.2 → bec_server-4.5.0}/.gitignore +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/.zed/debug.json +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/README.md +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/actors/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/actors/actor.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/actors/builtin_actor_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/actors/manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/actors/scan_interlock.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/actors/worker.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/bec_server_utils/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/bec_server_utils/launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/bec_server_utils/service_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/bec_server_utils/subprocess_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/bec_server_utils/tmux_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/data_processing/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/data_processing/cli/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/data_processing/cli/launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/data_processing/dap_server.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/data_processing/dap_service.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/data_processing/dap_service_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/data_processing/lmfit1d_service.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/bec_message_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/cli/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/cli/launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/device_server.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/devices/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/devices/config_update_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/devices/device_serializer.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/devices/devicemanager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/friendly_device_exceptions.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/ophyd_callback_monitor.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/rpc_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/tests/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/device_server/tests/utils.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/async_writer.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/cli/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/cli/launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/default_writer.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/file_writer.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/file_writer_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/file_writer/merged_dicts.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/Containerfile.bec_linux_base +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/Containerfile.requirements +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/Containerfile.worker +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/_dev_runner.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/builtin_procedures.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/constants.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/container_utils.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/container_worker.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/oop_worker_base.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/procedure_registry.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/protocol.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/queue_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/subprocess_worker.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/procedures/worker_base.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_bundler/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_bundler/bec_emitter.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_bundler/cli/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_bundler/cli/launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_bundler/emitter.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_bundler/scan_bundler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/beamline_state_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/cli/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/cli/launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/device_lock_registry.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/errors.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/instruction_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scan_assembler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scan_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scan_server.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scan_worker.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/acquire.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/cont_line_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/device_rpc.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/fermat_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/grid_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/hexagonal_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/line_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/line_sweep_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/list_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/log_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/move.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/multi_region_grid_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/multi_region_line_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/path_optimization.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/position_generators.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/round_roi_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/round_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/scan_argument_modifier.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/scan_base.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/scan_components.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/time_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/scans/updated_move.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/tests/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/tests/fixtures.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/tests/scan_fixtures.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/tests/scan_hook_tests.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scan_server/tests/utils.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/atlas/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/atlas/atlas_active_client_emitter.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/atlas/atlas_connector.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/atlas/atlas_forwarder.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/atlas/atlas_metadata_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/atlas/atlas_plugin_repo_emitter.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/atlas/config_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/cli/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/cli/launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/scihub.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/service_handler/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/scihub/service_handler/service_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/test/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/test/actor_test_utils.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/bec_server/test/helpers.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_actors/test_actors.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_bec_server_utils/test_main.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_bec_server_utils/test_service_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_bec_server_utils/test_subprocess_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_bec_server_utils/test_tmux_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_data_processing/conftest.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_data_processing/test_dap_cli_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_data_processing/test_dap_server.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_data_processing/test_dap_service_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_data_processing/test_lmfit1d_service.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/conftest.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_config_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_config_metadata_refresh.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_device_instructions.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_device_manager_ds.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_device_serializer.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_device_server.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_device_server_cli_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_ophyd_callback_monitor.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_device_server/test_rpc_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_file_writer/conftest.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_file_writer/test_async_file_writer.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_file_writer/test_file_writer.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_file_writer/test_file_writer_cli_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_file_writer/test_file_writer_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_bundler/conftest.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_bundler/test_bec_emitter.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_bundler/test_scan_bundler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_bundler/test_scan_bundler_cli_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/conftest.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/__init__.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_acquire.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_cont_line_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_device_rpc_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_fermat_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_grid_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_hexagonal_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_line_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_line_sweep_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_list_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_log_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_move_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_multi_region_grid_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_multi_region_line_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_position_preview.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_relative_scan_return_to_start.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_round_roi_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_round_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_scan_components.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_time_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/scans/test_updated_move_scan.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_beamline_state_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_builtin_actor_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_container_utils.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_device_lock_registry.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_instruction_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_path_optimization.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_procedure_container_worker.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_procedure_queue_pool.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_procedure_submission.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_procedure_subprocess_worker.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_procedures.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_argument_modifier.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_assembler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_fixture_imports.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_interlock.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_server_cli_launch.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scan_server/test_scan_server_scan_manager.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/conftest.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/test_atlas_active_client_emitter.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/test_atlas_config_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/test_atlas_connector.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/test_atlas_forwarder.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/test_atlas_metadata_handler.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/test_atlas_plugin_repo_emitter.py +0 -0
- {bec_server-4.4.2 → bec_server-4.5.0}/tests/tests_scihub/test_scihub_cli_launch.py +0 -0
|
@@ -79,6 +79,7 @@ class DirectScanWorker:
|
|
|
79
79
|
scan.actions._update_queue_info_callback = self.update_queue_info
|
|
80
80
|
queue = self.worker.current_instruction_queue_item
|
|
81
81
|
try:
|
|
82
|
+
scan.actions._hook_broadcaster.start()
|
|
82
83
|
with self.worker.device_manager._rpc_method(scan.actions.rpc_call):
|
|
83
84
|
scan.actions._initialize_scan()
|
|
84
85
|
for step in SCAN_SEQUENCE:
|
|
@@ -86,7 +87,8 @@ class DirectScanWorker:
|
|
|
86
87
|
if not method:
|
|
87
88
|
raise ScanAbortion(f"Scan is missing required method: {step}")
|
|
88
89
|
self.check_for_interruption()
|
|
89
|
-
|
|
90
|
+
with scan.actions._scan_hook_context(step):
|
|
91
|
+
method()
|
|
90
92
|
self.run_post_scan_step(step, scan)
|
|
91
93
|
except ScanAbortion as exc:
|
|
92
94
|
if not self._prepare_exception_cleanup(queue, exc):
|
|
@@ -97,7 +99,10 @@ class DirectScanWorker:
|
|
|
97
99
|
return
|
|
98
100
|
self._handle_exception(exc)
|
|
99
101
|
finally:
|
|
100
|
-
|
|
102
|
+
try:
|
|
103
|
+
scan.actions._hook_broadcaster.stop()
|
|
104
|
+
finally:
|
|
105
|
+
self._release_scan_locks(scan)
|
|
101
106
|
|
|
102
107
|
if queue is None:
|
|
103
108
|
return
|
|
@@ -245,7 +250,9 @@ class DirectScanWorker:
|
|
|
245
250
|
try:
|
|
246
251
|
scan._shutdown_event.clear()
|
|
247
252
|
with self.worker.device_manager._rpc_method(scan.actions.rpc_call):
|
|
248
|
-
|
|
253
|
+
# pylint: disable=protected-access
|
|
254
|
+
with scan.actions._scan_hook_context("on_exception"):
|
|
255
|
+
scan.on_exception(hook_exc)
|
|
249
256
|
|
|
250
257
|
except Exception:
|
|
251
258
|
scan.actions.send_client_info("")
|
|
@@ -8,7 +8,6 @@ from typing import TYPE_CHECKING
|
|
|
8
8
|
from bec_lib import messages
|
|
9
9
|
from bec_lib.endpoints import MessageEndpoints
|
|
10
10
|
from bec_lib.logger import bec_logger
|
|
11
|
-
from bec_server.scan_server.scan_queue import ScanQueueStatus
|
|
12
11
|
|
|
13
12
|
logger = bec_logger.logger
|
|
14
13
|
|
|
@@ -308,28 +307,21 @@ class ScanGuard:
|
|
|
308
307
|
logger.error(f"Invalid queue: {target_queue}")
|
|
309
308
|
self._send_scan_queue_order_change_response(False, f"Invalid queue: {target_queue}")
|
|
310
309
|
return
|
|
311
|
-
if self.parent.queue_manager.queues[target_queue].status != ScanQueueStatus.PAUSED:
|
|
312
|
-
logger.error(f"Queue {target_queue} is not paused.")
|
|
313
|
-
self._send_scan_queue_order_change_response(
|
|
314
|
-
False, f"Queue {target_queue} is not paused. Cannot move scans."
|
|
315
|
-
)
|
|
316
|
-
return
|
|
317
|
-
if msg.action == "move_to" and msg.target_position is None:
|
|
318
|
-
logger.error("Missing target_position")
|
|
319
|
-
self._send_scan_queue_order_change_response(
|
|
320
|
-
False, "Missing target_position for move_to"
|
|
321
|
-
)
|
|
322
|
-
return
|
|
323
|
-
|
|
324
310
|
queue = self.parent.queue_manager.queues[target_queue]
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
311
|
+
with queue._lock: # pylint: disable=protected-access
|
|
312
|
+
active = queue.active_instruction_queue
|
|
313
|
+
if active is not None and msg.scan_id in active.scan_id:
|
|
314
|
+
rejection = "The running scan cannot be moved."
|
|
315
|
+
elif msg.action == "move_to" and msg.target_position is None:
|
|
316
|
+
rejection = "Missing target_position for move_to"
|
|
317
|
+
elif not any(msg.scan_id in scan.scan_id for scan in queue.queue):
|
|
318
|
+
rejection = f"Scan {msg.scan_id} not found in queue {target_queue}"
|
|
319
|
+
else:
|
|
320
|
+
rejection = None
|
|
321
|
+
|
|
322
|
+
if rejection is not None:
|
|
323
|
+
logger.error(rejection)
|
|
324
|
+
self._send_scan_queue_order_change_response(False, rejection)
|
|
333
325
|
return
|
|
334
326
|
self.device_manager.connector.send(sqoc, msg)
|
|
335
327
|
self._send_scan_queue_order_change_response(True, "Order change accepted")
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Broadcast and store the latest scan lifecycle or instruction update for clients."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import threading
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from bec_lib import messages
|
|
9
|
+
from bec_lib.endpoints import MessageEndpoints
|
|
10
|
+
from bec_lib.logger import bec_logger
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from bec_lib.redis_connector import RedisConnector
|
|
14
|
+
|
|
15
|
+
logger = bec_logger.logger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ScanHookBroadcaster:
|
|
19
|
+
"""Send only the latest update in each 0.1 second broadcast window, unless flushed at once."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, connector: RedisConnector) -> None:
|
|
22
|
+
self._connector = connector
|
|
23
|
+
self._lock = threading.Lock()
|
|
24
|
+
self._publish_lock = threading.Lock()
|
|
25
|
+
self._latest_update: messages.ScanHookMessage | None = None
|
|
26
|
+
self._timer: threading.Timer | None = None
|
|
27
|
+
self._active = False
|
|
28
|
+
self._stopped = False
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def active(self) -> bool:
|
|
32
|
+
"""Whether events are collected, i.e. the scan worker is executing the scan."""
|
|
33
|
+
with self._lock:
|
|
34
|
+
return self._active
|
|
35
|
+
|
|
36
|
+
def start(self) -> None:
|
|
37
|
+
"""Enable event collection when the scan worker begins execution."""
|
|
38
|
+
with self._lock:
|
|
39
|
+
if self._stopped:
|
|
40
|
+
raise RuntimeError("A stopped scan hook broadcaster cannot be restarted.")
|
|
41
|
+
self._active = True
|
|
42
|
+
|
|
43
|
+
def stop(self) -> None:
|
|
44
|
+
"""Stop collection, join the pending timer, and attempt final delivery."""
|
|
45
|
+
with self._lock:
|
|
46
|
+
if self._stopped:
|
|
47
|
+
return
|
|
48
|
+
self._stopped = True
|
|
49
|
+
self._active = False
|
|
50
|
+
timer = self._timer
|
|
51
|
+
if timer is not None:
|
|
52
|
+
timer.cancel()
|
|
53
|
+
if timer is not None and timer is not threading.current_thread():
|
|
54
|
+
timer.join()
|
|
55
|
+
self._flush_scheduled()
|
|
56
|
+
|
|
57
|
+
def add(self, event: messages.ScanHookMessage) -> None:
|
|
58
|
+
"""Replace the pending update and schedule a flush when the first event arrives.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
event (messages.ScanHookMessage): Lifecycle or instruction event to broadcast.
|
|
62
|
+
"""
|
|
63
|
+
with self._lock:
|
|
64
|
+
if not self._active:
|
|
65
|
+
return
|
|
66
|
+
self._latest_update = event
|
|
67
|
+
if self._timer is None:
|
|
68
|
+
self._timer = threading.Timer(0.1, self._flush_scheduled)
|
|
69
|
+
self._timer.daemon = True
|
|
70
|
+
self._timer.start()
|
|
71
|
+
|
|
72
|
+
def _flush_scheduled(self) -> None:
|
|
73
|
+
try:
|
|
74
|
+
self.flush()
|
|
75
|
+
except Exception: # pylint: disable=broad-except
|
|
76
|
+
logger.exception("Failed to broadcast scan hook events")
|
|
77
|
+
|
|
78
|
+
def flush_now(self) -> None:
|
|
79
|
+
"""Send the pending update without waiting for the window, e.g. for a step change.
|
|
80
|
+
|
|
81
|
+
A failed publication is logged and does not interrupt the caller.
|
|
82
|
+
"""
|
|
83
|
+
self._flush_scheduled()
|
|
84
|
+
|
|
85
|
+
def flush(self) -> None:
|
|
86
|
+
"""Send the latest pending update and cancel the pending timer.
|
|
87
|
+
|
|
88
|
+
Scans call this on every exit path to deliver their final update.
|
|
89
|
+
Failed publications retain the update for retry unless a newer one arrives.
|
|
90
|
+
"""
|
|
91
|
+
timer = None
|
|
92
|
+
try:
|
|
93
|
+
# Serialize publications without blocking producers on network I/O.
|
|
94
|
+
with self._publish_lock:
|
|
95
|
+
with self._lock:
|
|
96
|
+
timer = self._timer
|
|
97
|
+
self._timer = None
|
|
98
|
+
if timer is not None:
|
|
99
|
+
timer.cancel()
|
|
100
|
+
event = self._latest_update
|
|
101
|
+
self._latest_update = None
|
|
102
|
+
if event is None:
|
|
103
|
+
return
|
|
104
|
+
try:
|
|
105
|
+
self._connector.set_and_publish(MessageEndpoints.scan_hook(), event)
|
|
106
|
+
except Exception:
|
|
107
|
+
with self._lock:
|
|
108
|
+
if not self._stopped and self._latest_update is None:
|
|
109
|
+
self._latest_update = event
|
|
110
|
+
raise
|
|
111
|
+
finally:
|
|
112
|
+
# A timer may itself be waiting to publish, so release both locks first.
|
|
113
|
+
if timer is not None and timer is not threading.current_thread():
|
|
114
|
+
timer.join()
|
|
@@ -237,14 +237,21 @@ class QueueManager:
|
|
|
237
237
|
msg (messages.ScanQueueOrderMessage): ScanQueueOrderMessage
|
|
238
238
|
|
|
239
239
|
"""
|
|
240
|
-
|
|
240
|
+
target_queue = msg.queue
|
|
241
|
+
# take the worker's queue lock first (same order as the worker) so the running item
|
|
242
|
+
# cannot be popped while we decide what may move
|
|
243
|
+
with self.queues[target_queue]._lock, self._lock:
|
|
241
244
|
logger.info(f"Handling scan queue order change: {msg}")
|
|
242
|
-
target_queue = msg.queue
|
|
243
245
|
queue = self.queues[target_queue].queue
|
|
244
246
|
queue_item = self._get_queue_item_by_scan_id(msg)
|
|
245
247
|
if not queue_item:
|
|
246
248
|
logger.error(f"Scan {msg.scan_id} not found in queue {target_queue}")
|
|
247
249
|
return
|
|
250
|
+
# in a running queue, the active item stays first and nothing moves in front of it
|
|
251
|
+
first = self._first_movable_index(target_queue)
|
|
252
|
+
if queue.index(queue_item) < first:
|
|
253
|
+
logger.error(f"Scan {msg.scan_id} is running and cannot be moved")
|
|
254
|
+
return
|
|
248
255
|
|
|
249
256
|
if msg.action == "move_to":
|
|
250
257
|
# move the scan to the target position
|
|
@@ -252,7 +259,7 @@ class QueueManager:
|
|
|
252
259
|
logger.error("Missing target_position")
|
|
253
260
|
return
|
|
254
261
|
|
|
255
|
-
position = max(
|
|
262
|
+
position = max(first, min(msg.target_position, len(queue) - 1))
|
|
256
263
|
|
|
257
264
|
queue.remove(queue_item)
|
|
258
265
|
queue.insert(position, queue_item)
|
|
@@ -260,7 +267,7 @@ class QueueManager:
|
|
|
260
267
|
if msg.action == "move_up":
|
|
261
268
|
# move the scan up by one position
|
|
262
269
|
idx = queue.index(queue_item)
|
|
263
|
-
if idx
|
|
270
|
+
if idx <= first:
|
|
264
271
|
return
|
|
265
272
|
queue.remove(queue_item)
|
|
266
273
|
queue.insert(idx - 1, queue_item)
|
|
@@ -276,7 +283,7 @@ class QueueManager:
|
|
|
276
283
|
if msg.action == "move_top":
|
|
277
284
|
# move the scan to the top of the queue
|
|
278
285
|
queue.remove(queue_item)
|
|
279
|
-
queue.insert(
|
|
286
|
+
queue.insert(first, queue_item)
|
|
280
287
|
|
|
281
288
|
if msg.action == "move_bottom":
|
|
282
289
|
# move the scan to the bottom of the queue
|
|
@@ -285,6 +292,19 @@ class QueueManager:
|
|
|
285
292
|
|
|
286
293
|
self.send_queue_status()
|
|
287
294
|
|
|
295
|
+
def _first_movable_index(self, queue_name: str) -> int:
|
|
296
|
+
"""
|
|
297
|
+
Index of the first queue item that may be moved: 1 while the active item is at the head,
|
|
298
|
+
paused or not, else 0. Nothing may move in front of the active item: the worker pops the
|
|
299
|
+
head once the active item is done, so anything placed before it would leave the finished
|
|
300
|
+
item in the queue to be started again.
|
|
301
|
+
"""
|
|
302
|
+
scan_queue = self.queues[queue_name]
|
|
303
|
+
active = scan_queue.active_instruction_queue
|
|
304
|
+
if active is not None and scan_queue.queue and scan_queue.queue[0] is active:
|
|
305
|
+
return 1
|
|
306
|
+
return 0
|
|
307
|
+
|
|
288
308
|
def _get_queue_item_by_scan_id(
|
|
289
309
|
self, msg: messages.ScanQueueOrderMessage
|
|
290
310
|
) -> DirectInstructionQueueItem | None:
|
|
@@ -2,8 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
4
|
import os
|
|
5
|
+
import time
|
|
5
6
|
import uuid
|
|
6
|
-
from collections.abc import Iterable
|
|
7
|
+
from collections.abc import Iterable, Iterator
|
|
8
|
+
from contextlib import contextmanager
|
|
7
9
|
from string import Template
|
|
8
10
|
from typing import TYPE_CHECKING, Any, Callable, Literal, TypeAlias
|
|
9
11
|
|
|
@@ -18,6 +20,8 @@ from bec_lib.logger import bec_logger
|
|
|
18
20
|
from bec_lib.messaging_hooks import MessagingEvent
|
|
19
21
|
from bec_lib.messaging_services import NotificationMessageObject
|
|
20
22
|
from bec_lib.utils.scan_utils import compose_cli_input_from_scan_info
|
|
23
|
+
from bec_server.scan_server.errors import UserScanInterruption
|
|
24
|
+
from bec_server.scan_server.scan_hook_broadcaster import ScanHookBroadcaster
|
|
21
25
|
from bec_server.scan_server.scans.scan_status import ScanStatus
|
|
22
26
|
|
|
23
27
|
if TYPE_CHECKING:
|
|
@@ -67,6 +71,84 @@ class ScanActions:
|
|
|
67
71
|
self._metadata_suffix = ""
|
|
68
72
|
self._queued_device_locks: set[str] = set()
|
|
69
73
|
self._scan_running = False
|
|
74
|
+
self._scan_hook_stack: list[str] = []
|
|
75
|
+
self._step_started_at: float | None = None
|
|
76
|
+
self._hook_broadcaster = ScanHookBroadcaster(self._connector)
|
|
77
|
+
|
|
78
|
+
@contextmanager
|
|
79
|
+
def _scan_hook_context(self, hook: str) -> Iterator[None]:
|
|
80
|
+
"""
|
|
81
|
+
Broadcast lifecycle hooks, reporting per-point execution as scan_core. The start, end and
|
|
82
|
+
failure of a top-level step are sent at once, so no step or error is lost to coalescing.
|
|
83
|
+
A step ended by a user or alarm interruption (finish now, abort, halt) is reported as
|
|
84
|
+
interrupted, any other exception as an error.
|
|
85
|
+
"""
|
|
86
|
+
if hook == "at_each_point":
|
|
87
|
+
hook = "scan_core"
|
|
88
|
+
if self._scan_hook_stack and self._scan_hook_stack[-1] == hook:
|
|
89
|
+
yield
|
|
90
|
+
return
|
|
91
|
+
is_step = not self._scan_hook_stack
|
|
92
|
+
if is_step and self._hook_broadcaster.active:
|
|
93
|
+
self._step_started_at = time.time()
|
|
94
|
+
self._scan_hook_stack.append(hook)
|
|
95
|
+
try:
|
|
96
|
+
self._broadcast_scan_hook(flush=is_step)
|
|
97
|
+
yield
|
|
98
|
+
except UserScanInterruption:
|
|
99
|
+
self._broadcast_scan_hook(status="interrupted", flush=is_step)
|
|
100
|
+
raise
|
|
101
|
+
except BaseException:
|
|
102
|
+
self._broadcast_scan_hook(status="error", flush=is_step)
|
|
103
|
+
raise
|
|
104
|
+
else:
|
|
105
|
+
self._broadcast_scan_hook(status="completed", flush=is_step)
|
|
106
|
+
finally:
|
|
107
|
+
self._scan_hook_stack.pop()
|
|
108
|
+
if self._scan_hook_stack:
|
|
109
|
+
self._broadcast_scan_hook()
|
|
110
|
+
else:
|
|
111
|
+
self._step_started_at = None
|
|
112
|
+
|
|
113
|
+
def _broadcast_scan_hook(
|
|
114
|
+
self,
|
|
115
|
+
instructions: list[messages.DeviceInstructionMessage] | None = None,
|
|
116
|
+
status: Literal["running", "completed", "interrupted", "error"] = "running",
|
|
117
|
+
waiting: bool = False,
|
|
118
|
+
wait_started_at: float | None = None,
|
|
119
|
+
flush: bool = False,
|
|
120
|
+
) -> None:
|
|
121
|
+
"""
|
|
122
|
+
Publish the current hook with the scan's original correlation metadata.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
flush (bool): Send at once instead of at the end of the 0.1 second window.
|
|
126
|
+
"""
|
|
127
|
+
scan_info = self._scan.scan_info
|
|
128
|
+
if scan_info.scan_id is None:
|
|
129
|
+
return
|
|
130
|
+
self._hook_broadcaster.add(
|
|
131
|
+
messages.ScanHookMessage(
|
|
132
|
+
scan_id=scan_info.scan_id,
|
|
133
|
+
hook=self._scan_hook_stack[-1] if self._scan_hook_stack else None,
|
|
134
|
+
status=status,
|
|
135
|
+
instructions=instructions or [],
|
|
136
|
+
waiting=waiting,
|
|
137
|
+
wait_started_at=wait_started_at,
|
|
138
|
+
hook_started_at=self._step_started_at,
|
|
139
|
+
metadata={**scan_info.metadata, "scan_id": scan_info.scan_id},
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
if flush:
|
|
143
|
+
self._hook_broadcaster.flush_now()
|
|
144
|
+
|
|
145
|
+
def _on_status_wait(self, status: ScanStatus) -> None:
|
|
146
|
+
"""Report pending instructions; the next lifecycle or instruction update replaces the wait."""
|
|
147
|
+
self._broadcast_scan_hook(
|
|
148
|
+
instructions=status.pending_instructions,
|
|
149
|
+
waiting=True,
|
|
150
|
+
wait_started_at=status.wait_started_at,
|
|
151
|
+
)
|
|
70
152
|
|
|
71
153
|
@property
|
|
72
154
|
def readout_priority(self) -> dict:
|
|
@@ -649,10 +731,13 @@ class ScanActions:
|
|
|
649
731
|
metadata={"device_instr_id": status._device_instr_id},
|
|
650
732
|
)
|
|
651
733
|
self._send(instr)
|
|
652
|
-
if
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
734
|
+
# The exposure delay blocks execution even if the trigger has already completed.
|
|
735
|
+
# pylint: disable=protected-access
|
|
736
|
+
with status._wait_context(waiting=bool(min_wait and min_wait > 0)):
|
|
737
|
+
if min_wait is not None:
|
|
738
|
+
self._shutdown_event.wait(min_wait)
|
|
739
|
+
if wait:
|
|
740
|
+
status.wait()
|
|
656
741
|
return status
|
|
657
742
|
|
|
658
743
|
@requires_scan_is_running
|
|
@@ -1045,6 +1130,7 @@ class ScanActions:
|
|
|
1045
1130
|
registry=self._status_registry,
|
|
1046
1131
|
is_container=is_container,
|
|
1047
1132
|
name=name,
|
|
1133
|
+
wait_callback=self._on_status_wait,
|
|
1048
1134
|
)
|
|
1049
1135
|
self._status_registry[status._device_instr_id] = status
|
|
1050
1136
|
return status
|
|
@@ -1076,7 +1162,11 @@ class ScanActions:
|
|
|
1076
1162
|
instr_devices = msg.device if isinstance(msg.device, list) else [msg.device]
|
|
1077
1163
|
if set(instr_devices) & self._devices_with_required_response:
|
|
1078
1164
|
msg.metadata["response"] = True
|
|
1165
|
+
status = self._status_registry.get(msg.metadata.get("device_instr_id"))
|
|
1166
|
+
if status is not None:
|
|
1167
|
+
status.instruction = msg
|
|
1079
1168
|
self._connector.send(MessageEndpoints.device_instructions(), msg)
|
|
1169
|
+
self._broadcast_scan_hook(instructions=[msg])
|
|
1080
1170
|
|
|
1081
1171
|
def _get_message_metadata(self) -> dict:
|
|
1082
1172
|
metadata = {}
|
|
@@ -101,8 +101,8 @@ def scan_hook(func):
|
|
|
101
101
|
in the appropriate order.
|
|
102
102
|
"""
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
def
|
|
104
|
+
# pylint: disable=protected-access
|
|
105
|
+
def dispatch(self, *args, **kwargs):
|
|
106
106
|
if func.__name__ not in self._scan_modifier_hooks:
|
|
107
107
|
return func(self, *args, **kwargs)
|
|
108
108
|
|
|
@@ -131,6 +131,11 @@ def scan_hook(func):
|
|
|
131
131
|
|
|
132
132
|
return
|
|
133
133
|
|
|
134
|
+
@wraps(func)
|
|
135
|
+
def wrapper(self, *args, **kwargs):
|
|
136
|
+
with self.actions._scan_hook_context(func.__name__):
|
|
137
|
+
return dispatch(self, *args, **kwargs)
|
|
138
|
+
|
|
134
139
|
# pylint: disable=protected-access
|
|
135
140
|
wrapper._scan_hook_info = {"method_name": func.__name__} # type: ignore
|
|
136
141
|
wrapper._scan_hook_original = func # type: ignore[attr-defined]
|