bec-server 4.3.0__tar.gz → 4.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. {bec_server-4.3.0 → bec_server-4.3.2}/PKG-INFO +1 -1
  2. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/worker.py +5 -15
  3. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/constants.py +21 -2
  4. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/container_utils.py +74 -5
  5. bec_server-4.3.2/bec_server/procedures/container_worker.py +152 -0
  6. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/manager.py +82 -117
  7. bec_server-4.3.2/bec_server/procedures/oop_worker_base.py +603 -0
  8. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/protocol.py +11 -0
  9. bec_server-4.3.2/bec_server/procedures/queue_manager.py +598 -0
  10. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/subprocess_worker.py +38 -18
  11. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/worker_base.py +44 -10
  12. {bec_server-4.3.0 → bec_server-4.3.2}/pyproject.toml +1 -1
  13. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_actors/test_actors.py +27 -2
  14. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_container_utils.py +93 -0
  15. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_procedure_container_worker.py +143 -2
  16. bec_server-4.3.2/tests/tests_scan_server/test_procedure_queue_pool.py +608 -0
  17. bec_server-4.3.2/tests/tests_scan_server/test_procedure_submission.py +137 -0
  18. bec_server-4.3.2/tests/tests_scan_server/test_procedure_subprocess_worker.py +490 -0
  19. bec_server-4.3.2/tests/tests_scan_server/test_procedures.py +313 -0
  20. bec_server-4.3.0/bec_server/procedures/container_worker.py +0 -78
  21. bec_server-4.3.0/bec_server/procedures/oop_worker_base.py +0 -248
  22. bec_server-4.3.0/tests/tests_scan_server/test_procedures.py +0 -678
  23. {bec_server-4.3.0 → bec_server-4.3.2}/.gitignore +0 -0
  24. {bec_server-4.3.0 → bec_server-4.3.2}/.zed/debug.json +0 -0
  25. {bec_server-4.3.0 → bec_server-4.3.2}/README.md +0 -0
  26. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/__init__.py +0 -0
  27. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/__init__.py +0 -0
  28. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/actor.py +0 -0
  29. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/builtin_actor_manager.py +0 -0
  30. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/manager.py +0 -0
  31. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/scan_interlock.py +0 -0
  32. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/__init__.py +0 -0
  33. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/launch.py +0 -0
  34. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/service_handler.py +0 -0
  35. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/subprocess_launch.py +0 -0
  36. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/tmux_launch.py +0 -0
  37. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/__init__.py +0 -0
  38. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/cli/__init__.py +0 -0
  39. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/cli/launch.py +0 -0
  40. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/dap_server.py +0 -0
  41. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/dap_service.py +0 -0
  42. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/dap_service_manager.py +0 -0
  43. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/lmfit1d_service.py +0 -0
  44. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/__init__.py +0 -0
  45. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/bec_message_handler.py +0 -0
  46. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/cli/__init__.py +0 -0
  47. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/cli/launch.py +0 -0
  48. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/device_server.py +0 -0
  49. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/__init__.py +0 -0
  50. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/config_update_handler.py +0 -0
  51. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/device_serializer.py +0 -0
  52. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/devicemanager.py +0 -0
  53. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/friendly_device_exceptions.py +0 -0
  54. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/ophyd_callback_monitor.py +0 -0
  55. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/rpc_handler.py +0 -0
  56. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/tests/__init__.py +0 -0
  57. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/tests/utils.py +0 -0
  58. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/__init__.py +0 -0
  59. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/async_writer.py +0 -0
  60. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/cli/__init__.py +0 -0
  61. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/cli/launch.py +0 -0
  62. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/default_writer.py +0 -0
  63. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/file_writer.py +0 -0
  64. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/file_writer_manager.py +0 -0
  65. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/merged_dicts.py +0 -0
  66. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/Containerfile.bec_linux_base +0 -0
  67. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/Containerfile.requirements +0 -0
  68. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/Containerfile.worker +0 -0
  69. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/__init__.py +0 -0
  70. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/_dev_runner.py +0 -0
  71. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/builtin_procedures.py +0 -0
  72. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/procedure_registry.py +0 -0
  73. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/__init__.py +0 -0
  74. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/bec_emitter.py +0 -0
  75. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/cli/__init__.py +0 -0
  76. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/cli/launch.py +0 -0
  77. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/emitter.py +0 -0
  78. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/scan_bundler.py +0 -0
  79. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/__init__.py +0 -0
  80. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/beamline_state_manager.py +0 -0
  81. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/cli/__init__.py +0 -0
  82. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/cli/launch.py +0 -0
  83. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/device_lock_registry.py +0 -0
  84. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/direct_scan_worker.py +0 -0
  85. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/errors.py +0 -0
  86. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/instruction_handler.py +0 -0
  87. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_assembler.py +0 -0
  88. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_guard.py +0 -0
  89. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_manager.py +0 -0
  90. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_queue.py +0 -0
  91. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_server.py +0 -0
  92. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_worker.py +0 -0
  93. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/__init__.py +0 -0
  94. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/acquire.py +0 -0
  95. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/cont_line_scan.py +0 -0
  96. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/device_rpc.py +0 -0
  97. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/fermat_scan.py +0 -0
  98. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/grid_scan.py +0 -0
  99. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/hexagonal_scan.py +0 -0
  100. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/line_scan.py +0 -0
  101. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/line_sweep_scan.py +0 -0
  102. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/list_scan.py +0 -0
  103. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/log_scan.py +0 -0
  104. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/move.py +0 -0
  105. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/multi_region_grid_scan.py +0 -0
  106. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/multi_region_line_scan.py +0 -0
  107. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/path_optimization.py +0 -0
  108. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/position_generators.py +0 -0
  109. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/round_roi_scan.py +0 -0
  110. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/round_scan.py +0 -0
  111. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_actions.py +0 -0
  112. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_argument_modifier.py +0 -0
  113. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_base.py +0 -0
  114. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_components.py +0 -0
  115. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_modifier.py +0 -0
  116. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_status.py +0 -0
  117. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/time_scan.py +0 -0
  118. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/updated_move.py +0 -0
  119. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/__init__.py +0 -0
  120. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/fixtures.py +0 -0
  121. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/scan_fixtures.py +0 -0
  122. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/scan_hook_tests.py +0 -0
  123. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/utils.py +0 -0
  124. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/__init__.py +0 -0
  125. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/__init__.py +0 -0
  126. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_active_client_emitter.py +0 -0
  127. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_connector.py +0 -0
  128. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_forwarder.py +0 -0
  129. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_metadata_handler.py +0 -0
  130. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_plugin_repo_emitter.py +0 -0
  131. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/config_handler.py +0 -0
  132. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/cli/__init__.py +0 -0
  133. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/cli/launch.py +0 -0
  134. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/scihub.py +0 -0
  135. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/service_handler/__init__.py +0 -0
  136. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/service_handler/service_handler.py +0 -0
  137. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/test/__init__.py +0 -0
  138. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/test/actor_test_utils.py +0 -0
  139. {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/test/helpers.py +0 -0
  140. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_main.py +0 -0
  141. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_service_handler.py +0 -0
  142. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_subprocess_launch.py +0 -0
  143. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_tmux_launch.py +0 -0
  144. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/conftest.py +0 -0
  145. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_dap_cli_launch.py +0 -0
  146. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_dap_server.py +0 -0
  147. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_dap_service_manager.py +0 -0
  148. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_lmfit1d_service.py +0 -0
  149. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/conftest.py +0 -0
  150. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_config_handler.py +0 -0
  151. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_instructions.py +0 -0
  152. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_manager_ds.py +0 -0
  153. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_serializer.py +0 -0
  154. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_server.py +0 -0
  155. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_server_cli_launch.py +0 -0
  156. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_ophyd_callback_monitor.py +0 -0
  157. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_rpc_handler.py +0 -0
  158. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/conftest.py +0 -0
  159. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_async_file_writer.py +0 -0
  160. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_file_writer.py +0 -0
  161. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_file_writer_cli_launch.py +0 -0
  162. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_file_writer_manager.py +0 -0
  163. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/conftest.py +0 -0
  164. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/test_bec_emitter.py +0 -0
  165. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/test_scan_bundler.py +0 -0
  166. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/test_scan_bundler_cli_launch.py +0 -0
  167. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/conftest.py +0 -0
  168. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/__init__.py +0 -0
  169. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_acquire.py +0 -0
  170. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_cont_line_scan.py +0 -0
  171. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_device_rpc_scan.py +0 -0
  172. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_fermat_scan.py +0 -0
  173. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_grid_scan.py +0 -0
  174. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_hexagonal_scan.py +0 -0
  175. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_line_scan.py +0 -0
  176. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_line_sweep_scan.py +0 -0
  177. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_list_scan.py +0 -0
  178. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_log_scan.py +0 -0
  179. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_move_scan.py +0 -0
  180. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_multi_region_grid_scan.py +0 -0
  181. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_multi_region_line_scan.py +0 -0
  182. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_position_preview.py +0 -0
  183. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_relative_scan_return_to_start.py +0 -0
  184. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_round_roi_scan.py +0 -0
  185. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_round_scan.py +0 -0
  186. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_scan_actions.py +0 -0
  187. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_scan_components.py +0 -0
  188. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_scan_status.py +0 -0
  189. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_time_scan.py +0 -0
  190. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_updated_move_scan.py +0 -0
  191. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_beamline_state_manager.py +0 -0
  192. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_builtin_actor_manager.py +0 -0
  193. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_device_lock_registry.py +0 -0
  194. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_direct_scan_worker.py +0 -0
  195. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_instruction_handler.py +0 -0
  196. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_path_optimization.py +0 -0
  197. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_argument_modifier.py +0 -0
  198. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_assembler.py +0 -0
  199. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_fixture_imports.py +0 -0
  200. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_guard.py +0 -0
  201. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_interlock.py +0 -0
  202. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_modifier.py +0 -0
  203. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_server_cli_launch.py +0 -0
  204. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_server_queue.py +0 -0
  205. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_server_scan_manager.py +0 -0
  206. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_worker.py +0 -0
  207. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/conftest.py +0 -0
  208. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_active_client_emitter.py +0 -0
  209. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_config_handler.py +0 -0
  210. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_connector.py +0 -0
  211. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_forwarder.py +0 -0
  212. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_metadata_handler.py +0 -0
  213. {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_plugin_repo_emitter.py +0 -0
  214. {bec_server-4.3.0 → bec_server-4.3.2}/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.0
3
+ Version: 4.3.2
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
@@ -1,14 +1,12 @@
1
1
  import importlib
2
2
  import os
3
- from contextlib import redirect_stdout
4
3
  from inspect import isclass
5
4
 
6
5
  from bec_lib.client import BECClient
7
- from bec_lib.logger import LogLevel, bec_logger
6
+ from bec_lib.logger import bec_logger
8
7
  from bec_lib.messages import ProcedureWorkerStatus
9
- from bec_lib.redis_connector import RedisConnector
10
8
  from bec_server.actors.actor import ActorBase
11
- from bec_server.procedures.oop_worker_base import RedisOutputDiverter, get_env, push_status, setup
9
+ from bec_server.procedures.oop_worker_base import get_env, push_status, setup
12
10
  from bec_server.procedures.subprocess_worker import SubProcessWorker
13
11
 
14
12
  logger = bec_logger.logger
@@ -53,20 +51,12 @@ def get_actor_env():
53
51
  def main():
54
52
  env, helper, client, conn = setup(get_env())
55
53
  actor_env = get_actor_env()
56
- logger_connector = RedisConnector(env["redis_server"])
57
- output_diverter = RedisOutputDiverter(logger_connector, env["queue"])
58
- with redirect_stdout(output_diverter):
59
- logger.add(
60
- output_diverter,
61
- level=LogLevel.SUCCESS,
62
- format=bec_logger.formatting(is_container=True),
63
- filter=bec_logger.filter(),
64
- )
65
- logger.success(f"Starting ActorProcedureWorker with env: {actor_env}")
54
+ # The parent SubProcessWorker streams stdout and stderr to Redis.
55
+ logger.success(f"Starting ActorProcedureWorker with env: {actor_env}")
66
56
  push_status(conn, env["queue"], ProcedureWorkerStatus.IDLE)
67
57
  actor_procedure(bec=client, **actor_env)
58
+ push_status(conn, env["queue"], ProcedureWorkerStatus.FINISHED)
68
59
  conn.shutdown()
69
- logger_connector.shutdown()
70
60
 
71
61
 
72
62
  if __name__ == "__main__":
@@ -18,6 +18,7 @@ class OopWorkerEnv(TypedDict):
18
18
  queue: str
19
19
  timeout_s: str
20
20
  client_class: NotRequired[BecClientType]
21
+ worker_id: NotRequired[str]
21
22
 
22
23
 
23
24
  P = ParamSpec("P")
@@ -33,7 +34,25 @@ class BecProcedure(Protocol[P]):
33
34
  def __call__(self, *args: P.args, **kwargs: P.kwargs) -> None: ...
34
35
 
35
36
 
36
- class ProcedureWorkerError(RuntimeError): ...
37
+ class ProcedureWorkerFailure(str, Enum):
38
+ """Fixed, credential-free descriptions suitable for public execution status."""
39
+
40
+ STARTUP = "Procedure worker startup failed"
41
+ AUTHENTICATION = "Procedure worker authentication failed"
42
+ EXITED = "Procedure worker exited unexpectedly"
43
+ INPUT_CLOSED = "Procedure worker input closed unexpectedly"
44
+ ABORTED = "Procedure worker was aborted"
45
+
46
+
47
+ class ProcedureWorkerError(RuntimeError):
48
+ """Worker failure with an optional safe category for public status."""
49
+
50
+ def __init__(self, *args: object, failure: ProcedureWorkerFailure | None = None) -> None:
51
+ """Default to the public failure description unless internal details are supplied."""
52
+ if not args and failure is not None:
53
+ args = (failure.value,)
54
+ super().__init__(*args)
55
+ self.failure = failure
37
56
 
38
57
 
39
58
  class WorkerAlreadyExists(ProcedureWorkerError): ...
@@ -48,7 +67,7 @@ class NoImage(ProcedureWorkerError): ...
48
67
  @dataclass(frozen=True)
49
68
  class _WORKER:
50
69
  MAX_WORKERS = 10
51
- QUEUE_TIMEOUT_S = 10
70
+ QUEUE_TIMEOUT_S = 60
52
71
  DEFAULT_QUEUE = "primary"
53
72
 
54
73
 
@@ -10,7 +10,7 @@ from typing import Iterator, Literal, cast
10
10
 
11
11
  from podman import PodmanClient
12
12
  from podman.domain.containers import Container
13
- from podman.errors import APIError
13
+ from podman.errors import APIError, NotFound
14
14
 
15
15
  from bec_lib.logger import bec_logger
16
16
  from bec_server.procedures.constants import (
@@ -81,6 +81,67 @@ class _PodmanUtilsBase(ContainerCommandBackend):
81
81
  tag=f"{PROCEDURE.CONTAINER.IMAGE_NAME}:v{PROCEDURE.BEC_VERSION}",
82
82
  )
83
83
 
84
+ def run_interactive(
85
+ self,
86
+ image_tag: str,
87
+ environment: OopWorkerEnv,
88
+ volumes: list[VolumeSpec],
89
+ command: str,
90
+ pod_name: str | None = None,
91
+ container_name: str | None = None,
92
+ ) -> subprocess.Popen:
93
+ """Attach process pipes so private worker bootstrap never enters Podman metadata.
94
+
95
+ Args:
96
+ image_tag (str): Worker image.
97
+ environment (OopWorkerEnv): Non-secret worker settings.
98
+ volumes (list[VolumeSpec]): Code mounts.
99
+ command (str): Worker entry point.
100
+ pod_name (str | None): Existing Podman pod.
101
+ container_name (str | None): Unique worker container name.
102
+ Returns:
103
+ subprocess.Popen: Attached process with stdin and separate output pipes.
104
+ """
105
+ prefix = self._cli_prefix()
106
+ args = [*prefix, "create", "-i"]
107
+ args.extend(_multi_args_from_dict("-e", environment))
108
+ for volume in volumes:
109
+ args.extend(
110
+ [
111
+ "-v",
112
+ f"{volume['source']}:{volume['target']}{':ro' if volume['read_only'] else ''}",
113
+ ]
114
+ )
115
+ if pod_name:
116
+ args.extend(["--pod", pod_name])
117
+ if container_name:
118
+ args.extend(["--name", container_name])
119
+ # Create synchronously: cancelling the attached start cannot leave a later
120
+ # `podman run` creating an orphan container after cleanup has returned.
121
+ container_id = _run_and_capture_error(*args, image_tag, command).stdout.decode().strip()
122
+ try:
123
+ return subprocess.Popen(
124
+ [*prefix, "start", "--attach", "--interactive", container_id],
125
+ stdin=subprocess.PIPE,
126
+ stdout=subprocess.PIPE,
127
+ stderr=subprocess.PIPE,
128
+ bufsize=0,
129
+ )
130
+ except BaseException:
131
+ self.remove(container_id)
132
+ raise
133
+
134
+ def _cli_prefix(self) -> list[str]:
135
+ return ["podman", "--url", self.uri] if isinstance(self, PodmanApiUtils) else ["podman"]
136
+
137
+ def remove(self, id: str) -> None:
138
+ """Remove a stopped or starting worker container, preventing a later start.
139
+
140
+ Args:
141
+ id (str): Container name or ID.
142
+ """
143
+ _run_and_capture_error(*self._cli_prefix(), "rm", "--force", "--ignore", id)
144
+
84
145
 
85
146
  class PodmanApiOutput(ContainerCommandOutput):
86
147
  def __init__(self, command_output: Iterator[bytes]):
@@ -157,7 +218,10 @@ class PodmanApiUtils(_PodmanUtilsBase):
157
218
 
158
219
  def state(self, id: str) -> PodmanContainerStates | None:
159
220
  with PodmanClient(base_url=self.uri) as client:
160
- status = client.containers.get(id).status
221
+ try:
222
+ status = client.containers.get(id).status
223
+ except NotFound:
224
+ return None
161
225
  if status == "unknown":
162
226
  return None
163
227
  return PodmanContainerStates(status)
@@ -220,7 +284,7 @@ class PodmanCliUtils(_PodmanUtilsBase):
220
284
  _name_arg = ["--replace", "--name", container_name] if container_name else []
221
285
  if container_name:
222
286
  # in case of incomplete cleanup previously, even with --replace it is possible to get an error
223
- _run_and_capture_error("podman", "rm", "-f", container_name)
287
+ _run_and_capture_error("podman", "rm", "-f", "--ignore", container_name)
224
288
  return (
225
289
  _run_and_capture_error(
226
290
  "podman",
@@ -251,14 +315,19 @@ class PodmanCliUtils(_PodmanUtilsBase):
251
315
 
252
316
  def logs(self, id: str) -> list[str]:
253
317
  try:
254
- return _run_and_capture_error("podman", "logs", id).stderr.decode().splitlines()
318
+ output = _run_and_capture_error("podman", "logs", id)
319
+ return (output.stdout + output.stderr).decode(errors="replace").splitlines()
255
320
  except ProcedureWorkerError as e:
256
321
  logger.error(e)
257
322
  return [f"No logs found for container {id}\n"]
258
323
 
259
324
  def state(self, id: str) -> PodmanContainerStates | None:
260
325
  for container in self._podman_ls_json():
261
- if container["Id"] == id or container["Id"].startswith(id):
326
+ if (
327
+ container["Id"] == id
328
+ or container["Id"].startswith(id)
329
+ or id in container.get("Names", [])
330
+ ):
262
331
  if names := container.get("Names"):
263
332
  logger.debug(f"Container {names[0]} status: {container['State']}")
264
333
  return PodmanContainerStates(container["State"])
@@ -0,0 +1,152 @@
1
+ import time
2
+
3
+ from bec_lib.logger import bec_logger
4
+ from bec_lib.redis_connector import RedisConnector
5
+ from bec_server.procedures.constants import PROCEDURE, PodmanContainerStates
6
+ from bec_server.procedures.container_utils import get_backend
7
+ from bec_server.procedures.oop_worker_base import (
8
+ main, # temporarily needed before update of base image on release
9
+ )
10
+ from bec_server.procedures.oop_worker_base import PROCESS_TIMEOUT, OutOfProcessWorkerBase
11
+ from bec_server.procedures.protocol import ContainerCommandBackend
12
+
13
+ logger = bec_logger.logger
14
+
15
+
16
+ class ContainerProcedureWorker(OutOfProcessWorkerBase):
17
+ """A worker which runs scripts in a container with a full BEC environment,
18
+ mounted from the filesystem, and only access to Redis"""
19
+
20
+ # The Podman client is a thin wrapper around the libpod API
21
+ # documented at https://docs.podman.io/en/latest/_static/api.html
22
+ # which is more detailed than the podman-py documentation
23
+
24
+ def _setup_execution_environment(self):
25
+ self._backend: ContainerCommandBackend = get_backend()
26
+ image_tag = f"{PROCEDURE.CONTAINER.IMAGE_NAME}:v{PROCEDURE.BEC_VERSION}"
27
+ self.container_name = (
28
+ f"bec_procedure_{PROCEDURE.BEC_VERSION}_{self._worker_id or self._queue}"
29
+ )
30
+ if not self._backend.image_exists(image_tag):
31
+ self._backend.build_worker_image()
32
+ environment = self._worker_environment() | self._additional_env
33
+ if self._worker_id is not None:
34
+ self._container_id = self.container_name
35
+ self._process = self._backend.run_interactive(
36
+ image_tag,
37
+ environment,
38
+ [
39
+ {
40
+ "source": str(PROCEDURE.CONTAINER.DEPLOYMENT_PATH),
41
+ "target": "/bec",
42
+ "type": "bind",
43
+ "read_only": True,
44
+ }
45
+ ],
46
+ PROCEDURE.CONTAINER.COMMAND,
47
+ pod_name=PROCEDURE.CONTAINER.POD_NAME,
48
+ container_name=self.container_name,
49
+ )
50
+ output_conn = RedisConnector([self._redis_server], name="Procedure container output")
51
+ try:
52
+ if self._control_credentials is not None:
53
+ output_conn.authenticate(
54
+ username=self._control_credentials["username"] or "default",
55
+ password=self._control_credentials["token"],
56
+ )
57
+ self._start_output_capture(output_conn)
58
+ except BaseException:
59
+ output_conn.shutdown()
60
+ self._kill_process()
61
+ raise
62
+ return
63
+ self._container_id = self._backend.run(
64
+ image_tag,
65
+ environment,
66
+ [
67
+ {
68
+ "source": str(PROCEDURE.CONTAINER.DEPLOYMENT_PATH),
69
+ "target": "/bec",
70
+ "type": "bind",
71
+ "read_only": True,
72
+ }
73
+ ],
74
+ PROCEDURE.CONTAINER.COMMAND,
75
+ pod_name=PROCEDURE.CONTAINER.POD_NAME,
76
+ container_name=self.container_name,
77
+ )
78
+
79
+ def _ending_or_ended(self):
80
+ if self._worker_id is not None:
81
+ return self._process.poll() is not None
82
+ return self._backend.state(self._container_id) in [
83
+ PodmanContainerStates.EXITED,
84
+ PodmanContainerStates.STOPPED,
85
+ PodmanContainerStates.STOPPING,
86
+ ]
87
+
88
+ def _kill_process(self):
89
+ if self._worker_id is not None:
90
+ # The attached CLI can fail while the container is still running.
91
+ terminal = (
92
+ None,
93
+ PodmanContainerStates.CREATED,
94
+ PodmanContainerStates.EXITED,
95
+ PodmanContainerStates.STOPPED,
96
+ )
97
+ if self._backend.state(self.container_name) not in terminal:
98
+ self._backend.interrupt(self.container_name)
99
+ deadline = time.monotonic() + PROCESS_TIMEOUT
100
+ while time.monotonic() < deadline:
101
+ if self._backend.state(self.container_name) in terminal:
102
+ break
103
+ time.sleep(0.1)
104
+ else:
105
+ self._backend.kill(self.container_name)
106
+ deadline = time.monotonic() + PROCESS_TIMEOUT
107
+ while self._backend.state(self.container_name) not in terminal:
108
+ if time.monotonic() >= deadline:
109
+ raise RuntimeError("Procedure container failed to stop")
110
+ time.sleep(0.1)
111
+ # Creation completed before the launcher was started, so removal also
112
+ # prevents an attached start that has not reached the engine yet.
113
+ self._backend.remove(self.container_name)
114
+ if self._process.stdin is not None:
115
+ self._process.stdin.close()
116
+ try:
117
+ self._process.wait(PROCESS_TIMEOUT)
118
+ except Exception:
119
+ self._process.kill()
120
+ self._process.wait(PROCESS_TIMEOUT)
121
+ return
122
+ if not self._ending_or_ended():
123
+ self._backend.interrupt(self.container_name)
124
+ start = time.monotonic()
125
+ while time.monotonic() < start + PROCESS_TIMEOUT:
126
+ if self._ending_or_ended():
127
+ return
128
+ time.sleep(0.2)
129
+ logger.warning(
130
+ f"Procedure worker {self._container_id} for queue {self._queue} failed to shut down, killing."
131
+ )
132
+ self._backend.kill(self.container_name)
133
+
134
+ def abort_execution(self, execution_id: str):
135
+ """Abort the execution with the given id. Has no effect if the given ID is not the current job"""
136
+ if execution_id == self._current_execution_id:
137
+ self._backend.kill(self._container_id)
138
+ self._helper.remove_from_active.by_exec_id(execution_id)
139
+ logger.info(
140
+ f"Aborting execution {execution_id}, restarting worker for queue: {self._queue}"
141
+ )
142
+ self._setup_execution_environment()
143
+
144
+ def logs(self):
145
+ if self._worker_id is not None:
146
+ if self._process.poll() is not None:
147
+ self._join_output()
148
+ with self._output_lock:
149
+ return "".join(self._output_logs).splitlines()
150
+ if self._container_id is None:
151
+ return [""]
152
+ return self._backend.logs(self._container_id)