fractal-server 2.9.1__tar.gz → 2.10.0a0__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 (247) hide show
  1. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/PKG-INFO +1 -1
  2. fractal_server-2.10.0a0/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/security.py +0 -1
  4. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/user_settings.py +1 -2
  5. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/project.py +7 -1
  6. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +2 -2
  7. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/submit.py +9 -5
  8. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/task_collection.py +110 -21
  9. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/workflow_import.py +4 -7
  10. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/_slurm_config.py +2 -2
  11. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/ssh/executor.py +4 -3
  12. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_common.py +1 -2
  13. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local/__init__.py +0 -4
  14. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -6
  15. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +1 -7
  16. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/user_settings.py +0 -18
  17. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/__init__.py +1 -0
  18. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/task_collection.py +31 -35
  19. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/task_group.py +0 -16
  20. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/user_settings.py +2 -2
  21. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/config.py +1 -2
  22. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/logger.py +2 -4
  23. fractal_server-2.10.0a0/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +36 -0
  24. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/ssh/_fabric.py +9 -11
  25. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/local/collect.py +17 -22
  26. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/ssh/_utils.py +1 -1
  27. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/ssh/collect.py +26 -15
  28. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/utils_database.py +6 -3
  29. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/utils_python_interpreter.py +2 -2
  30. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/utils_templates.py +3 -3
  31. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/pyproject.toml +2 -2
  32. fractal_server-2.9.1/fractal_server/__init__.py +0 -1
  33. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/LICENSE +0 -0
  34. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/README.md +0 -0
  35. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/__main__.py +0 -0
  36. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/alembic.ini +0 -0
  37. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/__init__.py +0 -0
  38. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/db/__init__.py +0 -0
  39. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/__init__.py +0 -0
  40. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/linkusergroup.py +0 -0
  41. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/linkuserproject.py +0 -0
  42. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v1/__init__.py +0 -0
  43. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v1/dataset.py +0 -0
  44. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v1/job.py +0 -0
  45. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v1/project.py +0 -0
  46. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v1/state.py +0 -0
  47. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v1/task.py +0 -0
  48. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v1/workflow.py +0 -0
  49. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/__init__.py +0 -0
  50. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/dataset.py +0 -0
  51. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/job.py +0 -0
  52. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/project.py +0 -0
  53. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/task.py +0 -0
  54. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/task_group.py +0 -0
  55. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/workflow.py +0 -0
  56. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/models/v2/workflowtask.py +0 -0
  57. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/__init__.py +0 -0
  58. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/__init__.py +0 -0
  59. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/v1.py +0 -0
  60. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  61. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/v2/job.py +0 -0
  62. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/v2/project.py +0 -0
  63. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/v2/task.py +0 -0
  64. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  65. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  66. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/__init__.py +0 -0
  67. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/__init__.py +0 -0
  68. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/_aux_functions.py +0 -0
  69. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/dataset.py +0 -0
  70. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/job.py +0 -0
  71. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/task.py +0 -0
  72. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/task_collection.py +0 -0
  73. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/workflow.py +0 -0
  74. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v1/workflowtask.py +0 -0
  75. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  76. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  77. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  78. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  79. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/images.py +0 -0
  80. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/job.py +0 -0
  81. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/project.py +0 -0
  82. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/status.py +0 -0
  83. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/task.py +0 -0
  84. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  85. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  86. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  87. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  88. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  89. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/__init__.py +0 -0
  90. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  91. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/current_user.py +0 -0
  92. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/group.py +0 -0
  93. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/login.py +0 -0
  94. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/oauth.py +0 -0
  95. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/register.py +0 -0
  96. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/router.py +0 -0
  97. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/auth/users.py +0 -0
  98. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/aux/__init__.py +0 -0
  99. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/aux/_job.py +0 -0
  100. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/aux/_runner.py +0 -0
  101. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  102. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/.gitignore +0 -0
  103. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/__init__.py +0 -0
  104. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/async_wrap.py +0 -0
  105. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/components.py +0 -0
  106. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/compress_folder.py +0 -0
  107. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/exceptions.py +0 -0
  108. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/__init__.py +0 -0
  109. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
  110. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
  111. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
  112. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
  113. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
  114. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -0
  115. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
  116. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
  117. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
  118. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
  119. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/sudo/executor.py +0 -0
  120. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/executors/slurm/utils_executors.py +0 -0
  121. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/extract_archive.py +0 -0
  122. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/filenames.py +0 -0
  123. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/run_subprocess.py +0 -0
  124. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  125. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/shutdown.py +0 -0
  126. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/task_files.py +0 -0
  127. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/__init__.py +0 -0
  128. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
  129. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
  130. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
  131. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_local/executor.py +0 -0
  132. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
  133. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
  134. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
  135. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/common.py +0 -0
  136. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
  137. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/__init__.py +0 -0
  138. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
  139. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
  140. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local/executor.py +0 -0
  141. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
  142. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
  143. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
  144. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
  145. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
  146. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
  147. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
  148. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
  149. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  150. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
  151. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  152. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/runner.py +0 -0
  153. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  154. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  155. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/v2/task_interface.py +0 -0
  156. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/runner/versions.py +0 -0
  157. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/__init__.py +0 -0
  158. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/_validators.py +0 -0
  159. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/user.py +0 -0
  160. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/user_group.py +0 -0
  161. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/__init__.py +0 -0
  162. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/applyworkflow.py +0 -0
  163. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/dataset.py +0 -0
  164. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/dumps.py +0 -0
  165. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/manifest.py +0 -0
  166. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/project.py +0 -0
  167. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/state.py +0 -0
  168. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/task.py +0 -0
  169. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/task_collection.py +0 -0
  170. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v1/workflow.py +0 -0
  171. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/dataset.py +0 -0
  172. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/dumps.py +0 -0
  173. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/job.py +0 -0
  174. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/manifest.py +0 -0
  175. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/project.py +0 -0
  176. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/status.py +0 -0
  177. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/task.py +0 -0
  178. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/workflow.py +0 -0
  179. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  180. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/app/security/__init__.py +0 -0
  181. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/data_migrations/README.md +0 -0
  182. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/data_migrations/tools.py +0 -0
  183. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/gunicorn_fractal.py +0 -0
  184. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/images/__init__.py +0 -0
  185. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/images/models.py +0 -0
  186. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/images/tools.py +0 -0
  187. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/main.py +0 -0
  188. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/README +0 -0
  189. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/env.py +0 -0
  190. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/naming_convention.py +0 -0
  191. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/script.py.mako +0 -0
  192. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  193. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  194. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  195. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  196. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  197. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  198. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  199. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  200. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  201. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  202. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  203. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  204. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  205. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  206. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  207. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  208. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  209. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  210. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  211. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  212. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  213. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  214. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  215. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  216. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  217. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/py.typed +0 -0
  218. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/ssh/__init__.py +0 -0
  219. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/string_tools.py +0 -0
  220. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/syringe.py +0 -0
  221. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/__init__.py +0 -0
  222. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/utils.py +0 -0
  223. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v1/_TaskCollectPip.py +0 -0
  224. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v1/__init__.py +0 -0
  225. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v1/background_operations.py +0 -0
  226. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v1/endpoint_operations.py +0 -0
  227. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v1/get_collection_data.py +0 -0
  228. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v1/utils.py +0 -0
  229. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/__init__.py +0 -0
  230. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/local/__init__.py +0 -0
  231. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/local/_utils.py +0 -0
  232. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  233. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  234. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  235. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  236. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  237. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  238. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  239. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  240. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  241. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  242. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  243. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/utils_background.py +0 -0
  244. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  245. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/urls.py +0 -0
  246. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/fractal_server/utils.py +0 -0
  247. {fractal_server-2.9.1 → fractal_server-2.10.0a0}/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.9.1
3
+ Version: 2.10.0a0
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.10.0a0"
@@ -76,7 +76,6 @@ class UserOAuth(SQLModel, table=True):
76
76
  is_verified:
77
77
  slurm_user:
78
78
  slurm_accounts:
79
- cache_dir:
80
79
  username:
81
80
  oauth_accounts:
82
81
  """
@@ -20,7 +20,7 @@ class UserSettings(SQLModel, table=True):
20
20
  ssh_tasks_dir: Task-venvs base folder on `ssh_host`.
21
21
  ssh_jobs_dir: Jobs base folder on `ssh_host`.
22
22
  slurm_user: Local user, to be impersonated via `sudo -u`
23
- cache_dir: Folder where `slurm_user` can write.
23
+ project_dir: Folder where `slurm_user` can write.
24
24
  """
25
25
 
26
26
  __tablename__ = "user_settings"
@@ -35,5 +35,4 @@ class UserSettings(SQLModel, table=True):
35
35
  ssh_tasks_dir: Optional[str] = None
36
36
  ssh_jobs_dir: Optional[str] = None
37
37
  slurm_user: Optional[str] = None
38
- cache_dir: Optional[str] = None
39
38
  project_dir: Optional[str] = None
@@ -448,6 +448,12 @@ async def apply_workflow(
448
448
  await db.commit()
449
449
  await db.refresh(job)
450
450
 
451
+ cache_dir = (
452
+ f"{user_settings.project_dir}/.fractal_cache"
453
+ if user_settings.project_dir is not None
454
+ else None
455
+ )
456
+
451
457
  background_tasks.add_task(
452
458
  submit_workflow,
453
459
  workflow_id=workflow.id,
@@ -456,7 +462,7 @@ async def apply_workflow(
456
462
  job_id=job.id,
457
463
  worker_init=apply_workflow.worker_init,
458
464
  slurm_user=user_settings.slurm_user,
459
- user_cache_dir=user_settings.cache_dir,
465
+ user_cache_dir=cache_dir,
460
466
  )
461
467
  request.app.state.jobsV1.append(job.id)
462
468
  logger.info(
@@ -182,8 +182,8 @@ async def check_no_submitted_job(
182
182
  Find submitted jobs which include tasks from a given task group.
183
183
 
184
184
  Arguments:
185
- task_id_list: List of TaskV2 IDs
186
- db: Database session
185
+ task_group_id: ID of the `TaskGroupV2` object.
186
+ db: Asynchronous database session.
187
187
  """
188
188
  stm = (
189
189
  select(func.count(JobV2.id))
@@ -186,18 +186,22 @@ async def apply_workflow(
186
186
  f"_{timestamp_string}"
187
187
  )
188
188
 
189
+ cache_dir = (
190
+ Path(user_settings.project_dir) / ".fractal_cache"
191
+ if user_settings.project_dir is not None
192
+ else None
193
+ )
194
+
189
195
  # Define user-side job directory
190
196
  if FRACTAL_RUNNER_BACKEND == "local":
191
197
  WORKFLOW_DIR_REMOTE = WORKFLOW_DIR_LOCAL
192
198
  elif FRACTAL_RUNNER_BACKEND == "local_experimental":
193
199
  WORKFLOW_DIR_REMOTE = WORKFLOW_DIR_LOCAL
194
200
  elif FRACTAL_RUNNER_BACKEND == "slurm":
195
- WORKFLOW_DIR_REMOTE = (
196
- Path(user_settings.cache_dir) / f"{WORKFLOW_DIR_LOCAL.name}"
197
- )
201
+ WORKFLOW_DIR_REMOTE = cache_dir / WORKFLOW_DIR_LOCAL.name
198
202
  elif FRACTAL_RUNNER_BACKEND == "slurm_ssh":
199
203
  WORKFLOW_DIR_REMOTE = (
200
- Path(user_settings.ssh_jobs_dir) / f"{WORKFLOW_DIR_LOCAL.name}"
204
+ Path(user_settings.ssh_jobs_dir) / WORKFLOW_DIR_LOCAL.name
201
205
  )
202
206
 
203
207
  # Update job folders in the db
@@ -229,7 +233,7 @@ async def apply_workflow(
229
233
  user_settings=user_settings,
230
234
  worker_init=job.worker_init,
231
235
  slurm_user=user_settings.slurm_user,
232
- user_cache_dir=user_settings.cache_dir,
236
+ user_cache_dir=cache_dir.as_posix() if cache_dir else None,
233
237
  fractal_ssh=fractal_ssh,
234
238
  )
235
239
  request.app.state.jobsV2.append(job.id)
@@ -1,13 +1,19 @@
1
+ import json
1
2
  from pathlib import Path
2
3
  from typing import Optional
3
4
 
4
5
  from fastapi import APIRouter
5
6
  from fastapi import BackgroundTasks
6
7
  from fastapi import Depends
8
+ from fastapi import File
9
+ from fastapi import Form
7
10
  from fastapi import HTTPException
8
11
  from fastapi import Request
9
12
  from fastapi import Response
10
13
  from fastapi import status
14
+ from fastapi import UploadFile
15
+ from pydantic import BaseModel
16
+ from pydantic import root_validator
11
17
  from pydantic import ValidationError
12
18
  from sqlmodel import select
13
19
 
@@ -22,6 +28,7 @@ from ....schemas.v2 import TaskCollectPipV2
22
28
  from ....schemas.v2 import TaskGroupActivityStatusV2
23
29
  from ....schemas.v2 import TaskGroupActivityV2Read
24
30
  from ....schemas.v2 import TaskGroupCreateV2Strict
31
+ from ....schemas.v2 import WheelFile
25
32
  from ...aux.validate_user_settings import validate_user_settings
26
33
  from ._aux_functions_task_lifecycle import get_package_version_from_pypi
27
34
  from ._aux_functions_tasks import _get_valid_user_group_id
@@ -44,20 +51,99 @@ from fractal_server.tasks.v2.utils_python_interpreter import (
44
51
  get_python_interpreter_v2,
45
52
  )
46
53
 
54
+
47
55
  router = APIRouter()
48
56
 
49
57
  logger = set_logger(__name__)
50
58
 
51
59
 
60
+ class CollectionRequestData(BaseModel):
61
+ """
62
+ Validate form data _and_ wheel file.
63
+ """
64
+
65
+ task_collect: TaskCollectPipV2
66
+ file: Optional[UploadFile] = None
67
+ origin: TaskGroupV2OriginEnum
68
+
69
+ @root_validator(pre=True)
70
+ def validate_data(cls, values):
71
+ file = values.get("file")
72
+ package = values.get("task_collect").package
73
+ package_version = values.get("task_collect").package_version
74
+
75
+ if file is None:
76
+ if package is None:
77
+ raise ValueError(
78
+ "When no `file` is provided, `package` is required."
79
+ )
80
+ values["origin"] = TaskGroupV2OriginEnum.PYPI
81
+ else:
82
+ if package is not None:
83
+ raise ValueError(
84
+ "Cannot set `package` when `file` is provided "
85
+ f"(given package='{package}')."
86
+ )
87
+ if package_version is not None:
88
+ raise ValueError(
89
+ "Cannot set `package_version` when `file` is "
90
+ f"provided (given package_version='{package_version}')."
91
+ )
92
+ values["origin"] = TaskGroupV2OriginEnum.WHEELFILE
93
+ return values
94
+
95
+
96
+ def parse_request_data(
97
+ package: Optional[str] = Form(None),
98
+ package_version: Optional[str] = Form(None),
99
+ package_extras: Optional[str] = Form(None),
100
+ python_version: Optional[str] = Form(None),
101
+ pinned_package_versions: Optional[str] = Form(None),
102
+ file: Optional[UploadFile] = File(None),
103
+ ) -> CollectionRequestData:
104
+ """
105
+ Expand the parsing/validation of `parse_form_data`, based on `file`.
106
+ """
107
+
108
+ try:
109
+ # Convert dict_pinned_pkg from a JSON string into a Python dictionary
110
+ dict_pinned_pkg = (
111
+ json.loads(pinned_package_versions)
112
+ if pinned_package_versions
113
+ else None
114
+ )
115
+ # Validate and coerce form data
116
+ task_collect_pip = TaskCollectPipV2(
117
+ package=package,
118
+ package_version=package_version,
119
+ package_extras=package_extras,
120
+ python_version=python_version,
121
+ pinned_package_versions=dict_pinned_pkg,
122
+ )
123
+
124
+ data = CollectionRequestData(
125
+ task_collect=task_collect_pip,
126
+ file=file,
127
+ )
128
+
129
+ except (ValidationError, json.JSONDecodeError) as e:
130
+ raise HTTPException(
131
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
132
+ detail=f"Invalid request-body\n{str(e)}",
133
+ )
134
+
135
+ return data
136
+
137
+
52
138
  @router.post(
53
139
  "/collect/pip/",
54
140
  response_model=TaskGroupActivityV2Read,
55
141
  )
56
142
  async def collect_tasks_pip(
57
- task_collect: TaskCollectPipV2,
58
- background_tasks: BackgroundTasks,
59
- response: Response,
60
143
  request: Request,
144
+ response: Response,
145
+ background_tasks: BackgroundTasks,
146
+ request_data: CollectionRequestData = Depends(parse_request_data),
61
147
  private: bool = False,
62
148
  user_group_id: Optional[int] = None,
63
149
  user: UserOAuth = Depends(current_active_verified_user),
@@ -66,12 +152,17 @@ async def collect_tasks_pip(
66
152
  """
67
153
  Task-collection endpoint
68
154
  """
69
-
70
155
  # Get settings
71
156
  settings = Inject(get_settings)
72
157
 
158
+ # Get some validated request data
159
+ task_collect = request_data.task_collect
160
+
73
161
  # Initialize task-group attributes
74
- task_group_attrs = dict(user_id=user.id)
162
+ task_group_attrs = dict(
163
+ user_id=user.id,
164
+ origin=request_data.origin,
165
+ )
75
166
 
76
167
  # Set/check python version
77
168
  if task_collect.python_version is None:
@@ -103,12 +194,19 @@ async def collect_tasks_pip(
103
194
  "pinned_package_versions"
104
195
  ] = task_collect.pinned_package_versions
105
196
 
197
+ # Initialize wheel_file_content as None
198
+ wheel_file = None
199
+
106
200
  # Set pkg_name, version, origin and wheel_path
107
- if task_collect.package.endswith(".whl"):
201
+ if request_data.origin == TaskGroupV2OriginEnum.WHEELFILE:
108
202
  try:
109
- task_group_attrs["wheel_path"] = task_collect.package
110
- wheel_filename = Path(task_group_attrs["wheel_path"]).name
203
+ wheel_filename = request_data.file.filename
111
204
  wheel_info = _parse_wheel_filename(wheel_filename)
205
+ wheel_file_content = await request_data.file.read()
206
+ wheel_file = WheelFile(
207
+ filename=wheel_filename,
208
+ contents=wheel_file_content,
209
+ )
112
210
  except ValueError as e:
113
211
  raise HTTPException(
114
212
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
@@ -121,11 +219,9 @@ async def collect_tasks_pip(
121
219
  wheel_info["distribution"]
122
220
  )
123
221
  task_group_attrs["version"] = wheel_info["version"]
124
- task_group_attrs["origin"] = TaskGroupV2OriginEnum.WHEELFILE
125
- else:
222
+ elif request_data.origin == TaskGroupV2OriginEnum.PYPI:
126
223
  pkg_name = task_collect.package
127
224
  task_group_attrs["pkg_name"] = normalize_package_name(pkg_name)
128
- task_group_attrs["origin"] = TaskGroupV2OriginEnum.PYPI
129
225
  latest_version = await get_package_version_from_pypi(
130
226
  task_collect.package,
131
227
  task_collect.package_version,
@@ -202,7 +298,6 @@ async def collect_tasks_pip(
202
298
  # On-disk checks
203
299
 
204
300
  if settings.FRACTAL_RUNNER_BACKEND != "slurm_ssh":
205
-
206
301
  # Verify that folder does not exist (for local collection)
207
302
  if Path(task_group_path).exists():
208
303
  raise HTTPException(
@@ -210,15 +305,6 @@ async def collect_tasks_pip(
210
305
  detail=f"{task_group_path} already exists.",
211
306
  )
212
307
 
213
- # Verify that wheel file exists
214
- wheel_path = task_group_attrs.get("wheel_path", None)
215
- if wheel_path is not None:
216
- if not Path(wheel_path).exists():
217
- raise HTTPException(
218
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
219
- detail=f"No such file: {wheel_path}.",
220
- )
221
-
222
308
  # Create TaskGroupV2 object
223
309
  task_group = TaskGroupV2(**task_group_attrs)
224
310
  db.add(task_group)
@@ -259,14 +345,17 @@ async def collect_tasks_pip(
259
345
  task_group_activity_id=task_group_activity.id,
260
346
  fractal_ssh=fractal_ssh,
261
347
  tasks_base_dir=user_settings.ssh_tasks_dir,
348
+ wheel_file=wheel_file,
262
349
  )
263
350
 
264
351
  else:
265
352
  # Local task collection
353
+
266
354
  background_tasks.add_task(
267
355
  collect_local,
268
356
  task_group_id=task_group.id,
269
357
  task_group_activity_id=task_group_activity.id,
358
+ wheel_file=wheel_file,
270
359
  )
271
360
  logger.debug(
272
361
  "Task-collection endpoint: start background collection "
@@ -68,11 +68,8 @@ async def _get_task_by_source(
68
68
  Find task with a given source.
69
69
 
70
70
  Args:
71
- task_import: Info on task to be imported.
72
- user_id: ID of current user.
73
- default_group_id: ID of default user group.
74
- task_group_list: Current list of valid task groups.
75
- db: Asynchronous db session
71
+ source: `source` of the task to be imported.
72
+ task_groups_list: Current list of valid task groups.
76
73
 
77
74
  Return:
78
75
  `id` of the matching task, or `None`.
@@ -172,10 +169,10 @@ async def _get_task_by_taskimport(
172
169
 
173
170
  Args:
174
171
  task_import: Info on task to be imported.
172
+ task_groups_list: Current list of valid task groups.
175
173
  user_id: ID of current user.
176
174
  default_group_id: ID of default user group.
177
- task_group_list: Current list of valid task groups.
178
- db: Asynchronous db session
175
+ db: Asynchronous database session.
179
176
 
180
177
  Return:
181
178
  `id` of the matching task, or `None`.
@@ -327,7 +327,7 @@ class SlurmConfig(BaseModel, extra=Extra.forbid):
327
327
  script.
328
328
 
329
329
  Arguments:
330
- user_cache_dir:
330
+ remote_export_dir:
331
331
  Base directory for exports defined in
332
332
  `self.user_local_exports`.
333
333
  """
@@ -378,7 +378,7 @@ class SlurmConfig(BaseModel, extra=Extra.forbid):
378
378
  if self.user_local_exports:
379
379
  if remote_export_dir is None:
380
380
  raise ValueError(
381
- f"user_cache_dir=None but {self.user_local_exports=}"
381
+ f"remote_export_dir=None but {self.user_local_exports=}"
382
382
  )
383
383
  for key, value in self.user_local_exports.items():
384
384
  tmp_value = str(Path(remote_export_dir) / value)
@@ -917,7 +917,7 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
917
917
  thread via `fut.set_exception(...)`.
918
918
 
919
919
  Arguments:
920
- jobid: ID of the SLURM job
920
+ job_ids: IDs of the SLURM jobs to handle.
921
921
  """
922
922
  # Handle all uncaught exceptions in this broad try/except block
923
923
  try:
@@ -1109,8 +1109,9 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
1109
1109
  Fetch a remote folder via tar+sftp+tar
1110
1110
 
1111
1111
  Arguments:
1112
- job:
1113
- `SlurmJob` object (needed for its prefixes-related attributes).
1112
+ jobs:
1113
+ List of `SlurmJob` object (needed for their prefix-related
1114
+ attributes).
1114
1115
  """
1115
1116
 
1116
1117
  # Check that the subfolder is unique
@@ -524,8 +524,7 @@ def execute_tasks(
524
524
 
525
525
  **Note:** At the end of each task, write current metadata to
526
526
  `workflow_dir_local / METADATA_FILENAME`, so that they can be read as part
527
- of the [`get_job`
528
- endpoint](../../api/v1/job/#fractal_server.app.routes.api.v1.job.get_job).
527
+ of the `get_job` endpoint.
529
528
 
530
529
  Arguments:
531
530
  executor:
@@ -44,10 +44,6 @@ def _process_workflow(
44
44
  Internal processing routine
45
45
 
46
46
  Schedules the workflow using a `FractalThreadPoolExecutor`.
47
-
48
- Cf.
49
- [process_workflow][fractal_server.app.runner.v2._local.process_workflow]
50
- for the call signature.
51
47
  """
52
48
 
53
49
  with FractalThreadPoolExecutor() as executor:
@@ -55,9 +55,6 @@ def _process_workflow(
55
55
  workflow working dir and user to impersonate. It then schedules the
56
56
  workflow tasks and returns the new dataset attributes
57
57
 
58
- Cf.
59
- [process_workflow][fractal_server.app.runner.v2._local.process_workflow]
60
-
61
58
  Returns:
62
59
  new_dataset_attributes:
63
60
  """
@@ -115,9 +112,6 @@ async def process_workflow(
115
112
  ) -> dict:
116
113
  """
117
114
  Process workflow (SLURM backend public interface)
118
-
119
- Cf.
120
- [process_workflow][fractal_server.app.runner.v2._local.process_workflow]
121
115
  """
122
116
 
123
117
  # Set values of first_task_index and last_task_index
@@ -51,9 +51,6 @@ def _process_workflow(
51
51
  workflow working dir and user to impersonate. It then schedules the
52
52
  workflow tasks and returns the new dataset attributes
53
53
 
54
- Cf.
55
- [process_workflow][fractal_server.app.runner.v2._local.process_workflow]
56
-
57
54
  Returns:
58
55
  new_dataset_attributes:
59
56
  """
@@ -106,10 +103,7 @@ async def process_workflow(
106
103
  worker_init: Optional[str] = None,
107
104
  ) -> dict:
108
105
  """
109
- Process workflow (SLURM backend public interface)
110
-
111
- Cf.
112
- [process_workflow][fractal_server.app.runner.v2._local.process_workflow]
106
+ Process workflow (SLURM backend public interface).
113
107
  """
114
108
 
115
109
  # Set values of first_task_index and last_task_index
@@ -31,14 +31,12 @@ class UserSettingsRead(BaseModel):
31
31
  ssh_jobs_dir: Optional[str] = None
32
32
  slurm_user: Optional[str] = None
33
33
  slurm_accounts: list[str]
34
- cache_dir: Optional[str] = None
35
34
  project_dir: Optional[str] = None
36
35
 
37
36
 
38
37
  class UserSettingsReadStrict(BaseModel):
39
38
  slurm_user: Optional[str] = None
40
39
  slurm_accounts: list[str]
41
- cache_dir: Optional[str] = None
42
40
  ssh_username: Optional[str] = None
43
41
  project_dir: Optional[str] = None
44
42
 
@@ -55,7 +53,6 @@ class UserSettingsUpdate(BaseModel, extra=Extra.forbid):
55
53
  ssh_jobs_dir: Optional[str] = None
56
54
  slurm_user: Optional[str] = None
57
55
  slurm_accounts: Optional[list[StrictStr]] = None
58
- cache_dir: Optional[str] = None
59
56
  project_dir: Optional[str] = None
60
57
 
61
58
  _ssh_host = validator("ssh_host", allow_reuse=True)(
@@ -87,13 +84,6 @@ class UserSettingsUpdate(BaseModel, extra=Extra.forbid):
87
84
  value[i] = valstr(f"slurm_accounts[{i}]")(item)
88
85
  return val_unique_list("slurm_accounts")(value)
89
86
 
90
- @validator("cache_dir")
91
- def cache_dir_validator(cls, value):
92
- if value is None:
93
- return None
94
- validate_cmd(value)
95
- return val_absolute_path("cache_dir")(value)
96
-
97
87
  @validator("project_dir")
98
88
  def project_dir_validator(cls, value):
99
89
  if value is None:
@@ -104,15 +94,7 @@ class UserSettingsUpdate(BaseModel, extra=Extra.forbid):
104
94
 
105
95
  class UserSettingsUpdateStrict(BaseModel, extra=Extra.forbid):
106
96
  slurm_accounts: Optional[list[StrictStr]] = None
107
- cache_dir: Optional[str] = None
108
97
 
109
98
  _slurm_accounts = validator("slurm_accounts", allow_reuse=True)(
110
99
  val_unique_list("slurm_accounts")
111
100
  )
112
-
113
- @validator("cache_dir")
114
- def cache_dir_validator(cls, value):
115
- if value is None:
116
- return value
117
- validate_cmd(value)
118
- return val_absolute_path("cache_dir")(value)
@@ -25,6 +25,7 @@ from .task import TaskReadV2 # noqa F401
25
25
  from .task import TaskUpdateV2 # noqa F401
26
26
  from .task_collection import TaskCollectCustomV2 # noqa F401
27
27
  from .task_collection import TaskCollectPipV2 # noqa F401
28
+ from .task_collection import WheelFile # noqa F401
28
29
  from .task_group import TaskGroupActivityActionV2 # noqa F401
29
30
  from .task_group import TaskGroupActivityStatusV2 # noqa F401
30
31
  from .task_group import TaskGroupActivityV2Read # noqa F401
@@ -12,6 +12,15 @@ from fractal_server.app.schemas.v2 import ManifestV2
12
12
  from fractal_server.string_tools import validate_cmd
13
13
 
14
14
 
15
+ class WheelFile(BaseModel):
16
+ """
17
+ Model for data sent from the endpoint to the background task.
18
+ """
19
+
20
+ filename: str
21
+ contents: bytes
22
+
23
+
15
24
  class TaskCollectPipV2(BaseModel, extra=Extra.forbid):
16
25
  """
17
26
  TaskCollectPipV2 class
@@ -22,14 +31,11 @@ class TaskCollectPipV2(BaseModel, extra=Extra.forbid):
22
31
 
23
32
  Two cases are supported:
24
33
 
25
- 1. `package` is the path of a local wheel file;
26
- 2. `package` is the name of a package that can be installed via `pip`.
27
-
34
+ 1. `package` is the name of a package that can be installed via `pip`.
35
+ 1. `package=None`, and a wheel file is uploaded within the API request.
28
36
 
29
37
  Attributes:
30
- package:
31
- The name of a `pip`-installable package, or the path to a local
32
- wheel file.
38
+ package: The name of a `pip`-installable package, or `None`.
33
39
  package_version: Version of the package
34
40
  package_extras: Package extras to include in the `pip install` command
35
41
  python_version: Python version to install and run the package tasks
@@ -39,12 +45,28 @@ class TaskCollectPipV2(BaseModel, extra=Extra.forbid):
39
45
 
40
46
  """
41
47
 
42
- package: str
48
+ package: Optional[str] = None
43
49
  package_version: Optional[str] = None
44
50
  package_extras: Optional[str] = None
45
51
  python_version: Optional[Literal["3.9", "3.10", "3.11", "3.12"]] = None
46
52
  pinned_package_versions: Optional[dict[str, str]] = None
47
53
 
54
+ @validator("package")
55
+ def package_validator(cls, value: Optional[str]) -> Optional[str]:
56
+ if value is None:
57
+ return value
58
+ value = valstr("package")(value)
59
+ validate_cmd(value, attribute_name="package")
60
+ return value
61
+
62
+ @validator("package_version")
63
+ def package_version_validator(cls, value: Optional[str]) -> Optional[str]:
64
+ if value is None:
65
+ return value
66
+ value = valstr("package_version")(value)
67
+ validate_cmd(value, attribute_name="package_version")
68
+ return value
69
+
48
70
  @validator("pinned_package_versions")
49
71
  def pinned_package_versions_validator(cls, value):
50
72
  if value is None:
@@ -65,36 +87,10 @@ class TaskCollectPipV2(BaseModel, extra=Extra.forbid):
65
87
  validate_cmd(version)
66
88
  return value
67
89
 
68
- @validator("package")
69
- def package_validator(cls, value):
70
- value = valstr("package")(value)
71
- if "/" in value or value.endswith(".whl"):
72
- if not value.endswith(".whl"):
73
- raise ValueError(
74
- "Local-package path must be a wheel file "
75
- f"(given {value})."
76
- )
77
- if not Path(value).is_absolute():
78
- raise ValueError(
79
- f"Local-package path must be absolute: (given {value})."
80
- )
81
- validate_cmd(value, attribute_name="package")
82
- return value
83
-
84
- @validator("package_version")
85
- def package_version_validator(
86
- cls, v: Optional[str], values
87
- ) -> Optional[str]:
88
- v = valstr("package_version")(v)
89
- if values["package"].endswith(".whl"):
90
- raise ValueError(
91
- "Cannot provide package version when package is a wheel file."
92
- )
93
- validate_cmd(v, attribute_name="package_version")
94
- return v
95
-
96
90
  @validator("package_extras")
97
91
  def package_extras_validator(cls, value: Optional[str]) -> Optional[str]:
92
+ if value is None:
93
+ return value
98
94
  value = valstr("package_extras")(value)
99
95
  validate_cmd(value, attribute_name="package_extras")
100
96
  return value
@@ -5,7 +5,6 @@ from typing import Optional
5
5
  from pydantic import BaseModel
6
6
  from pydantic import Extra
7
7
  from pydantic import Field
8
- from pydantic import root_validator
9
8
  from pydantic import validator
10
9
 
11
10
  from .._validators import val_absolute_path
@@ -77,21 +76,6 @@ class TaskGroupCreateV2Strict(TaskGroupCreateV2):
77
76
  version: str
78
77
  python_version: str
79
78
 
80
- @root_validator
81
- def check_wheel_file(cls, values):
82
- origin = values.get("origin")
83
- wheel_path = values.get("wheel_path")
84
- bad_condition_1 = (
85
- origin == TaskGroupV2OriginEnum.WHEELFILE and wheel_path is None
86
- )
87
- bad_condition_2 = (
88
- origin != TaskGroupV2OriginEnum.WHEELFILE
89
- and wheel_path is not None
90
- )
91
- if bad_condition_1 or bad_condition_2:
92
- raise ValueError(f"Cannot have {origin=} and {wheel_path=}.")
93
- return values
94
-
95
79
 
96
80
  class TaskGroupReadV2(BaseModel):
97
81
  id: int
@@ -32,11 +32,11 @@ class SlurmSudoUserSettings(BaseModel):
32
32
 
33
33
  Attributes:
34
34
  slurm_user: User to be impersonated via `sudo -u`.
35
- cache_dir: Folder where `slurm_user` can write.
35
+ project_dir: Folder where `slurm_user` can write.
36
36
  slurm_accounts:
37
37
  List of SLURM accounts, to be used upon Fractal job submission.
38
38
  """
39
39
 
40
40
  slurm_user: str
41
- cache_dir: str
41
+ project_dir: str
42
42
  slurm_accounts: list[str]