fractal-server 2.6.3__tar.gz → 2.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. {fractal_server-2.6.3 → fractal_server-2.7.0}/PKG-INFO +3 -7
  2. fractal_server-2.7.0/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/__main__.py +1 -1
  4. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/linkusergroup.py +11 -0
  5. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v2/__init__.py +2 -0
  6. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v2/collection_state.py +1 -0
  7. fractal_server-2.7.0/fractal_server/app/models/v2/task.py +106 -0
  8. fractal_server-2.7.0/fractal_server/app/routes/admin/v2/__init__.py +16 -0
  9. fractal_server-2.6.3/fractal_server/app/routes/admin/v2.py → fractal_server-2.7.0/fractal_server/app/routes/admin/v2/job.py +20 -191
  10. fractal_server-2.7.0/fractal_server/app/routes/admin/v2/project.py +43 -0
  11. fractal_server-2.7.0/fractal_server/app/routes/admin/v2/task.py +133 -0
  12. fractal_server-2.7.0/fractal_server/app/routes/admin/v2/task_group.py +162 -0
  13. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/task_collection.py +4 -4
  14. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/__init__.py +8 -0
  15. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/_aux_functions.py +1 -68
  16. fractal_server-2.7.0/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +343 -0
  17. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/submit.py +16 -35
  18. fractal_server-2.7.0/fractal_server/app/routes/api/v2/task.py +230 -0
  19. fractal_server-2.7.0/fractal_server/app/routes/api/v2/task_collection.py +337 -0
  20. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/task_collection_custom.py +70 -64
  21. fractal_server-2.7.0/fractal_server/app/routes/api/v2/task_group.py +173 -0
  22. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/workflow.py +39 -102
  23. fractal_server-2.7.0/fractal_server/app/routes/api/v2/workflow_import.py +360 -0
  24. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/workflowtask.py +4 -8
  25. fractal_server-2.7.0/fractal_server/app/routes/auth/_aux_auth.py +159 -0
  26. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/current_user.py +5 -5
  27. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/group.py +73 -23
  28. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/router.py +0 -2
  29. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/users.py +8 -7
  30. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/ssh/executor.py +82 -63
  31. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/__init__.py +13 -7
  32. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/task_interface.py +4 -9
  33. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/user.py +1 -2
  34. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/__init__.py +7 -0
  35. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/dataset.py +2 -7
  36. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/dumps.py +1 -2
  37. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/job.py +1 -1
  38. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/manifest.py +25 -1
  39. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/project.py +1 -1
  40. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/task.py +95 -36
  41. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/task_collection.py +8 -6
  42. fractal_server-2.7.0/fractal_server/app/schemas/v2/task_group.py +85 -0
  43. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/workflow.py +7 -2
  44. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/workflowtask.py +9 -6
  45. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/security/__init__.py +8 -1
  46. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/config.py +8 -28
  47. fractal_server-2.7.0/fractal_server/data_migrations/2_7_0.py +323 -0
  48. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/images/models.py +2 -4
  49. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/main.py +1 -1
  50. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/env.py +4 -1
  51. fractal_server-2.7.0/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +184 -0
  52. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/ssh/_fabric.py +186 -73
  53. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/string_tools.py +6 -2
  54. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/utils.py +19 -5
  55. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v1/_TaskCollectPip.py +1 -1
  56. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v1/background_operations.py +5 -5
  57. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v1/get_collection_data.py +2 -2
  58. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/_venv_pip.py +67 -70
  59. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/background_operations.py +180 -69
  60. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/background_operations_ssh.py +57 -70
  61. fractal_server-2.7.0/fractal_server/tasks/v2/database_operations.py +44 -0
  62. fractal_server-2.7.0/fractal_server/tasks/v2/endpoint_operations.py +124 -0
  63. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/templates/_1_create_venv.sh +9 -5
  64. fractal_server-2.6.3/fractal_server/tasks/v2/templates/_2_upgrade_pip.sh → fractal_server-2.7.0/fractal_server/tasks/v2/templates/_2_preliminary_pip_operations.sh +1 -0
  65. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/utils.py +5 -0
  66. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/utils.py +3 -2
  67. {fractal_server-2.6.3 → fractal_server-2.7.0}/pyproject.toml +4 -7
  68. fractal_server-2.6.3/fractal_server/__init__.py +0 -1
  69. fractal_server-2.6.3/fractal_server/app/models/v2/task.py +0 -41
  70. fractal_server-2.6.3/fractal_server/app/routes/api/v2/task.py +0 -255
  71. fractal_server-2.6.3/fractal_server/app/routes/api/v2/task_collection.py +0 -349
  72. fractal_server-2.6.3/fractal_server/app/routes/auth/_aux_auth.py +0 -113
  73. fractal_server-2.6.3/fractal_server/app/routes/auth/group_names.py +0 -34
  74. fractal_server-2.6.3/fractal_server/tasks/v2/_TaskCollectPip.py +0 -132
  75. fractal_server-2.6.3/fractal_server/tasks/v2/endpoint_operations.py +0 -136
  76. {fractal_server-2.6.3 → fractal_server-2.7.0}/LICENSE +0 -0
  77. {fractal_server-2.6.3 → fractal_server-2.7.0}/README.md +0 -0
  78. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/alembic.ini +0 -0
  79. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/__init__.py +0 -0
  80. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/db/__init__.py +0 -0
  81. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/__init__.py +0 -0
  82. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/linkuserproject.py +0 -0
  83. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/security.py +0 -0
  84. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/user_settings.py +0 -0
  85. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v1/__init__.py +0 -0
  86. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v1/dataset.py +0 -0
  87. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v1/job.py +0 -0
  88. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v1/project.py +0 -0
  89. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v1/state.py +0 -0
  90. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v1/task.py +0 -0
  91. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v1/workflow.py +0 -0
  92. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v2/dataset.py +0 -0
  93. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v2/job.py +0 -0
  94. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v2/project.py +0 -0
  95. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v2/workflow.py +0 -0
  96. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/models/v2/workflowtask.py +0 -0
  97. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/__init__.py +0 -0
  98. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/admin/__init__.py +0 -0
  99. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/admin/v1.py +0 -0
  100. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/__init__.py +0 -0
  101. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/__init__.py +0 -0
  102. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/_aux_functions.py +0 -0
  103. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/dataset.py +0 -0
  104. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/job.py +0 -0
  105. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/project.py +0 -0
  106. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/task.py +0 -0
  107. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/workflow.py +0 -0
  108. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v1/workflowtask.py +0 -0
  109. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  110. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/images.py +0 -0
  111. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/job.py +0 -0
  112. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/project.py +0 -0
  113. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/api/v2/status.py +0 -0
  114. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/__init__.py +0 -0
  115. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/login.py +0 -0
  116. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/oauth.py +0 -0
  117. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/auth/register.py +0 -0
  118. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/aux/__init__.py +0 -0
  119. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/aux/_job.py +0 -0
  120. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/aux/_runner.py +0 -0
  121. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  122. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/.gitignore +0 -0
  123. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/__init__.py +0 -0
  124. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/async_wrap.py +0 -0
  125. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/components.py +0 -0
  126. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/compress_folder.py +0 -0
  127. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/exceptions.py +0 -0
  128. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/__init__.py +0 -0
  129. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
  130. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
  131. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
  132. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
  133. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
  134. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
  135. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -0
  136. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
  137. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
  138. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
  139. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
  140. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/executors/slurm/sudo/executor.py +0 -0
  141. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/extract_archive.py +0 -0
  142. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/filenames.py +0 -0
  143. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/run_subprocess.py +0 -0
  144. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  145. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/shutdown.py +0 -0
  146. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/task_files.py +0 -0
  147. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/__init__.py +0 -0
  148. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_common.py +0 -0
  149. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
  150. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
  151. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
  152. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_local/executor.py +0 -0
  153. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
  154. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
  155. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
  156. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/common.py +0 -0
  157. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
  158. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
  159. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
  160. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
  161. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local/executor.py +0 -0
  162. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
  163. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
  164. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
  165. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
  166. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
  167. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
  168. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
  169. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
  170. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +0 -0
  171. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
  172. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  173. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
  174. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  175. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/runner.py +0 -0
  176. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  177. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  178. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/runner/versions.py +0 -0
  179. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/__init__.py +0 -0
  180. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/_validators.py +0 -0
  181. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/user_group.py +0 -0
  182. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/user_settings.py +0 -0
  183. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/__init__.py +0 -0
  184. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/applyworkflow.py +0 -0
  185. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/dataset.py +0 -0
  186. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/dumps.py +0 -0
  187. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/manifest.py +0 -0
  188. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/project.py +0 -0
  189. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/state.py +0 -0
  190. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/task.py +0 -0
  191. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/task_collection.py +0 -0
  192. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v1/workflow.py +0 -0
  193. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/schemas/v2/status.py +0 -0
  194. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/app/user_settings.py +0 -0
  195. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/data_migrations/README.md +0 -0
  196. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/data_migrations/tools.py +0 -0
  197. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/gunicorn_fractal.py +0 -0
  198. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/images/__init__.py +0 -0
  199. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/images/tools.py +0 -0
  200. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/logger.py +0 -0
  201. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/README +0 -0
  202. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/naming_convention.py +0 -0
  203. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/script.py.mako +0 -0
  204. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  205. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  206. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  207. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  208. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  209. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  210. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  211. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  212. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  213. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  214. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  215. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  216. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  217. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  218. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  219. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  220. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  221. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  222. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  223. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  224. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  225. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/py.typed +0 -0
  226. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/ssh/__init__.py +0 -0
  227. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/syringe.py +0 -0
  228. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/__init__.py +0 -0
  229. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v1/__init__.py +0 -0
  230. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v1/endpoint_operations.py +0 -0
  231. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v1/utils.py +0 -0
  232. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/__init__.py +0 -0
  233. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/templates/_3_pip_install.sh +0 -0
  234. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/templates/_4_pip_freeze.sh +0 -0
  235. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/tasks/v2/templates/_5_pip_show.sh +0 -0
  236. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/urls.py +0 -0
  237. {fractal_server-2.6.3 → fractal_server-2.7.0}/fractal_server/zip_tools.py +0 -0
@@ -1,34 +1,30 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fractal-server
3
- Version: 2.6.3
3
+ Version: 2.7.0
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
7
7
  Author: Tommaso Comparin
8
8
  Author-email: tommaso.comparin@exact-lab.it
9
- Requires-Python: >=3.9,<4.0
9
+ Requires-Python: >=3.10,<4.0
10
10
  Classifier: License :: OSI Approved :: BSD License
11
11
  Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.9
13
12
  Classifier: Programming Language :: Python :: 3.10
14
13
  Classifier: Programming Language :: Python :: 3.11
15
14
  Classifier: Programming Language :: Python :: 3.12
16
15
  Provides-Extra: gunicorn
17
- Provides-Extra: postgres
18
16
  Provides-Extra: postgres-psycopg-binary
19
17
  Requires-Dist: aiosqlite (>=0.19.0,<0.20.0)
20
18
  Requires-Dist: alembic (>=1.13.1,<2.0.0)
21
- Requires-Dist: asyncpg (>=0.29.0,<0.30.0) ; extra == "postgres"
22
19
  Requires-Dist: bcrypt (==4.0.1)
23
20
  Requires-Dist: cloudpickle (>=3.0.0,<3.1.0)
24
21
  Requires-Dist: clusterfutures (>=0.5,<0.6)
25
22
  Requires-Dist: fabric (>=3.2.2,<4.0.0)
26
- Requires-Dist: fastapi (>=0.112.0,<0.113.0)
23
+ Requires-Dist: fastapi (>=0.115.0,<0.116.0)
27
24
  Requires-Dist: fastapi-users[oauth] (>=12.1.0,<13.0.0)
28
25
  Requires-Dist: gunicorn (>=21.2,<23.0) ; extra == "gunicorn"
29
26
  Requires-Dist: packaging (>=23.2,<24.0)
30
27
  Requires-Dist: psutil (>=5.9.8,<6.0.0)
31
- Requires-Dist: psycopg2 (>=2.9.5,<3.0.0) ; extra == "postgres"
32
28
  Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0) ; extra == "postgres-psycopg-binary"
33
29
  Requires-Dist: pydantic (>=1.10.8,<2)
34
30
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.7.0"
@@ -57,7 +57,7 @@ set_db_parser.add_argument(
57
57
  )
58
58
 
59
59
  # fractalctl update-db-data
60
- subparsers.add_parser(
60
+ update_db_data_parser = subparsers.add_parser(
61
61
  "update-db-data",
62
62
  description="Apply data-migration script to an existing database.",
63
63
  )
@@ -1,6 +1,12 @@
1
+ from datetime import datetime
2
+
3
+ from sqlalchemy import Column
4
+ from sqlalchemy.types import DateTime
1
5
  from sqlmodel import Field
2
6
  from sqlmodel import SQLModel
3
7
 
8
+ from fractal_server.utils import get_timestamp
9
+
4
10
 
5
11
  class LinkUserGroup(SQLModel, table=True):
6
12
  """
@@ -9,3 +15,8 @@ class LinkUserGroup(SQLModel, table=True):
9
15
 
10
16
  group_id: int = Field(foreign_key="usergroup.id", primary_key=True)
11
17
  user_id: int = Field(foreign_key="user_oauth.id", primary_key=True)
18
+
19
+ timestamp_created: datetime = Field(
20
+ default_factory=get_timestamp,
21
+ sa_column=Column(DateTime(timezone=True), nullable=False),
22
+ )
@@ -6,6 +6,7 @@ from .collection_state import CollectionStateV2
6
6
  from .dataset import DatasetV2
7
7
  from .job import JobV2
8
8
  from .project import ProjectV2
9
+ from .task import TaskGroupV2
9
10
  from .task import TaskV2
10
11
  from .workflow import WorkflowV2
11
12
  from .workflowtask import WorkflowTaskV2
@@ -16,6 +17,7 @@ __all__ = [
16
17
  "JobV2",
17
18
  "ProjectV2",
18
19
  "CollectionStateV2",
20
+ "TaskGroupV2",
19
21
  "TaskV2",
20
22
  "WorkflowTaskV2",
21
23
  "WorkflowV2",
@@ -14,6 +14,7 @@ from ....utils import get_timestamp
14
14
  class CollectionStateV2(SQLModel, table=True):
15
15
 
16
16
  id: Optional[int] = Field(default=None, primary_key=True)
17
+ taskgroupv2_id: Optional[int] = Field(foreign_key="taskgroupv2.id")
17
18
  data: dict[str, Any] = Field(sa_column=Column(JSON), default={})
18
19
  timestamp: datetime = Field(
19
20
  default_factory=get_timestamp,
@@ -0,0 +1,106 @@
1
+ from datetime import datetime
2
+ from typing import Any
3
+ from typing import Optional
4
+
5
+ from pydantic import HttpUrl
6
+ from sqlalchemy import Column
7
+ from sqlalchemy.types import DateTime
8
+ from sqlalchemy.types import JSON
9
+ from sqlmodel import Field
10
+ from sqlmodel import Relationship
11
+ from sqlmodel import SQLModel
12
+
13
+ from fractal_server.utils import get_timestamp
14
+
15
+
16
+ class TaskV2(SQLModel, table=True):
17
+ id: Optional[int] = Field(default=None, primary_key=True)
18
+ name: str
19
+
20
+ type: str
21
+ command_non_parallel: Optional[str] = None
22
+ command_parallel: Optional[str] = None
23
+ source: Optional[str] = None
24
+
25
+ meta_non_parallel: dict[str, Any] = Field(
26
+ sa_column=Column(JSON, server_default="{}", default={}, nullable=False)
27
+ )
28
+ meta_parallel: dict[str, Any] = Field(
29
+ sa_column=Column(JSON, server_default="{}", default={}, nullable=False)
30
+ )
31
+
32
+ owner: Optional[str] = None
33
+ version: Optional[str] = None
34
+ args_schema_non_parallel: Optional[dict[str, Any]] = Field(
35
+ sa_column=Column(JSON), default=None
36
+ )
37
+ args_schema_parallel: Optional[dict[str, Any]] = Field(
38
+ sa_column=Column(JSON), default=None
39
+ )
40
+ args_schema_version: Optional[str]
41
+ docs_info: Optional[str] = None
42
+ docs_link: Optional[HttpUrl] = None
43
+
44
+ input_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
45
+ output_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
46
+
47
+ taskgroupv2_id: Optional[int] = Field(foreign_key="taskgroupv2.id")
48
+
49
+ category: Optional[str] = None
50
+ modality: Optional[str] = None
51
+ authors: Optional[str] = None
52
+ tags: list[str] = Field(
53
+ sa_column=Column(JSON, server_default="[]", nullable=False)
54
+ )
55
+
56
+
57
+ class TaskGroupV2(SQLModel, table=True):
58
+ id: Optional[int] = Field(default=None, primary_key=True)
59
+ task_list: list[TaskV2] = Relationship(
60
+ sa_relationship_kwargs=dict(
61
+ lazy="selectin", cascade="all, delete-orphan"
62
+ ),
63
+ )
64
+
65
+ user_id: int = Field(foreign_key="user_oauth.id")
66
+ user_group_id: Optional[int] = Field(foreign_key="usergroup.id")
67
+
68
+ origin: str
69
+ pkg_name: str
70
+ version: Optional[str] = None
71
+ python_version: Optional[str] = None
72
+ path: Optional[str] = None
73
+ venv_path: Optional[str] = None
74
+ wheel_path: Optional[str] = None
75
+ pip_extras: Optional[str] = None
76
+ pinned_package_versions: dict[str, str] = Field(
77
+ sa_column=Column(
78
+ JSON,
79
+ server_default="{}",
80
+ default={},
81
+ nullable=True,
82
+ ),
83
+ )
84
+
85
+ active: bool = True
86
+ timestamp_created: datetime = Field(
87
+ default_factory=get_timestamp,
88
+ sa_column=Column(DateTime(timezone=True), nullable=False),
89
+ )
90
+
91
+ @property
92
+ def pip_install_string(self) -> str:
93
+ """
94
+ Prepare string to be used in `python -m pip install`.
95
+ """
96
+ extras = f"[{self.pip_extras}]" if self.pip_extras is not None else ""
97
+
98
+ if self.wheel_path is not None:
99
+ return f"{self.wheel_path}{extras}"
100
+ else:
101
+ if self.version is None:
102
+ raise ValueError(
103
+ "Cannot run `pip_install_string` with "
104
+ f"{self.pkg_name=}, {self.wheel_path=}, {self.version=}."
105
+ )
106
+ return f"{self.pkg_name}{extras}=={self.version}"
@@ -0,0 +1,16 @@
1
+ """
2
+ `admin/v2` module
3
+ """
4
+ from fastapi import APIRouter
5
+
6
+ from .job import router as job_router
7
+ from .project import router as project_router
8
+ from .task import router as task_router
9
+ from .task_group import router as task_group_router
10
+
11
+ router_admin_v2 = APIRouter()
12
+
13
+ router_admin_v2.include_router(job_router, prefix="/job")
14
+ router_admin_v2.include_router(project_router, prefix="/project")
15
+ router_admin_v2.include_router(task_router, prefix="/task")
16
+ router_admin_v2.include_router(task_group_router, prefix="/task-group")
@@ -1,10 +1,6 @@
1
- """
2
- Definition of `/admin` routes.
3
- """
4
1
  from datetime import datetime
5
2
  from datetime import timezone
6
3
  from pathlib import Path
7
- from typing import Literal
8
4
  from typing import Optional
9
5
 
10
6
  from fastapi import APIRouter
@@ -13,33 +9,26 @@ from fastapi import HTTPException
13
9
  from fastapi import Response
14
10
  from fastapi import status
15
11
  from fastapi.responses import StreamingResponse
16
- from pydantic import BaseModel
17
- from pydantic import EmailStr
18
- from pydantic import Field
19
12
  from sqlmodel import select
20
13
 
21
- from ....config import get_settings
22
- from ....syringe import Inject
23
- from ....utils import get_timestamp
24
- from ....zip_tools import _zip_folder_to_byte_stream_iterator
25
- from ...db import AsyncSession
26
- from ...db import get_async_db
27
- from ...models.v2 import JobV2
28
- from ...models.v2 import ProjectV2
29
- from ...models.v2 import TaskV2
30
- from ...models.v2 import WorkflowTaskV2
31
- from ...models.v2 import WorkflowV2
32
- from ...runner.filenames import WORKFLOW_LOG_FILENAME
33
- from ...schemas.v2 import JobReadV2
34
- from ...schemas.v2 import JobStatusTypeV2
35
- from ...schemas.v2 import JobUpdateV2
36
- from ...schemas.v2 import ProjectReadV2
37
- from ..aux._job import _write_shutdown_file
38
- from ..aux._runner import _check_shutdown_is_supported
14
+ from fractal_server.app.db import AsyncSession
15
+ from fractal_server.app.db import get_async_db
39
16
  from fractal_server.app.models import UserOAuth
17
+ from fractal_server.app.models.v2 import JobV2
18
+ from fractal_server.app.models.v2 import ProjectV2
40
19
  from fractal_server.app.routes.auth import current_active_superuser
20
+ from fractal_server.app.routes.aux._job import _write_shutdown_file
21
+ from fractal_server.app.routes.aux._runner import _check_shutdown_is_supported
22
+ from fractal_server.app.runner.filenames import WORKFLOW_LOG_FILENAME
23
+ from fractal_server.app.schemas.v2 import JobReadV2
24
+ from fractal_server.app.schemas.v2 import JobStatusTypeV2
25
+ from fractal_server.app.schemas.v2 import JobUpdateV2
26
+ from fractal_server.config import get_settings
27
+ from fractal_server.syringe import Inject
28
+ from fractal_server.utils import get_timestamp
29
+ from fractal_server.zip_tools import _zip_folder_to_byte_stream_iterator
41
30
 
42
- router_admin_v2 = APIRouter()
31
+ router = APIRouter()
43
32
 
44
33
 
45
34
  def _convert_to_db_timestamp(dt: datetime) -> datetime:
@@ -59,36 +48,7 @@ def _convert_to_db_timestamp(dt: datetime) -> datetime:
59
48
  return _dt
60
49
 
61
50
 
62
- @router_admin_v2.get("/project/", response_model=list[ProjectReadV2])
63
- async def view_project(
64
- id: Optional[int] = None,
65
- user_id: Optional[int] = None,
66
- user: UserOAuth = Depends(current_active_superuser),
67
- db: AsyncSession = Depends(get_async_db),
68
- ) -> list[ProjectReadV2]:
69
- """
70
- Query `ProjectV2` table.
71
-
72
- Args:
73
- id: If not `None`, select a given `project.id`.
74
- user_id: If not `None`, select a given `project.user_id`.
75
- """
76
-
77
- stm = select(ProjectV2)
78
-
79
- if id is not None:
80
- stm = stm.where(ProjectV2.id == id)
81
- if user_id is not None:
82
- stm = stm.where(ProjectV2.user_list.any(UserOAuth.id == user_id))
83
-
84
- res = await db.execute(stm)
85
- project_list = res.scalars().all()
86
- await db.close()
87
-
88
- return project_list
89
-
90
-
91
- @router_admin_v2.get("/job/", response_model=list[JobReadV2])
51
+ @router.get("/", response_model=list[JobReadV2])
92
52
  async def view_job(
93
53
  id: Optional[int] = None,
94
54
  user_id: Optional[int] = None,
@@ -164,7 +124,7 @@ async def view_job(
164
124
  return job_list
165
125
 
166
126
 
167
- @router_admin_v2.get("/job/{job_id}/", response_model=JobReadV2)
127
+ @router.get("/{job_id}/", response_model=JobReadV2)
168
128
  async def view_single_job(
169
129
  job_id: int = None,
170
130
  show_tmp_logs: bool = False,
@@ -190,10 +150,7 @@ async def view_single_job(
190
150
  return job
191
151
 
192
152
 
193
- @router_admin_v2.patch(
194
- "/job/{job_id}/",
195
- response_model=JobReadV2,
196
- )
153
+ @router.patch("/{job_id}/", response_model=JobReadV2)
197
154
  async def update_job(
198
155
  job_update: JobUpdateV2,
199
156
  job_id: int,
@@ -227,7 +184,7 @@ async def update_job(
227
184
  return job
228
185
 
229
186
 
230
- @router_admin_v2.get("/job/{job_id}/stop/", status_code=202)
187
+ @router.get("/{job_id}/stop/", status_code=202)
231
188
  async def stop_job(
232
189
  job_id: int,
233
190
  user: UserOAuth = Depends(current_active_superuser),
@@ -251,10 +208,7 @@ async def stop_job(
251
208
  return Response(status_code=status.HTTP_202_ACCEPTED)
252
209
 
253
210
 
254
- @router_admin_v2.get(
255
- "/job/{job_id}/download/",
256
- response_class=StreamingResponse,
257
- )
211
+ @router.get("/{job_id}/download/", response_class=StreamingResponse)
258
212
  async def download_job_logs(
259
213
  job_id: int,
260
214
  user: UserOAuth = Depends(current_active_superuser),
@@ -278,128 +232,3 @@ async def download_job_logs(
278
232
  media_type="application/x-zip-compressed",
279
233
  headers={"Content-Disposition": f"attachment;filename={zip_filename}"},
280
234
  )
281
-
282
-
283
- class TaskV2Minimal(BaseModel):
284
-
285
- id: int
286
- name: str
287
- type: str
288
- command_non_parallel: Optional[str]
289
- command_parallel: Optional[str]
290
- source: str
291
- owner: Optional[str]
292
- version: Optional[str]
293
-
294
-
295
- class ProjectUser(BaseModel):
296
-
297
- id: int
298
- email: EmailStr
299
-
300
-
301
- class TaskV2Relationship(BaseModel):
302
-
303
- workflow_id: int
304
- workflow_name: str
305
- project_id: int
306
- project_name: str
307
- project_users: list[ProjectUser] = Field(default_factory=list)
308
-
309
-
310
- class TaskV2Info(BaseModel):
311
-
312
- task: TaskV2Minimal
313
- relationships: list[TaskV2Relationship]
314
-
315
-
316
- @router_admin_v2.get("/task/", response_model=list[TaskV2Info])
317
- async def query_tasks(
318
- id: Optional[int] = None,
319
- source: Optional[str] = None,
320
- version: Optional[str] = None,
321
- name: Optional[str] = None,
322
- owner: Optional[str] = None,
323
- kind: Optional[Literal["common", "users"]] = None,
324
- max_number_of_results: int = 25,
325
- user: UserOAuth = Depends(current_active_superuser),
326
- db: AsyncSession = Depends(get_async_db),
327
- ) -> list[TaskV2Info]:
328
- """
329
- Query `TaskV2` table and get informations about related items
330
- (WorkflowV2s and ProjectV2s)
331
-
332
- Args:
333
- id: If not `None`, query for matching `task.id`.
334
- source: If not `None`, query for contained case insensitive
335
- `task.source`.
336
- version: If not `None`, query for matching `task.version`.
337
- name: If not `None`, query for contained case insensitive `task.name`.
338
- owner: If not `None`, query for matching `task.owner`.
339
- kind: If not `None`, query for TaskV2s that have (`users`) or don't
340
- have (`common`) a `task.owner`.
341
- max_number_of_results: The maximum length of the response.
342
- """
343
-
344
- stm = select(TaskV2)
345
-
346
- if id is not None:
347
- stm = stm.where(TaskV2.id == id)
348
- if source is not None:
349
- stm = stm.where(TaskV2.source.icontains(source))
350
- if version is not None:
351
- stm = stm.where(TaskV2.version == version)
352
- if name is not None:
353
- stm = stm.where(TaskV2.name.icontains(name))
354
- if owner is not None:
355
- stm = stm.where(TaskV2.owner == owner)
356
-
357
- if kind == "common":
358
- stm = stm.where(TaskV2.owner == None) # noqa E711
359
- elif kind == "users":
360
- stm = stm.where(TaskV2.owner != None) # noqa E711
361
-
362
- res = await db.execute(stm)
363
- task_list = res.scalars().all()
364
- if len(task_list) > max_number_of_results:
365
- await db.close()
366
- raise HTTPException(
367
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
368
- detail=(
369
- f"Too many Tasks ({len(task_list)} > {max_number_of_results})."
370
- " Please add more query filters."
371
- ),
372
- )
373
-
374
- task_info_list = []
375
-
376
- for task in task_list:
377
- stm = (
378
- select(WorkflowV2)
379
- .join(WorkflowTaskV2)
380
- .where(WorkflowTaskV2.workflow_id == WorkflowV2.id)
381
- .where(WorkflowTaskV2.task_id == task.id)
382
- )
383
- res = await db.execute(stm)
384
- wf_list = res.scalars().all()
385
-
386
- task_info_list.append(
387
- dict(
388
- task=task.model_dump(),
389
- relationships=[
390
- dict(
391
- workflow_id=workflow.id,
392
- workflow_name=workflow.name,
393
- project_id=workflow.project.id,
394
- project_name=workflow.project.name,
395
- project_users=[
396
- dict(id=user.id, email=user.email)
397
- for user in workflow.project.user_list
398
- ],
399
- )
400
- for workflow in wf_list
401
- ],
402
- )
403
- )
404
-
405
- return task_info_list
@@ -0,0 +1,43 @@
1
+ from typing import Optional
2
+
3
+ from fastapi import APIRouter
4
+ from fastapi import Depends
5
+ from sqlmodel import select
6
+
7
+ from fractal_server.app.db import AsyncSession
8
+ from fractal_server.app.db import get_async_db
9
+ from fractal_server.app.models import UserOAuth
10
+ from fractal_server.app.models.v2 import ProjectV2
11
+ from fractal_server.app.routes.auth import current_active_superuser
12
+ from fractal_server.app.schemas.v2 import ProjectReadV2
13
+
14
+ router = APIRouter()
15
+
16
+
17
+ @router.get("/", response_model=list[ProjectReadV2])
18
+ async def view_project(
19
+ id: Optional[int] = None,
20
+ user_id: Optional[int] = None,
21
+ user: UserOAuth = Depends(current_active_superuser),
22
+ db: AsyncSession = Depends(get_async_db),
23
+ ) -> list[ProjectReadV2]:
24
+ """
25
+ Query `ProjectV2` table.
26
+
27
+ Args:
28
+ id: If not `None`, select a given `project.id`.
29
+ user_id: If not `None`, select a given `project.user_id`.
30
+ """
31
+
32
+ stm = select(ProjectV2)
33
+
34
+ if id is not None:
35
+ stm = stm.where(ProjectV2.id == id)
36
+ if user_id is not None:
37
+ stm = stm.where(ProjectV2.user_list.any(UserOAuth.id == user_id))
38
+
39
+ res = await db.execute(stm)
40
+ project_list = res.scalars().all()
41
+ await db.close()
42
+
43
+ return project_list
@@ -0,0 +1,133 @@
1
+ from typing import Optional
2
+
3
+ from fastapi import APIRouter
4
+ from fastapi import Depends
5
+ from fastapi import HTTPException
6
+ from fastapi import status
7
+ from pydantic import BaseModel
8
+ from pydantic import EmailStr
9
+ from pydantic import Field
10
+ from sqlmodel import select
11
+
12
+ from fractal_server.app.db import AsyncSession
13
+ from fractal_server.app.db import get_async_db
14
+ from fractal_server.app.models import UserOAuth
15
+ from fractal_server.app.models.v2 import TaskV2
16
+ from fractal_server.app.models.v2 import WorkflowTaskV2
17
+ from fractal_server.app.models.v2 import WorkflowV2
18
+ from fractal_server.app.routes.auth import current_active_superuser
19
+
20
+ router = APIRouter()
21
+
22
+
23
+ class TaskV2Minimal(BaseModel):
24
+
25
+ id: int
26
+ name: str
27
+ type: str
28
+ taskgroupv2_id: int
29
+ command_non_parallel: Optional[str] = None
30
+ command_parallel: Optional[str]
31
+ source: Optional[str] = None
32
+ version: Optional[str] = None
33
+
34
+
35
+ class ProjectUser(BaseModel):
36
+
37
+ id: int
38
+ email: EmailStr
39
+
40
+
41
+ class TaskV2Relationship(BaseModel):
42
+
43
+ workflow_id: int
44
+ workflow_name: str
45
+ project_id: int
46
+ project_name: str
47
+ project_users: list[ProjectUser] = Field(default_factory=list)
48
+
49
+
50
+ class TaskV2Info(BaseModel):
51
+
52
+ task: TaskV2Minimal
53
+ relationships: list[TaskV2Relationship]
54
+
55
+
56
+ @router.get("/", response_model=list[TaskV2Info])
57
+ async def query_tasks(
58
+ id: Optional[int] = None,
59
+ source: Optional[str] = None,
60
+ version: Optional[str] = None,
61
+ name: Optional[str] = None,
62
+ max_number_of_results: int = 25,
63
+ user: UserOAuth = Depends(current_active_superuser),
64
+ db: AsyncSession = Depends(get_async_db),
65
+ ) -> list[TaskV2Info]:
66
+ """
67
+ Query `TaskV2` table and get informations about related items
68
+ (WorkflowV2s and ProjectV2s)
69
+
70
+ Args:
71
+ id: If not `None`, query for matching `task.id`.
72
+ source: If not `None`, query for contained case insensitive
73
+ `task.source`.
74
+ version: If not `None`, query for matching `task.version`.
75
+ name: If not `None`, query for contained case insensitive `task.name`.
76
+ max_number_of_results: The maximum length of the response.
77
+ """
78
+
79
+ stm = select(TaskV2)
80
+
81
+ if id is not None:
82
+ stm = stm.where(TaskV2.id == id)
83
+ if source is not None:
84
+ stm = stm.where(TaskV2.source.icontains(source))
85
+ if version is not None:
86
+ stm = stm.where(TaskV2.version == version)
87
+ if name is not None:
88
+ stm = stm.where(TaskV2.name.icontains(name))
89
+
90
+ res = await db.execute(stm)
91
+ task_list = res.scalars().all()
92
+ if len(task_list) > max_number_of_results:
93
+ await db.close()
94
+ raise HTTPException(
95
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
96
+ detail=(
97
+ f"Too many Tasks ({len(task_list)} > {max_number_of_results})."
98
+ " Please add more query filters."
99
+ ),
100
+ )
101
+
102
+ task_info_list = []
103
+
104
+ for task in task_list:
105
+ stm = (
106
+ select(WorkflowV2)
107
+ .join(WorkflowTaskV2)
108
+ .where(WorkflowTaskV2.workflow_id == WorkflowV2.id)
109
+ .where(WorkflowTaskV2.task_id == task.id)
110
+ )
111
+ res = await db.execute(stm)
112
+ wf_list = res.scalars().all()
113
+
114
+ task_info_list.append(
115
+ dict(
116
+ task=task.model_dump(),
117
+ relationships=[
118
+ dict(
119
+ workflow_id=workflow.id,
120
+ workflow_name=workflow.name,
121
+ project_id=workflow.project.id,
122
+ project_name=workflow.project.name,
123
+ project_users=[
124
+ dict(id=user.id, email=user.email)
125
+ for user in workflow.project.user_list
126
+ ],
127
+ )
128
+ for workflow in wf_list
129
+ ],
130
+ )
131
+ )
132
+
133
+ return task_info_list