fractal-server 2.5.0a1__tar.gz → 2.5.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. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/PKG-INFO +1 -1
  2. fractal_server-2.5.2/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/submit.py +13 -1
  4. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/task_collection.py +10 -1
  5. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/task_collection_custom.py +2 -1
  6. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/compress_folder.py +1 -1
  7. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/ssh/executor.py +24 -4
  8. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +2 -0
  9. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/sudo/executor.py +9 -2
  10. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/run_subprocess.py +5 -1
  11. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_common.py +2 -0
  12. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/runner_functions_low_level.py +5 -0
  13. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/user.py +15 -10
  14. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/dumps.py +11 -2
  15. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/task.py +6 -0
  16. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/main.py +12 -10
  17. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/ssh/_fabric.py +185 -34
  18. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/string_tools.py +25 -0
  19. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/pyproject.toml +2 -2
  20. fractal_server-2.5.0a1/fractal_server/__init__.py +0 -1
  21. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/LICENSE +0 -0
  22. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/README.md +0 -0
  23. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/__main__.py +0 -0
  24. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/alembic.ini +0 -0
  25. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/__init__.py +0 -0
  26. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/db/__init__.py +0 -0
  27. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/__init__.py +0 -0
  28. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/linkusergroup.py +0 -0
  29. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/linkuserproject.py +0 -0
  30. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/security.py +0 -0
  31. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v1/__init__.py +0 -0
  32. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v1/dataset.py +0 -0
  33. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v1/job.py +0 -0
  34. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v1/project.py +0 -0
  35. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v1/state.py +0 -0
  36. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v1/task.py +0 -0
  37. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v1/workflow.py +0 -0
  38. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/__init__.py +0 -0
  39. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/collection_state.py +0 -0
  40. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/dataset.py +0 -0
  41. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/job.py +0 -0
  42. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/project.py +0 -0
  43. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/task.py +0 -0
  44. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/workflow.py +0 -0
  45. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/models/v2/workflowtask.py +0 -0
  46. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/__init__.py +0 -0
  47. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/admin/__init__.py +0 -0
  48. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/admin/v1.py +0 -0
  49. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/admin/v2.py +0 -0
  50. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/__init__.py +0 -0
  51. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/__init__.py +0 -0
  52. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/_aux_functions.py +0 -0
  53. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/dataset.py +0 -0
  54. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/job.py +0 -0
  55. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/project.py +0 -0
  56. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/task.py +0 -0
  57. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/task_collection.py +0 -0
  58. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/workflow.py +0 -0
  59. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v1/workflowtask.py +0 -0
  60. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  61. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  62. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  63. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/images.py +0 -0
  64. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/job.py +0 -0
  65. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/project.py +0 -0
  66. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/status.py +0 -0
  67. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/task.py +0 -0
  68. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  69. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  70. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/__init__.py +0 -0
  71. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  72. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/current_user.py +0 -0
  73. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/group.py +0 -0
  74. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/group_names.py +0 -0
  75. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/login.py +0 -0
  76. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/oauth.py +0 -0
  77. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/register.py +0 -0
  78. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/router.py +0 -0
  79. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/auth/users.py +0 -0
  80. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/aux/__init__.py +0 -0
  81. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/aux/_job.py +0 -0
  82. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/routes/aux/_runner.py +0 -0
  83. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/.gitignore +0 -0
  84. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/__init__.py +0 -0
  85. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/async_wrap.py +0 -0
  86. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/components.py +0 -0
  87. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/exceptions.py +0 -0
  88. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/__init__.py +0 -0
  89. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
  90. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
  91. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
  92. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
  93. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
  94. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
  95. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -0
  96. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
  97. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
  98. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
  99. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/extract_archive.py +0 -0
  100. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/filenames.py +0 -0
  101. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  102. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/shutdown.py +0 -0
  103. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/task_files.py +0 -0
  104. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/__init__.py +0 -0
  105. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
  106. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
  107. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
  108. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_local/executor.py +0 -0
  109. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
  110. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
  111. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
  112. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/common.py +0 -0
  113. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
  114. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/__init__.py +0 -0
  115. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
  116. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
  117. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
  118. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local/executor.py +0 -0
  119. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
  120. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
  121. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
  122. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
  123. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
  124. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
  125. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
  126. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
  127. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +0 -0
  128. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
  129. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  130. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
  131. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  132. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/runner.py +0 -0
  133. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  134. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/v2/task_interface.py +0 -0
  135. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/runner/versions.py +0 -0
  136. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/__init__.py +0 -0
  137. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/_validators.py +0 -0
  138. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/user_group.py +0 -0
  139. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/__init__.py +0 -0
  140. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/applyworkflow.py +0 -0
  141. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/dataset.py +0 -0
  142. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/dumps.py +0 -0
  143. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/manifest.py +0 -0
  144. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/project.py +0 -0
  145. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/state.py +0 -0
  146. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/task.py +0 -0
  147. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/task_collection.py +0 -0
  148. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v1/workflow.py +0 -0
  149. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/__init__.py +0 -0
  150. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/dataset.py +0 -0
  151. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/job.py +0 -0
  152. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/manifest.py +0 -0
  153. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/project.py +0 -0
  154. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/status.py +0 -0
  155. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  156. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/workflow.py +0 -0
  157. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  158. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/app/security/__init__.py +0 -0
  159. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/config.py +0 -0
  160. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/data_migrations/2_4_0.py +0 -0
  161. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/data_migrations/README.md +0 -0
  162. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/gunicorn_fractal.py +0 -0
  163. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/images/__init__.py +0 -0
  164. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/images/models.py +0 -0
  165. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/images/tools.py +0 -0
  166. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/logger.py +0 -0
  167. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/README +0 -0
  168. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/env.py +0 -0
  169. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/naming_convention.py +0 -0
  170. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/script.py.mako +0 -0
  171. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  172. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  173. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  174. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  175. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  176. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  177. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  178. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  179. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  180. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  181. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  182. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  183. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  184. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  185. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  186. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  187. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  188. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  189. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/py.typed +0 -0
  190. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/ssh/__init__.py +0 -0
  191. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/syringe.py +0 -0
  192. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/__init__.py +0 -0
  193. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/utils.py +0 -0
  194. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v1/_TaskCollectPip.py +0 -0
  195. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v1/__init__.py +0 -0
  196. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v1/background_operations.py +0 -0
  197. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v1/endpoint_operations.py +0 -0
  198. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v1/get_collection_data.py +0 -0
  199. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v1/utils.py +0 -0
  200. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/_TaskCollectPip.py +0 -0
  201. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/__init__.py +0 -0
  202. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/_venv_pip.py +0 -0
  203. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/background_operations.py +0 -0
  204. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/background_operations_ssh.py +0 -0
  205. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/endpoint_operations.py +0 -0
  206. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/templates/_1_create_venv.sh +0 -0
  207. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/templates/_2_upgrade_pip.sh +0 -0
  208. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/templates/_3_pip_install.sh +0 -0
  209. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/templates/_4_pip_freeze.sh +0 -0
  210. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/templates/_5_pip_show.sh +0 -0
  211. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/tasks/v2/utils.py +0 -0
  212. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/urls.py +0 -0
  213. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/utils.py +0 -0
  214. {fractal_server-2.5.0a1 → fractal_server-2.5.2}/fractal_server/zip_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fractal-server
3
- Version: 2.5.0a1
3
+ Version: 2.5.2
4
4
  Summary: Server component of the Fractal analytics platform
5
5
  Home-page: https://github.com/fractal-analytics-platform/fractal-server
6
6
  License: BSD-3-Clause
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.5.2"
@@ -238,6 +238,18 @@ async def apply_workflow(
238
238
  await db.merge(job)
239
239
  await db.commit()
240
240
 
241
+ # User appropriate FractalSSH object
242
+ if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
243
+ ssh_credentials = dict(
244
+ user=settings.FRACTAL_SLURM_SSH_USER,
245
+ host=settings.FRACTAL_SLURM_SSH_HOST,
246
+ key_path=settings.FRACTAL_SLURM_SSH_PRIVATE_KEY_PATH,
247
+ )
248
+ fractal_ssh_list = request.app.state.fractal_ssh_list
249
+ fractal_ssh = fractal_ssh_list.get(**ssh_credentials)
250
+ else:
251
+ fractal_ssh = None
252
+
241
253
  background_tasks.add_task(
242
254
  submit_workflow,
243
255
  workflow_id=workflow.id,
@@ -246,7 +258,7 @@ async def apply_workflow(
246
258
  worker_init=job.worker_init,
247
259
  slurm_user=user.slurm_user,
248
260
  user_cache_dir=user.cache_dir,
249
- fractal_ssh=request.app.state.fractal_ssh,
261
+ fractal_ssh=fractal_ssh,
250
262
  )
251
263
  request.app.state.jobsV2.append(job.id)
252
264
  logger.info(
@@ -124,11 +124,20 @@ async def collect_tasks_pip(
124
124
  db.add(state)
125
125
  await db.commit()
126
126
 
127
+ # User appropriate FractalSSH object
128
+ ssh_credentials = dict(
129
+ user=settings.FRACTAL_SLURM_SSH_USER,
130
+ host=settings.FRACTAL_SLURM_SSH_HOST,
131
+ key_path=settings.FRACTAL_SLURM_SSH_PRIVATE_KEY_PATH,
132
+ )
133
+ fractal_ssh_list = request.app.state.fractal_ssh_list
134
+ fractal_ssh = fractal_ssh_list.get(**ssh_credentials)
135
+
127
136
  background_tasks.add_task(
128
137
  background_collect_pip_ssh,
129
138
  state.id,
130
139
  task_pkg,
131
- request.app.state.fractal_ssh,
140
+ fractal_ssh,
132
141
  )
133
142
 
134
143
  response.status_code = status.HTTP_201_CREATED
@@ -20,12 +20,12 @@ from ....schemas.v2 import TaskCreateV2
20
20
  from ....schemas.v2 import TaskReadV2
21
21
  from fractal_server.app.models import UserOAuth
22
22
  from fractal_server.app.routes.auth import current_active_verified_user
23
+ from fractal_server.string_tools import validate_cmd
23
24
  from fractal_server.tasks.v2.background_operations import _insert_tasks
24
25
  from fractal_server.tasks.v2.background_operations import (
25
26
  _prepare_tasks_metadata,
26
27
  )
27
28
 
28
-
29
29
  router = APIRouter()
30
30
 
31
31
  logger = set_logger(__name__)
@@ -74,6 +74,7 @@ async def collect_task_custom(
74
74
  package_name_underscore = task_collect.package_name.replace("-", "_")
75
75
  # Note that python_command is then used as part of a subprocess.run
76
76
  # statement: be careful with mixing `'` and `"`.
77
+ validate_cmd(package_name_underscore)
77
78
  python_command = (
78
79
  "import importlib.util; "
79
80
  "from pathlib import Path; "
@@ -48,7 +48,7 @@ def create_tar_archive(
48
48
  "."
49
49
  )
50
50
  logger.debug(f"cmd tar:\n{cmd_tar}")
51
- run_subprocess(cmd=cmd_tar, logger_name=logger_name)
51
+ run_subprocess(cmd=cmd_tar, logger_name=logger_name, allow_char="*")
52
52
 
53
53
 
54
54
  def remove_temp_subfolder(subfolder_path_tmp_copy: Path, logger_name: str):
@@ -163,17 +163,34 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
163
163
  settings = Inject(get_settings)
164
164
  self.python_remote = settings.FRACTAL_SLURM_WORKER_PYTHON
165
165
  if self.python_remote is None:
166
+ self._stop_and_join_wait_thread()
166
167
  raise ValueError("FRACTAL_SLURM_WORKER_PYTHON is not set. Exit.")
167
168
 
168
169
  # Initialize connection and perform handshake
169
170
  self.fractal_ssh = fractal_ssh
170
171
  logger.warning(self.fractal_ssh)
171
- self.handshake()
172
+ try:
173
+ self.handshake()
174
+ except Exception as e:
175
+ logger.warning(
176
+ "Stop/join waiting thread and then "
177
+ f"re-raise original error {str(e)}"
178
+ )
179
+ self._stop_and_join_wait_thread()
180
+ raise e
172
181
 
173
182
  # Set/validate parameters for SLURM submission scripts
174
183
  self.slurm_account = slurm_account
175
184
  self.common_script_lines = common_script_lines or []
176
- self._validate_common_script_lines()
185
+ try:
186
+ self._validate_common_script_lines()
187
+ except Exception as e:
188
+ logger.warning(
189
+ "Stop/join waiting thread and then "
190
+ f"re-raise original error {str(e)}"
191
+ )
192
+ self._stop_and_join_wait_thread()
193
+ raise e
177
194
 
178
195
  # Set/initialize some more options
179
196
  self.keep_pickle_files = keep_pickle_files
@@ -1385,6 +1402,10 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
1385
1402
  self.fractal_ssh.run_command(cmd=scancel_command)
1386
1403
  logger.debug("Executor shutdown: end")
1387
1404
 
1405
+ def _stop_and_join_wait_thread(self):
1406
+ self.wait_thread.stop()
1407
+ self.wait_thread.join()
1408
+
1388
1409
  def __exit__(self, *args, **kwargs):
1389
1410
  """
1390
1411
  See
@@ -1393,8 +1414,7 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
1393
1414
  logger.debug(
1394
1415
  "[FractalSlurmSSHExecutor.__exit__] Stop and join `wait_thread`"
1395
1416
  )
1396
- self.wait_thread.stop()
1397
- self.wait_thread.join()
1417
+ self._stop_and_join_wait_thread()
1398
1418
  logger.debug("[FractalSlurmSSHExecutor.__exit__] End")
1399
1419
 
1400
1420
  def run_squeue(self, job_ids):
@@ -20,6 +20,7 @@ import subprocess # nosec
20
20
  from typing import Optional
21
21
 
22
22
  from ......logger import set_logger
23
+ from fractal_server.string_tools import validate_cmd
23
24
 
24
25
  logger = set_logger(__name__)
25
26
 
@@ -47,6 +48,7 @@ def _run_command_as_user(
47
48
  Returns:
48
49
  res: The return value from `subprocess.run`.
49
50
  """
51
+ validate_cmd(cmd)
50
52
  logger.debug(f'[_run_command_as_user] {user=}, cmd="{cmd}"')
51
53
  if user:
52
54
  new_cmd = f"sudo --set-home --non-interactive -u {user} {cmd}"
@@ -47,6 +47,7 @@ from ._subprocess_run_as_user import _path_exists_as_user
47
47
  from ._subprocess_run_as_user import _run_command_as_user
48
48
  from fractal_server import __VERSION__
49
49
  from fractal_server.app.runner.components import _COMPONENT_KEY_
50
+ from fractal_server.string_tools import validate_cmd
50
51
 
51
52
 
52
53
  logger = set_logger(__name__)
@@ -65,6 +66,7 @@ def _subprocess_run_or_raise(full_command: str) -> Optional[CompletedProcess]:
65
66
  Returns:
66
67
  The actual `CompletedProcess` output of `subprocess.run`.
67
68
  """
69
+ validate_cmd(full_command)
68
70
  try:
69
71
  output = subprocess.run( # nosec
70
72
  shlex.split(full_command),
@@ -257,6 +259,7 @@ class FractalSlurmExecutor(SlurmExecutor):
257
259
  for line in self.common_script_lines
258
260
  if line.startswith("#SBATCH --account=")
259
261
  )
262
+ self._stop_and_join_wait_thread()
260
263
  raise RuntimeError(
261
264
  "Invalid line in `FractalSlurmExecutor.common_script_lines`: "
262
265
  f"'{invalid_line}'.\n"
@@ -1266,6 +1269,7 @@ class FractalSlurmExecutor(SlurmExecutor):
1266
1269
  pre_command = f"sudo --non-interactive -u {self.slurm_user}"
1267
1270
  submit_command = f"scancel {scancel_string}"
1268
1271
  full_command = f"{pre_command} {submit_command}"
1272
+ validate_cmd(full_command)
1269
1273
  logger.debug(f"Now execute `{full_command}`")
1270
1274
  try:
1271
1275
  subprocess.run( # nosec
@@ -1284,6 +1288,10 @@ class FractalSlurmExecutor(SlurmExecutor):
1284
1288
 
1285
1289
  logger.debug("Executor shutdown: end")
1286
1290
 
1291
+ def _stop_and_join_wait_thread(self):
1292
+ self.wait_thread.stop()
1293
+ self.wait_thread.join()
1294
+
1287
1295
  def __exit__(self, *args, **kwargs):
1288
1296
  """
1289
1297
  See
@@ -1292,6 +1300,5 @@ class FractalSlurmExecutor(SlurmExecutor):
1292
1300
  logger.debug(
1293
1301
  "[FractalSlurmExecutor.__exit__] Stop and join `wait_thread`"
1294
1302
  )
1295
- self.wait_thread.stop()
1296
- self.wait_thread.join()
1303
+ self._stop_and_join_wait_thread()
1297
1304
  logger.debug("[FractalSlurmExecutor.__exit__] End")
@@ -3,11 +3,15 @@ import subprocess # nosec
3
3
  from typing import Optional
4
4
 
5
5
  from fractal_server.logger import get_logger
6
+ from fractal_server.string_tools import validate_cmd
6
7
 
7
8
 
8
9
  def run_subprocess(
9
- cmd: str, logger_name: Optional[str] = None
10
+ cmd: str,
11
+ allow_char: Optional[str] = None,
12
+ logger_name: Optional[str] = None,
10
13
  ) -> subprocess.CompletedProcess:
14
+ validate_cmd(cmd, allow_char=allow_char)
11
15
  logger = get_logger(logger_name)
12
16
  try:
13
17
  res = subprocess.run( # nosec
@@ -31,6 +31,7 @@ from .common import write_args_file
31
31
  from fractal_server.app.runner.filenames import HISTORY_FILENAME
32
32
  from fractal_server.app.runner.filenames import METADATA_FILENAME
33
33
  from fractal_server.app.runner.task_files import get_task_file_paths
34
+ from fractal_server.string_tools import validate_cmd
34
35
 
35
36
 
36
37
  def no_op_submit_setup_call(
@@ -77,6 +78,7 @@ def _call_command_wrapper(cmd: str, stdout: Path, stderr: Path) -> None:
77
78
  TERM or KILL signal)
78
79
  """
79
80
 
81
+ validate_cmd(cmd)
80
82
  # Verify that task command is executable
81
83
  if shutil.which(shlex_split(cmd)[0]) is None:
82
84
  msg = (
@@ -12,6 +12,7 @@ from ..exceptions import JobExecutionError
12
12
  from ..exceptions import TaskExecutionError
13
13
  from fractal_server.app.models.v2 import WorkflowTaskV2
14
14
  from fractal_server.app.runner.task_files import get_task_file_paths
15
+ from fractal_server.string_tools import validate_cmd
15
16
 
16
17
 
17
18
  def _call_command_wrapper(cmd: str, log_path: Path) -> None:
@@ -25,6 +26,10 @@ def _call_command_wrapper(cmd: str, log_path: Path) -> None:
25
26
  exit code (e.g. due to the subprocess receiving a
26
27
  TERM or KILL signal)
27
28
  """
29
+ try:
30
+ validate_cmd(cmd)
31
+ except ValueError as e:
32
+ raise TaskExecutionError(f"Invalid command. Original error: {str(e)}")
28
33
 
29
34
  # Verify that task command is executable
30
35
  if shutil.which(shlex_split(cmd)[0]) is None:
@@ -10,7 +10,7 @@ from pydantic.types import StrictStr
10
10
  from ._validators import val_absolute_path
11
11
  from ._validators import val_unique_list
12
12
  from ._validators import valstr
13
-
13
+ from fractal_server.string_tools import validate_cmd
14
14
 
15
15
  __all__ = (
16
16
  "UserRead",
@@ -77,14 +77,16 @@ class UserUpdate(schemas.BaseUserUpdate):
77
77
  valstr("slurm_user")
78
78
  )
79
79
  _username = validator("username", allow_reuse=True)(valstr("username"))
80
- _cache_dir = validator("cache_dir", allow_reuse=True)(
81
- val_absolute_path("cache_dir")
82
- )
83
80
 
84
81
  _slurm_accounts = validator("slurm_accounts", allow_reuse=True)(
85
82
  val_unique_list("slurm_accounts")
86
83
  )
87
84
 
85
+ @validator("cache_dir")
86
+ def cache_dir_validator(cls, value):
87
+ validate_cmd(value)
88
+ return val_absolute_path("cache_dir")(value)
89
+
88
90
  @validator(
89
91
  "is_active",
90
92
  "is_verified",
@@ -115,9 +117,10 @@ class UserUpdateStrict(BaseModel, extra=Extra.forbid):
115
117
  val_unique_list("slurm_accounts")
116
118
  )
117
119
 
118
- _cache_dir = validator("cache_dir", allow_reuse=True)(
119
- val_absolute_path("cache_dir")
120
- )
120
+ @validator("cache_dir")
121
+ def cache_dir_validator(cls, value):
122
+ validate_cmd(value)
123
+ return val_absolute_path("cache_dir")(value)
121
124
 
122
125
 
123
126
  class UserUpdateWithNewGroupIds(UserUpdate):
@@ -157,6 +160,8 @@ class UserCreate(schemas.BaseUserCreate):
157
160
  valstr("slurm_user")
158
161
  )
159
162
  _username = validator("username", allow_reuse=True)(valstr("username"))
160
- _cache_dir = validator("cache_dir", allow_reuse=True)(
161
- val_absolute_path("cache_dir")
162
- )
163
+
164
+ @validator("cache_dir")
165
+ def cache_dir_validator(cls, value):
166
+ validate_cmd(value)
167
+ return val_absolute_path("cache_dir")(value)
@@ -39,14 +39,23 @@ class TaskDumpV2(BaseModel):
39
39
 
40
40
 
41
41
  class WorkflowTaskDumpV2(BaseModel):
42
+ """
43
+ Before v2.5.0, WorkflowTaskV2 could have `task_id=task=None` and
44
+ non-`None` `task_legacy_id` and `task_legacy`. Since these objects
45
+ may still exist in the database after version updates, we are setting
46
+ `task_id` and `task` to `Optional` to avoid response-validation errors
47
+ for the endpoints that GET datasets.
48
+ Ref issue #1783.
49
+ """
50
+
42
51
  id: int
43
52
  workflow_id: int
44
53
  order: Optional[int]
45
54
 
46
55
  input_filters: Filters
47
56
 
48
- task_id: int
49
- task: TaskDumpV2
57
+ task_id: Optional[int]
58
+ task: Optional[TaskDumpV2]
50
59
 
51
60
 
52
61
  class WorkflowDumpV2(BaseModel, extra=Extra.forbid):
@@ -11,6 +11,7 @@ from pydantic import validator
11
11
 
12
12
  from .._validators import valdictkeys
13
13
  from .._validators import valstr
14
+ from fractal_server.string_tools import validate_cmd
14
15
 
15
16
 
16
17
  class TaskCreateV2(BaseModel, extra=Extra.forbid):
@@ -43,6 +44,11 @@ class TaskCreateV2(BaseModel, extra=Extra.forbid):
43
44
  "Task must have at least one valid command "
44
45
  "(parallel and/or non_parallel)"
45
46
  )
47
+ if command_parallel is not None:
48
+ validate_cmd(command_parallel)
49
+ if command_non_parallel is not None:
50
+ validate_cmd(command_non_parallel)
51
+
46
52
  return values
47
53
 
48
54
  _name = validator("name", allow_reuse=True)(valstr("name"))
@@ -92,32 +92,34 @@ async def lifespan(app: FastAPI):
92
92
  settings = Inject(get_settings)
93
93
 
94
94
  if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
95
- from fractal_server.ssh._fabric import get_ssh_connection
96
- from fractal_server.ssh._fabric import FractalSSH
97
95
 
98
- connection = get_ssh_connection()
99
- app.state.fractal_ssh = FractalSSH(connection=connection)
96
+ from fractal_server.ssh._fabric import FractalSSHList
97
+
98
+ app.state.fractal_ssh_list = FractalSSHList()
99
+
100
100
  logger.info(
101
- f"Created SSH connection "
102
- f"({app.state.fractal_ssh.is_connected=})."
101
+ "Added empty FractalSSHList to app.state "
102
+ f"(id={id(app.state.fractal_ssh_list)})."
103
103
  )
104
104
  else:
105
- app.state.fractal_ssh = None
105
+ app.state.fractal_ssh_list = None
106
106
 
107
107
  config_uvicorn_loggers()
108
108
  logger.info("End application startup")
109
109
  reset_logger_handlers(logger)
110
+
110
111
  yield
112
+
111
113
  logger = get_logger("fractal_server.lifespan")
112
114
  logger.info("Start application shutdown")
113
115
 
114
116
  if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
115
117
  logger.info(
116
- f"Closing SSH connection "
117
- f"(current: {app.state.fractal_ssh.is_connected=})."
118
+ "Close FractalSSH connections "
119
+ f"(current size: {app.state.fractal_ssh_list.size})."
118
120
  )
119
121
 
120
- app.state.fractal_ssh.close()
122
+ app.state.fractal_ssh_list.close_all()
121
123
 
122
124
  logger.info(
123
125
  f"Current worker with pid {os.getpid()} is shutting down. "