fractal-server 2.9.0a2__tar.gz → 2.9.0a3__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 (248) hide show
  1. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/PKG-INFO +1 -1
  2. fractal_server-2.9.0a3/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/task_collection.py +3 -10
  4. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +50 -6
  5. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/_validators.py +0 -14
  6. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/applyworkflow.py +0 -8
  7. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/dataset.py +0 -5
  8. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/project.py +0 -5
  9. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/state.py +0 -5
  10. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/workflow.py +0 -5
  11. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/dataset.py +0 -6
  12. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/job.py +0 -8
  13. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/project.py +0 -5
  14. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/workflow.py +0 -5
  15. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/ssh/_fabric.py +4 -2
  16. fractal_server-2.9.0a2/fractal_server/tasks/v2/local/utils_local.py → fractal_server-2.9.0a3/fractal_server/tasks/v2/local/_utils.py +25 -0
  17. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/local/collect.py +2 -2
  18. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/local/deactivate.py +1 -1
  19. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/local/reactivate.py +1 -1
  20. fractal_server-2.9.0a3/fractal_server/tasks/v2/ssh/__init__.py +3 -0
  21. fractal_server-2.9.0a3/fractal_server/tasks/v2/ssh/_utils.py +87 -0
  22. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/ssh/collect.py +3 -78
  23. fractal_server-2.9.0a3/fractal_server/tasks/v2/ssh/deactivate.py +243 -0
  24. fractal_server-2.9.0a3/fractal_server/tasks/v2/ssh/reactivate.py +199 -0
  25. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/utils_background.py +0 -24
  26. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/zip_tools.py +21 -4
  27. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/pyproject.toml +2 -2
  28. fractal_server-2.9.0a2/fractal_server/__init__.py +0 -1
  29. fractal_server-2.9.0a2/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  30. fractal_server-2.9.0a2/fractal_server/tasks/v2/ssh/deactivate.py +0 -2
  31. fractal_server-2.9.0a2/fractal_server/tasks/v2/ssh/reactivate.py +0 -2
  32. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/LICENSE +0 -0
  33. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/README.md +0 -0
  34. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/__main__.py +0 -0
  35. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/alembic.ini +0 -0
  36. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/__init__.py +0 -0
  37. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/db/__init__.py +0 -0
  38. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/__init__.py +0 -0
  39. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/linkusergroup.py +0 -0
  40. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/linkuserproject.py +0 -0
  41. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/security.py +0 -0
  42. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/user_settings.py +0 -0
  43. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v1/__init__.py +0 -0
  44. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v1/dataset.py +0 -0
  45. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v1/job.py +0 -0
  46. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v1/project.py +0 -0
  47. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v1/state.py +0 -0
  48. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v1/task.py +0 -0
  49. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v1/workflow.py +0 -0
  50. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/__init__.py +0 -0
  51. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/dataset.py +0 -0
  52. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/job.py +0 -0
  53. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/project.py +0 -0
  54. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/task.py +0 -0
  55. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/task_group.py +0 -0
  56. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/workflow.py +0 -0
  57. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/models/v2/workflowtask.py +0 -0
  58. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/__init__.py +0 -0
  59. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/admin/__init__.py +0 -0
  60. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/admin/v1.py +0 -0
  61. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  62. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/admin/v2/job.py +0 -0
  63. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/admin/v2/project.py +0 -0
  64. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/admin/v2/task.py +0 -0
  65. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  66. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/__init__.py +0 -0
  67. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/__init__.py +0 -0
  68. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/_aux_functions.py +0 -0
  69. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/dataset.py +0 -0
  70. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/job.py +0 -0
  71. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/project.py +0 -0
  72. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/task.py +0 -0
  73. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/task_collection.py +0 -0
  74. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/workflow.py +0 -0
  75. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v1/workflowtask.py +0 -0
  76. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  77. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  78. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  79. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  80. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  81. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/images.py +0 -0
  82. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/job.py +0 -0
  83. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/project.py +0 -0
  84. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/status.py +0 -0
  85. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/submit.py +0 -0
  86. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/task.py +0 -0
  87. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  88. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  89. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  90. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  91. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  92. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/__init__.py +0 -0
  93. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  94. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/current_user.py +0 -0
  95. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/group.py +0 -0
  96. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/login.py +0 -0
  97. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/oauth.py +0 -0
  98. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/register.py +0 -0
  99. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/router.py +0 -0
  100. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/auth/users.py +0 -0
  101. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/aux/__init__.py +0 -0
  102. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/aux/_job.py +0 -0
  103. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/aux/_runner.py +0 -0
  104. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/aux/_timestamp.py +0 -0
  105. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  106. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/.gitignore +0 -0
  107. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/__init__.py +0 -0
  108. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/async_wrap.py +0 -0
  109. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/components.py +0 -0
  110. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/compress_folder.py +0 -0
  111. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/exceptions.py +0 -0
  112. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/__init__.py +0 -0
  113. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
  114. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
  115. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
  116. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
  117. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
  118. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
  119. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -0
  120. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/ssh/executor.py +0 -0
  121. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
  122. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
  123. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
  124. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
  125. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/executors/slurm/sudo/executor.py +0 -0
  126. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/extract_archive.py +0 -0
  127. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/filenames.py +0 -0
  128. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/run_subprocess.py +0 -0
  129. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  130. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/shutdown.py +0 -0
  131. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/task_files.py +0 -0
  132. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/__init__.py +0 -0
  133. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_common.py +0 -0
  134. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
  135. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
  136. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
  137. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_local/executor.py +0 -0
  138. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
  139. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
  140. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
  141. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/common.py +0 -0
  142. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
  143. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/__init__.py +0 -0
  144. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
  145. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
  146. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
  147. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local/executor.py +0 -0
  148. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
  149. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
  150. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
  151. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
  152. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
  153. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
  154. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
  155. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
  156. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +0 -0
  157. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
  158. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  159. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
  160. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  161. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/runner.py +0 -0
  162. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  163. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  164. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/v2/task_interface.py +0 -0
  165. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/runner/versions.py +0 -0
  166. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/__init__.py +0 -0
  167. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/user.py +0 -0
  168. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/user_group.py +0 -0
  169. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/user_settings.py +0 -0
  170. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/__init__.py +0 -0
  171. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/dumps.py +0 -0
  172. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/manifest.py +0 -0
  173. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/task.py +0 -0
  174. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v1/task_collection.py +0 -0
  175. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/__init__.py +0 -0
  176. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/dumps.py +0 -0
  177. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/manifest.py +0 -0
  178. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/status.py +0 -0
  179. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/task.py +0 -0
  180. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  181. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/task_group.py +0 -0
  182. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  183. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/security/__init__.py +0 -0
  184. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/app/user_settings.py +0 -0
  185. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/config.py +0 -0
  186. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/data_migrations/README.md +0 -0
  187. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/data_migrations/tools.py +0 -0
  188. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/gunicorn_fractal.py +0 -0
  189. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/images/__init__.py +0 -0
  190. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/images/models.py +0 -0
  191. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/images/tools.py +0 -0
  192. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/logger.py +0 -0
  193. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/main.py +0 -0
  194. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/README +0 -0
  195. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/env.py +0 -0
  196. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/naming_convention.py +0 -0
  197. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/script.py.mako +0 -0
  198. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  199. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  200. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  201. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/3082479ac4ea_taskgroup_activity_and_venv_info_to_.py +0 -0
  202. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  203. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  204. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  205. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  206. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  207. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  208. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  209. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  210. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  211. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  212. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  213. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  214. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  215. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  216. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  217. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  218. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  219. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  220. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  221. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  222. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  223. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/py.typed +0 -0
  224. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/ssh/__init__.py +0 -0
  225. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/string_tools.py +0 -0
  226. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/syringe.py +0 -0
  227. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/__init__.py +0 -0
  228. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/utils.py +0 -0
  229. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v1/_TaskCollectPip.py +0 -0
  230. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v1/__init__.py +0 -0
  231. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v1/background_operations.py +0 -0
  232. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v1/endpoint_operations.py +0 -0
  233. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v1/get_collection_data.py +0 -0
  234. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v1/utils.py +0 -0
  235. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/__init__.py +0 -0
  236. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/local/__init__.py +0 -0
  237. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  238. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  239. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  240. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  241. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  242. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  243. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/utils_database.py +0 -0
  244. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  245. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  246. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/tasks/v2/utils_templates.py +0 -0
  247. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/urls.py +0 -0
  248. {fractal_server-2.9.0a2 → fractal_server-2.9.0a3}/fractal_server/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fractal-server
3
- Version: 2.9.0a2
3
+ Version: 2.9.0a3
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.9.0a3"
@@ -37,6 +37,7 @@ from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
37
37
  from fractal_server.tasks.v2.local.collect import (
38
38
  collect_local,
39
39
  )
40
+ from fractal_server.tasks.v2.ssh import collect_ssh
40
41
  from fractal_server.tasks.v2.utils_package_names import _parse_wheel_filename
41
42
  from fractal_server.tasks.v2.utils_package_names import normalize_package_name
42
43
  from fractal_server.tasks.v2.utils_python_interpreter import (
@@ -63,10 +64,7 @@ async def collect_tasks_pip(
63
64
  db: AsyncSession = Depends(get_async_db),
64
65
  ) -> TaskGroupActivityV2Read:
65
66
  """
66
- Task collection endpoint
67
-
68
- Trigger the creation of a dedicated virtual environment, the installation
69
- of a package and the collection of tasks as advertised in the manifest.
67
+ Task-collection endpoint
70
68
  """
71
69
 
72
70
  # Get settings
@@ -246,12 +244,7 @@ async def collect_tasks_pip(
246
244
 
247
245
  if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
248
246
  # SSH task collection
249
-
250
- from fractal_server.tasks.v2.ssh.collect import (
251
- collect_ssh,
252
- )
253
-
254
- # User appropriate FractalSSH object
247
+ # Use appropriate FractalSSH object
255
248
  ssh_credentials = dict(
256
249
  user=user_settings.ssh_username,
257
250
  host=user_settings.ssh_host,
@@ -2,9 +2,11 @@ from fastapi import APIRouter
2
2
  from fastapi import BackgroundTasks
3
3
  from fastapi import Depends
4
4
  from fastapi import HTTPException
5
+ from fastapi import Request
5
6
  from fastapi import Response
6
7
  from fastapi import status
7
8
 
9
+ from ...aux.validate_user_settings import validate_user_settings
8
10
  from ._aux_functions_task_lifecycle import check_no_ongoing_activity
9
11
  from ._aux_functions_tasks import _get_task_group_full_access
10
12
  from fractal_server.app.db import AsyncSession
@@ -22,6 +24,8 @@ from fractal_server.logger import set_logger
22
24
  from fractal_server.syringe import Inject
23
25
  from fractal_server.tasks.v2.local import deactivate_local
24
26
  from fractal_server.tasks.v2.local import reactivate_local
27
+ from fractal_server.tasks.v2.ssh import deactivate_ssh
28
+ from fractal_server.tasks.v2.ssh import reactivate_ssh
25
29
  from fractal_server.utils import get_timestamp
26
30
 
27
31
  router = APIRouter()
@@ -38,6 +42,7 @@ async def deactivate_task_group(
38
42
  task_group_id: int,
39
43
  background_tasks: BackgroundTasks,
40
44
  response: Response,
45
+ request: Request,
41
46
  user: UserOAuth = Depends(current_active_user),
42
47
  db: AsyncSession = Depends(get_async_db),
43
48
  ) -> TaskGroupReadV2:
@@ -103,10 +108,29 @@ async def deactivate_task_group(
103
108
  # Submit background task
104
109
  settings = Inject(get_settings)
105
110
  if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
106
- raise HTTPException(
107
- status_code=status.HTTP_501_NOT_IMPLEMENTED,
108
- detail="Not implemented (yet) for SSH.",
111
+
112
+ # Validate user settings (backend-specific)
113
+ user_settings = await validate_user_settings(
114
+ user=user, backend=settings.FRACTAL_RUNNER_BACKEND, db=db
115
+ )
116
+
117
+ # User appropriate FractalSSH object
118
+ ssh_credentials = dict(
119
+ user=user_settings.ssh_username,
120
+ host=user_settings.ssh_host,
121
+ key_path=user_settings.ssh_private_key_path,
122
+ )
123
+ fractal_ssh_list = request.app.state.fractal_ssh_list
124
+ fractal_ssh = fractal_ssh_list.get(**ssh_credentials)
125
+
126
+ background_tasks.add_task(
127
+ deactivate_ssh,
128
+ task_group_id=task_group.id,
129
+ task_group_activity_id=task_group_activity.id,
130
+ fractal_ssh=fractal_ssh,
131
+ tasks_base_dir=user_settings.ssh_tasks_dir,
109
132
  )
133
+
110
134
  else:
111
135
  background_tasks.add_task(
112
136
  deactivate_local,
@@ -130,6 +154,7 @@ async def reactivate_task_group(
130
154
  task_group_id: int,
131
155
  background_tasks: BackgroundTasks,
132
156
  response: Response,
157
+ request: Request,
133
158
  user: UserOAuth = Depends(current_active_user),
134
159
  db: AsyncSession = Depends(get_async_db),
135
160
  ) -> TaskGroupReadV2:
@@ -203,10 +228,29 @@ async def reactivate_task_group(
203
228
  # Submit background task
204
229
  settings = Inject(get_settings)
205
230
  if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
206
- raise HTTPException(
207
- status_code=status.HTTP_501_NOT_IMPLEMENTED,
208
- detail="Not implemented (yet) for SSH.",
231
+
232
+ # Validate user settings (backend-specific)
233
+ user_settings = await validate_user_settings(
234
+ user=user, backend=settings.FRACTAL_RUNNER_BACKEND, db=db
235
+ )
236
+
237
+ # Use appropriate FractalSSH object
238
+ ssh_credentials = dict(
239
+ user=user_settings.ssh_username,
240
+ host=user_settings.ssh_host,
241
+ key_path=user_settings.ssh_private_key_path,
242
+ )
243
+ fractal_ssh_list = request.app.state.fractal_ssh_list
244
+ fractal_ssh = fractal_ssh_list.get(**ssh_credentials)
245
+
246
+ background_tasks.add_task(
247
+ reactivate_ssh,
248
+ task_group_id=task_group.id,
249
+ task_group_activity_id=task_group_activity.id,
250
+ fractal_ssh=fractal_ssh,
251
+ tasks_base_dir=user_settings.ssh_tasks_dir,
209
252
  )
253
+
210
254
  else:
211
255
  background_tasks.add_task(
212
256
  reactivate_local,
@@ -1,6 +1,4 @@
1
1
  import os
2
- from datetime import datetime
3
- from datetime import timezone
4
2
  from typing import Any
5
3
  from typing import Optional
6
4
 
@@ -103,15 +101,3 @@ def val_unique_list(attribute: str):
103
101
  return must_be_unique
104
102
 
105
103
  return val
106
-
107
-
108
- def valutc(attribute: str):
109
- def val(timestamp: Optional[datetime]) -> Optional[datetime]:
110
- """
111
- Replace `tzinfo` with `timezone.utc`.
112
- """
113
- if timestamp is not None:
114
- return timestamp.replace(tzinfo=timezone.utc)
115
- return None
116
-
117
- return val
@@ -7,7 +7,6 @@ from pydantic import validator
7
7
  from pydantic.types import StrictStr
8
8
 
9
9
  from .._validators import valstr
10
- from .._validators import valutc
11
10
  from .dumps import DatasetDumpV1
12
11
  from .dumps import ProjectDumpV1
13
12
  from .dumps import WorkflowDumpV1
@@ -150,13 +149,6 @@ class ApplyWorkflowReadV1(_ApplyWorkflowBaseV1):
150
149
  first_task_index: Optional[int]
151
150
  last_task_index: Optional[int]
152
151
 
153
- _start_timestamp = validator("start_timestamp", allow_reuse=True)(
154
- valutc("start_timestamp")
155
- )
156
- _end_timestamp = validator("end_timestamp", allow_reuse=True)(
157
- valutc("end_timestamp")
158
- )
159
-
160
152
 
161
153
  class ApplyWorkflowUpdateV1(BaseModel):
162
154
  """
@@ -8,7 +8,6 @@ from pydantic import validator
8
8
 
9
9
  from .._validators import val_absolute_path
10
10
  from .._validators import valstr
11
- from .._validators import valutc
12
11
  from .dumps import WorkflowTaskDumpV1
13
12
  from .project import ProjectReadV1
14
13
  from .workflow import WorkflowTaskStatusTypeV1
@@ -151,10 +150,6 @@ class DatasetReadV1(_DatasetBaseV1):
151
150
  project: ProjectReadV1
152
151
  timestamp_created: datetime
153
152
 
154
- _timestamp_created = validator("timestamp_created", allow_reuse=True)(
155
- valutc("timestamp_created")
156
- )
157
-
158
153
 
159
154
  class DatasetStatusReadV1(BaseModel):
160
155
  """
@@ -5,7 +5,6 @@ from pydantic import BaseModel
5
5
  from pydantic import validator
6
6
 
7
7
  from .._validators import valstr
8
- from .._validators import valutc
9
8
 
10
9
 
11
10
  __all__ = (
@@ -50,10 +49,6 @@ class ProjectReadV1(_ProjectBaseV1):
50
49
  id: int
51
50
  timestamp_created: datetime
52
51
 
53
- _timestamp_created = validator("timestamp_created", allow_reuse=True)(
54
- valutc("timestamp_created")
55
- )
56
-
57
52
 
58
53
  class ProjectUpdateV1(_ProjectBaseV1):
59
54
  """
@@ -3,9 +3,6 @@ from typing import Any
3
3
  from typing import Optional
4
4
 
5
5
  from pydantic import BaseModel
6
- from pydantic import validator
7
-
8
- from fractal_server.app.schemas._validators import valutc
9
6
 
10
7
 
11
8
  class StateRead(BaseModel):
@@ -19,5 +16,3 @@ class StateRead(BaseModel):
19
16
  id: Optional[int]
20
17
  data: dict[str, Any]
21
18
  timestamp: datetime
22
-
23
- _timestamp = validator("timestamp", allow_reuse=True)(valutc("timestamp"))
@@ -8,7 +8,6 @@ from pydantic import validator
8
8
 
9
9
  from .._validators import valint
10
10
  from .._validators import valstr
11
- from .._validators import valutc
12
11
  from .project import ProjectReadV1
13
12
  from .task import TaskExportV1
14
13
  from .task import TaskImportV1
@@ -135,10 +134,6 @@ class WorkflowReadV1(_WorkflowBaseV1):
135
134
  project: ProjectReadV1
136
135
  timestamp_created: datetime
137
136
 
138
- _timestamp_created = validator("timestamp_created", allow_reuse=True)(
139
- valutc("timestamp_created")
140
- )
141
-
142
137
 
143
138
  class WorkflowCreateV1(_WorkflowBaseV1):
144
139
  """
@@ -7,7 +7,6 @@ from pydantic import Field
7
7
  from pydantic import validator
8
8
 
9
9
  from .._validators import valstr
10
- from .._validators import valutc
11
10
  from .dumps import WorkflowTaskDumpV2
12
11
  from .project import ProjectReadV2
13
12
  from .workflowtask import WorkflowTaskStatusTypeV2
@@ -62,11 +61,6 @@ class DatasetReadV2(BaseModel):
62
61
  zarr_dir: str
63
62
  filters: Filters = Field(default_factory=Filters)
64
63
 
65
- # Validators
66
- _timestamp_created = validator("timestamp_created", allow_reuse=True)(
67
- valutc("timestamp_created")
68
- )
69
-
70
64
 
71
65
  class DatasetUpdateV2(BaseModel, extra=Extra.forbid):
72
66
 
@@ -8,7 +8,6 @@ from pydantic import validator
8
8
  from pydantic.types import StrictStr
9
9
 
10
10
  from .._validators import valstr
11
- from .._validators import valutc
12
11
  from .dumps import DatasetDumpV2
13
12
  from .dumps import ProjectDumpV2
14
13
  from .dumps import WorkflowDumpV2
@@ -101,13 +100,6 @@ class JobReadV2(BaseModel):
101
100
  last_task_index: Optional[int]
102
101
  worker_init: Optional[str]
103
102
 
104
- _start_timestamp = validator("start_timestamp", allow_reuse=True)(
105
- valutc("start_timestamp")
106
- )
107
- _end_timestamp = validator("end_timestamp", allow_reuse=True)(
108
- valutc("end_timestamp")
109
- )
110
-
111
103
 
112
104
  class JobUpdateV2(BaseModel, extra=Extra.forbid):
113
105
 
@@ -6,7 +6,6 @@ from pydantic import Extra
6
6
  from pydantic import validator
7
7
 
8
8
  from .._validators import valstr
9
- from .._validators import valutc
10
9
 
11
10
 
12
11
  class ProjectCreateV2(BaseModel, extra=Extra.forbid):
@@ -21,10 +20,6 @@ class ProjectReadV2(BaseModel):
21
20
  id: int
22
21
  name: str
23
22
  timestamp_created: datetime
24
- # Validators
25
- _timestamp_created = validator("timestamp_created", allow_reuse=True)(
26
- valutc("timestamp_created")
27
- )
28
23
 
29
24
 
30
25
  class ProjectUpdateV2(BaseModel, extra=Extra.forbid):
@@ -6,7 +6,6 @@ from pydantic import Extra
6
6
  from pydantic import validator
7
7
 
8
8
  from .._validators import valstr
9
- from .._validators import valutc
10
9
  from .project import ProjectReadV2
11
10
  from .workflowtask import WorkflowTaskExportV2
12
11
  from .workflowtask import WorkflowTaskImportV2
@@ -31,10 +30,6 @@ class WorkflowReadV2(BaseModel):
31
30
  project: ProjectReadV2
32
31
  timestamp_created: datetime
33
32
 
34
- _timestamp_created = validator("timestamp_created", allow_reuse=True)(
35
- valutc("timestamp_created")
36
- )
37
-
38
33
 
39
34
  class WorkflowReadV2WithWarnings(WorkflowReadV2):
40
35
  task_list: list[WorkflowTaskReadV2WithWarning]
@@ -321,8 +321,10 @@ class FractalSSH(object):
321
321
  f"{prefix} END running '{cmd}' over SSH, "
322
322
  f"elapsed {t_1-t_0:.3f}"
323
323
  )
324
- self.logger.debug(f"STDOUT: {res.stdout}")
325
- self.logger.debug(f"STDERR: {res.stderr}")
324
+ self.logger.debug("STDOUT:")
325
+ self.logger.debug(res.stdout)
326
+ self.logger.debug("STDERR:")
327
+ self.logger.debug(res.stderr)
326
328
  return res.stdout
327
329
  except NoValidConnectionsError as e:
328
330
  # Case 2: Command fails with a connection error
@@ -1,5 +1,6 @@
1
1
  from pathlib import Path
2
2
 
3
+ from fractal_server.app.schemas.v2 import TaskCreateV2
3
4
  from fractal_server.logger import get_logger
4
5
  from fractal_server.tasks.v2.utils_templates import customize_template
5
6
  from fractal_server.utils import execute_command_sync
@@ -43,3 +44,27 @@ def _customize_and_run_template(
43
44
  stdout = execute_command_sync(command=cmd, logger_name=logger_name)
44
45
  logger.debug(f"_customize_and_run_template {template_filename} - END")
45
46
  return stdout
47
+
48
+
49
+ def check_task_files_exist(task_list: list[TaskCreateV2]) -> None:
50
+ """
51
+ Check that the modules listed in task commands point to existing files.
52
+
53
+ Args:
54
+ task_list:
55
+ """
56
+ for _task in task_list:
57
+ if _task.command_non_parallel is not None:
58
+ _task_path = _task.command_non_parallel.split()[1]
59
+ if not Path(_task_path).exists():
60
+ raise FileNotFoundError(
61
+ f"Task `{_task.name}` has `command_non_parallel` "
62
+ f"pointing to missing file `{_task_path}`."
63
+ )
64
+ if _task.command_parallel is not None:
65
+ _task_path = _task.command_parallel.split()[1]
66
+ if not Path(_task_path).exists():
67
+ raise FileNotFoundError(
68
+ f"Task `{_task.name}` has `command_parallel` "
69
+ f"pointing to missing file `{_task_path}`."
70
+ )
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  from tempfile import TemporaryDirectory
7
7
 
8
8
  from ..utils_database import create_db_tasks_and_update_task_group
9
- from .utils_local import _customize_and_run_template
9
+ from ._utils import _customize_and_run_template
10
10
  from fractal_server.app.db import get_sync_db
11
11
  from fractal_server.app.models.v2 import TaskGroupActivityV2
12
12
  from fractal_server.app.models.v2 import TaskGroupV2
@@ -16,9 +16,9 @@ from fractal_server.app.schemas.v2.manifest import ManifestV2
16
16
  from fractal_server.logger import get_logger
17
17
  from fractal_server.logger import set_logger
18
18
  from fractal_server.tasks.utils import get_log_path
19
+ from fractal_server.tasks.v2.local._utils import check_task_files_exist
19
20
  from fractal_server.tasks.v2.utils_background import _prepare_tasks_metadata
20
21
  from fractal_server.tasks.v2.utils_background import add_commit_refresh
21
- from fractal_server.tasks.v2.utils_background import check_task_files_exist
22
22
  from fractal_server.tasks.v2.utils_background import fail_and_cleanup
23
23
  from fractal_server.tasks.v2.utils_background import get_current_log
24
24
  from fractal_server.tasks.v2.utils_package_names import compare_package_names
@@ -7,7 +7,7 @@ from tempfile import TemporaryDirectory
7
7
  from ..utils_background import add_commit_refresh
8
8
  from ..utils_background import fail_and_cleanup
9
9
  from ..utils_templates import get_collection_replacements
10
- from .utils_local import _customize_and_run_template
10
+ from ._utils import _customize_and_run_template
11
11
  from fractal_server.app.db import get_sync_db
12
12
  from fractal_server.app.models.v2 import TaskGroupActivityV2
13
13
  from fractal_server.app.models.v2 import TaskGroupV2
@@ -7,7 +7,7 @@ from tempfile import TemporaryDirectory
7
7
  from ..utils_background import add_commit_refresh
8
8
  from ..utils_background import fail_and_cleanup
9
9
  from ..utils_templates import get_collection_replacements
10
- from .utils_local import _customize_and_run_template
10
+ from ._utils import _customize_and_run_template
11
11
  from fractal_server.app.db import get_sync_db
12
12
  from fractal_server.app.models.v2 import TaskGroupActivityV2
13
13
  from fractal_server.app.models.v2 import TaskGroupV2
@@ -0,0 +1,3 @@
1
+ from .collect import collect_ssh # noqa
2
+ from .deactivate import deactivate_ssh # noqa
3
+ from .reactivate import reactivate_ssh # noqa
@@ -0,0 +1,87 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ from fractal_server.app.models.v2 import TaskGroupV2
5
+ from fractal_server.logger import get_logger
6
+ from fractal_server.ssh._fabric import FractalSSH
7
+ from fractal_server.tasks.v2.utils_templates import customize_template
8
+
9
+
10
+ def _customize_and_run_template(
11
+ *,
12
+ template_filename: str,
13
+ replacements: list[tuple[str, str]],
14
+ script_dir_local: str,
15
+ prefix: str,
16
+ fractal_ssh: FractalSSH,
17
+ script_dir_remote: str,
18
+ logger_name: str,
19
+ ) -> str:
20
+ """
21
+ Customize one of the template bash scripts, transfer it to the remote host
22
+ via SFTP and then run it via SSH.
23
+
24
+ Args:
25
+ template_filename: Filename of the template file (ends with ".sh").
26
+ replacements: Dictionary of replacements.
27
+ script_dir: Local folder where the script will be placed.
28
+ prefix: Prefix for the script filename.
29
+ fractal_ssh: FractalSSH object
30
+ script_dir_remote: Remote scripts directory
31
+ """
32
+ logger = get_logger(logger_name=logger_name)
33
+ logger.debug(f"_customize_and_run_template {template_filename} - START")
34
+ # Prepare name and path of script
35
+ if not template_filename.endswith(".sh"):
36
+ raise ValueError(
37
+ f"Invalid {template_filename=} (it must end with '.sh')."
38
+ )
39
+ script_filename = f"{prefix}_{template_filename}"
40
+ script_path_local = (Path(script_dir_local) / script_filename).as_posix()
41
+
42
+ customize_template(
43
+ template_name=template_filename,
44
+ replacements=replacements,
45
+ script_path=script_path_local,
46
+ )
47
+
48
+ # Transfer script to remote host
49
+ script_path_remote = os.path.join(
50
+ script_dir_remote,
51
+ script_filename,
52
+ )
53
+ logger.debug(f"Now transfer {script_path_local=} over SSH.")
54
+ fractal_ssh.send_file(
55
+ local=script_path_local,
56
+ remote=script_path_remote,
57
+ )
58
+
59
+ # Execute script remotely
60
+ cmd = f"bash {script_path_remote}"
61
+ logger.debug(f"Now run '{cmd}' over SSH.")
62
+ stdout = fractal_ssh.run_command(cmd=cmd)
63
+
64
+ logger.debug(f"_customize_and_run_template {template_filename} - END")
65
+ return stdout
66
+
67
+
68
+ def _copy_wheel_file_ssh(
69
+ *, task_group: TaskGroupV2, fractal_ssh: FractalSSH, logger_name: str
70
+ ) -> str:
71
+ """
72
+ Handle the situation where `task_group.wheel_path` is not part of
73
+ `task_group.path`, by copying `wheel_path` into `path`.
74
+
75
+ Returns:
76
+ The new `wheel_path`.
77
+ """
78
+ logger = get_logger(logger_name=logger_name)
79
+ source = task_group.wheel_path
80
+ dest = (
81
+ Path(task_group.path) / Path(task_group.wheel_path).name
82
+ ).as_posix()
83
+ cmd = f"cp {source} {dest}"
84
+ logger.debug(f"[_copy_wheel_file] START {source=} {dest=}")
85
+ fractal_ssh.run_command(cmd=cmd)
86
+ logger.debug(f"[_copy_wheel_file] END {source=} {dest=}")
87
+ return dest
@@ -1,5 +1,4 @@
1
1
  import logging
2
- import os
3
2
  import time
4
3
  from pathlib import Path
5
4
  from tempfile import TemporaryDirectory
@@ -13,16 +12,16 @@ from fractal_server.app.models.v2 import TaskGroupV2
13
12
  from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
14
13
  from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
15
14
  from fractal_server.app.schemas.v2.manifest import ManifestV2
16
- from fractal_server.logger import get_logger
17
15
  from fractal_server.logger import set_logger
18
16
  from fractal_server.ssh._fabric import FractalSSH
17
+ from fractal_server.tasks.v2.ssh._utils import _copy_wheel_file_ssh
18
+ from fractal_server.tasks.v2.ssh._utils import _customize_and_run_template
19
19
  from fractal_server.tasks.v2.utils_background import add_commit_refresh
20
20
  from fractal_server.tasks.v2.utils_background import get_current_log
21
21
  from fractal_server.tasks.v2.utils_package_names import compare_package_names
22
22
  from fractal_server.tasks.v2.utils_python_interpreter import (
23
23
  get_python_interpreter_v2,
24
24
  )
25
- from fractal_server.tasks.v2.utils_templates import customize_template
26
25
  from fractal_server.tasks.v2.utils_templates import get_collection_replacements
27
26
  from fractal_server.tasks.v2.utils_templates import (
28
27
  parse_script_pip_show_stdout,
@@ -33,81 +32,6 @@ from fractal_server.utils import get_timestamp
33
32
  LOGGER_NAME = __name__
34
33
 
35
34
 
36
- def _customize_and_run_template(
37
- *,
38
- template_filename: str,
39
- replacements: list[tuple[str, str]],
40
- script_dir_local: str,
41
- prefix: str,
42
- fractal_ssh: FractalSSH,
43
- script_dir_remote: str,
44
- logger_name: str,
45
- ) -> str:
46
- """
47
- Customize one of the template bash scripts, transfer it to the remote host
48
- via SFTP and then run it via SSH.
49
-
50
- Args:
51
- template_filename: Filename of the template file (ends with ".sh").
52
- replacements: Dictionary of replacements.
53
- script_dir: Local folder where the script will be placed.
54
- prefix: Prefix for the script filename.
55
- fractal_ssh: FractalSSH object
56
- script_dir_remote: Remote scripts directory
57
- """
58
- logger = get_logger(logger_name=logger_name)
59
- logger.debug(f"_customize_and_run_template {template_filename} - START")
60
-
61
- # Prepare name and path of script
62
- if not template_filename.endswith(".sh"):
63
- raise ValueError(
64
- f"Invalid {template_filename=} (it must end with '.sh')."
65
- )
66
- script_filename = f"{prefix}_{template_filename}"
67
- script_path_local = Path(script_dir_local) / script_filename
68
-
69
- customize_template(
70
- template_name=template_filename,
71
- replacements=replacements,
72
- script_path=script_path_local,
73
- )
74
-
75
- # Transfer script to remote host
76
- script_path_remote = os.path.join(
77
- script_dir_remote,
78
- script_filename,
79
- )
80
- logger.debug(f"Now transfer {script_path_local=} over SSH.")
81
- fractal_ssh.send_file(
82
- local=script_path_local,
83
- remote=script_path_remote,
84
- )
85
-
86
- # Execute script remotely
87
- cmd = f"bash {script_path_remote}"
88
- logger.debug(f"Now run '{cmd}' over SSH.")
89
- stdout = fractal_ssh.run_command(cmd=cmd)
90
- logger.debug(f"Standard output of '{cmd}':\n{stdout}")
91
-
92
- logger.debug(f"_customize_and_run_template {template_filename} - END")
93
- return stdout
94
-
95
-
96
- def _copy_wheel_file_ssh(
97
- task_group: TaskGroupV2, fractal_ssh: FractalSSH
98
- ) -> str:
99
- logger = get_logger(LOGGER_NAME)
100
- source = task_group.wheel_path
101
- dest = (
102
- Path(task_group.path) / Path(task_group.wheel_path).name
103
- ).as_posix()
104
- cmd = f"cp {source} {dest}"
105
- logger.debug(f"[_copy_wheel_file] START {source=} {dest=}")
106
- fractal_ssh.run_command(cmd=cmd)
107
- logger.debug(f"[_copy_wheel_file] END {source=} {dest=}")
108
- return dest
109
-
110
-
111
35
  def collect_ssh(
112
36
  *,
113
37
  task_group_id: int,
@@ -232,6 +156,7 @@ def collect_ssh(
232
156
  new_wheel_path = _copy_wheel_file_ssh(
233
157
  task_group=task_group,
234
158
  fractal_ssh=fractal_ssh,
159
+ logger_name=LOGGER_NAME,
235
160
  )
236
161
  task_group.wheel_path = new_wheel_path
237
162
  task_group = add_commit_refresh(obj=task_group, db=db)