fractal-server 2.18.1__tar.gz → 2.18.3__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 (276) hide show
  1. {fractal_server-2.18.1 → fractal_server-2.18.3}/PKG-INFO +21 -28
  2. fractal_server-2.18.3/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/task_group.py +0 -2
  4. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/job.py +9 -0
  5. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/_aux_functions_history.py +13 -5
  6. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/history.py +4 -2
  7. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/job.py +12 -5
  8. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/oauth.py +27 -1
  9. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/task_group.py +0 -3
  10. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/config/_oauth.py +6 -0
  11. fractal_server-2.18.3/fractal_server/migrations/versions/068496367952_drop_taskgroup_venv_size_and_files_.py +48 -0
  12. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/config/_slurm.py +2 -0
  13. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/call_command_wrapper.py +13 -0
  14. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/base_slurm_runner.py +7 -3
  15. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/slurm_config.py +20 -2
  16. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/collect.py +2 -19
  17. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/collect_pixi.py +2 -12
  18. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/reactivate.py +1 -1
  19. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/collect.py +2 -19
  20. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/collect_pixi.py +2 -12
  21. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/reactivate.py +1 -1
  22. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -6
  23. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/utils_pixi.py +0 -4
  24. {fractal_server-2.18.1 → fractal_server-2.18.3}/pyproject.toml +44 -47
  25. fractal_server-2.18.1/LICENSE +0 -29
  26. fractal_server-2.18.1/fractal_server/__init__.py +0 -1
  27. fractal_server-2.18.1/fractal_server/data_migrations/README.md +0 -6
  28. fractal_server-2.18.1/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -12
  29. {fractal_server-2.18.1 → fractal_server-2.18.3}/README.md +0 -0
  30. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/__main__.py +0 -0
  31. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/alembic.ini +0 -0
  32. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/__init__.py +0 -0
  33. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/db/__init__.py +0 -0
  34. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/__init__.py +0 -0
  35. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/linkusergroup.py +0 -0
  36. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/linkuserproject.py +0 -0
  37. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/security.py +0 -0
  38. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/__init__.py +0 -0
  39. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/accounting.py +0 -0
  40. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/dataset.py +0 -0
  41. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/history.py +0 -0
  42. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/job.py +0 -0
  43. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/profile.py +0 -0
  44. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/project.py +0 -0
  45. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/resource.py +0 -0
  46. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/task.py +0 -0
  47. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/workflow.py +0 -0
  48. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/models/v2/workflowtask.py +0 -0
  49. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/__init__.py +0 -0
  50. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/__init__.py +0 -0
  51. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  52. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/_aux_functions.py +0 -0
  53. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  54. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  55. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/profile.py +0 -0
  56. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/resource.py +0 -0
  57. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/sharing.py +0 -0
  58. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/task.py +0 -0
  59. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  60. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  61. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/__init__.py +0 -0
  62. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  63. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  64. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/_aux_functions_sharing.py +0 -0
  65. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  66. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  67. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  68. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
  69. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  70. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/images.py +0 -0
  71. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
  72. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/project.py +0 -0
  73. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/sharing.py +0 -0
  74. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  75. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/submit.py +0 -0
  76. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/task.py +0 -0
  77. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  78. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  79. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
  80. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  81. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  82. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
  83. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  84. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  85. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  86. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/__init__.py +0 -0
  87. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  88. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/current_user.py +0 -0
  89. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/group.py +0 -0
  90. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/login.py +0 -0
  91. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/register.py +0 -0
  92. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/router.py +0 -0
  93. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/users.py +0 -0
  94. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/auth/viewer_paths.py +0 -0
  95. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/aux/__init__.py +0 -0
  96. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/aux/_job.py +0 -0
  97. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/aux/_runner.py +0 -0
  98. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/aux/validate_user_profile.py +0 -0
  99. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/routes/pagination.py +0 -0
  100. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/__init__.py +0 -0
  101. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/user.py +0 -0
  102. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/user_group.py +0 -0
  103. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/__init__.py +0 -0
  104. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/accounting.py +0 -0
  105. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/dataset.py +0 -0
  106. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/dumps.py +0 -0
  107. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/history.py +0 -0
  108. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/job.py +0 -0
  109. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/manifest.py +0 -0
  110. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/profile.py +0 -0
  111. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/project.py +0 -0
  112. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/resource.py +0 -0
  113. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/sharing.py +0 -0
  114. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  115. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/task.py +0 -0
  116. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  117. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/workflow.py +0 -0
  118. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  119. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/security/__init__.py +0 -0
  120. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/security/signup_email.py +0 -0
  121. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/app/shutdown.py +0 -0
  122. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/config/__init__.py +0 -0
  123. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/config/_data.py +0 -0
  124. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/config/_database.py +0 -0
  125. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/config/_email.py +0 -0
  126. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/config/_main.py +0 -0
  127. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/config/_settings_config.py +0 -0
  128. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/data_migrations/tools.py +0 -0
  129. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/exceptions.py +0 -0
  130. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/gunicorn_fractal.py +0 -0
  131. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/images/__init__.py +0 -0
  132. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/images/models.py +0 -0
  133. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/images/status_tools.py +0 -0
  134. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/images/tools.py +0 -0
  135. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/logger.py +0 -0
  136. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/main.py +0 -0
  137. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/env.py +0 -0
  138. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/naming_convention.py +0 -0
  139. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  140. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  141. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
  142. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  143. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
  144. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  145. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  146. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/40d6d6511b20_add_index_to_history_models.py +0 -0
  147. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +0 -0
  148. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  149. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/49d0856e9569_drop_table.py +0 -0
  150. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  151. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  152. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  153. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  154. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  155. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  156. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  157. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +0 -0
  158. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/7910eed4cf97_user_project_dirs_and_usergroup_viewer_.py +0 -0
  159. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
  160. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +0 -0
  161. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  162. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/88270f589c9b_add_prevent_new_submissions.py +0 -0
  163. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  164. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  165. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  166. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
  167. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  168. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
  169. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  170. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  171. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  172. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  173. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  174. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  175. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  176. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
  177. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
  178. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/b7477cc98f45_2_18_1.py +0 -0
  179. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/bc0e8b3327a7_project_sharing.py +0 -0
  180. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  181. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +0 -0
  182. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  183. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  184. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  185. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  186. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/e0e717ae2f26_delete_linkuserproject_ondelete_project.py +0 -0
  187. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  188. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  189. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  190. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/f0702066b007_one_submitted_job_per_dataset.py +0 -0
  191. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  192. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  193. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  194. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/py.typed +0 -0
  195. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/__init__.py +0 -0
  196. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/components.py +0 -0
  197. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/config/__init__.py +0 -0
  198. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/config/_local.py +0 -0
  199. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/config/slurm_mem_to_MB.py +0 -0
  200. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/exceptions.py +0 -0
  201. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/__init__.py +0 -0
  202. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/base_runner.py +0 -0
  203. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/local/__init__.py +0 -0
  204. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/local/get_local_config.py +0 -0
  205. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/local/runner.py +0 -0
  206. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/__init__.py +0 -0
  207. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/_batching.py +0 -0
  208. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/_job_states.py +0 -0
  209. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/get_slurm_config.py +0 -0
  210. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/remote.py +0 -0
  211. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  212. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_ssh/__init__.py +0 -0
  213. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  214. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_ssh/runner.py +0 -0
  215. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_ssh/tar_commands.py +0 -0
  216. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_sudo/__init__.py +0 -0
  217. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  218. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/executors/slurm_sudo/runner.py +0 -0
  219. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/filenames.py +0 -0
  220. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/set_start_and_last_task_index.py +0 -0
  221. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/task_files.py +0 -0
  222. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/__init__.py +0 -0
  223. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/_local.py +0 -0
  224. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/_slurm_ssh.py +0 -0
  225. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/_slurm_sudo.py +0 -0
  226. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/db_tools.py +0 -0
  227. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/deduplicate_list.py +0 -0
  228. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/merge_outputs.py +0 -0
  229. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/runner.py +0 -0
  230. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/runner_functions.py +0 -0
  231. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/submit_workflow.py +0 -0
  232. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/v2/task_interface.py +0 -0
  233. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/runner/versions.py +0 -0
  234. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/ssh/__init__.py +0 -0
  235. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/ssh/_fabric.py +0 -0
  236. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/string_tools.py +0 -0
  237. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/syringe.py +0 -0
  238. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/__init__.py +0 -0
  239. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/config/__init__.py +0 -0
  240. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/config/_pixi.py +0 -0
  241. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/config/_python.py +0 -0
  242. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/utils.py +0 -0
  243. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/__init__.py +0 -0
  244. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/__init__.py +0 -0
  245. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/_utils.py +0 -0
  246. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  247. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
  248. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/delete.py +0 -0
  249. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
  250. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  251. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -0
  252. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  253. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  254. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
  255. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/delete.py +0 -0
  256. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +0 -0
  257. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  258. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  259. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  260. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  261. /fractal_server-2.18.1/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh → /fractal_server-2.18.3/fractal_server/tasks/v2/templates/5_pip_install_from_freeze.sh +0 -0
  262. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
  263. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
  264. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/utils_background.py +0 -0
  265. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/utils_database.py +0 -0
  266. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  267. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  268. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/tasks/v2/utils_templates.py +0 -0
  269. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/types/__init__.py +0 -0
  270. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/types/validators/__init__.py +0 -0
  271. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/types/validators/_common_validators.py +0 -0
  272. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/types/validators/_filter_validators.py +0 -0
  273. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
  274. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/urls.py +0 -0
  275. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/utils.py +0 -0
  276. {fractal_server-2.18.1 → fractal_server-2.18.3}/fractal_server/zip_tools.py +0 -0
@@ -1,35 +1,29 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fractal-server
3
- Version: 2.18.1
3
+ Version: 2.18.3
4
4
  Summary: Backend component of the Fractal analytics platform
5
+ Author: Tommaso Comparin, Marco Franzon, Yuri Chiucconi, Jacopo Nespolo
6
+ Author-email: Tommaso Comparin <tommaso.comparin@exact-lab.it>, Marco Franzon <marco.franzon@exact-lab.it>, Yuri Chiucconi <yuri.chiucconi@exact-lab.it>, Jacopo Nespolo <jacopo.nespolo@exact-lab.it>
5
7
  License-Expression: BSD-3-Clause
6
- License-File: LICENSE
7
- Author: Tommaso Comparin
8
- Author-email: tommaso.comparin@exact-lab.it
9
- Requires-Python: >=3.11,<3.15
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Classifier: Programming Language :: Python :: 3.13
14
- Classifier: Programming Language :: Python :: 3.14
15
- Requires-Dist: alembic (>=1.13.1,<2.0.0)
16
- Requires-Dist: fabric (>=3.2.2,<3.3.0)
17
- Requires-Dist: fastapi (>=0.120.0,<0.121.0)
18
- Requires-Dist: fastapi-users[oauth] (>=15,<16)
19
- Requires-Dist: gunicorn (>=23.0,<24.0)
20
- Requires-Dist: packaging (>=25.0.0,<26.0.0)
21
- Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0)
22
- Requires-Dist: pydantic (>=2.12.0,<2.13.0)
23
- Requires-Dist: pydantic-settings (==2.11.0)
24
- Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
25
- Requires-Dist: sqlmodel (==0.0.27)
26
- Requires-Dist: tomli_w (>=1.2.0,<1.3.0)
27
- Requires-Dist: uvicorn (>=0.38.0,<0.39.0)
28
- Requires-Dist: uvicorn-worker (==0.4.0)
29
- Project-URL: Documentation, https://fractal-analytics-platform.github.io/fractal-server
30
- Project-URL: Homepage, https://github.com/fractal-analytics-platform/fractal-server
31
- Project-URL: Repository, https://github.com/fractal-analytics-platform/fractal-server
8
+ Requires-Dist: fastapi>=0.120.0,<0.121.0
9
+ Requires-Dist: sqlmodel==0.0.27
10
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.23,<2.1
11
+ Requires-Dist: fastapi-users[oauth]>=15,<16
12
+ Requires-Dist: alembic>=1.13.1,<2.0.0
13
+ Requires-Dist: uvicorn>=0.38.0,<0.39.0
14
+ Requires-Dist: uvicorn-worker==0.4.0
15
+ Requires-Dist: pydantic>=2.12.0,<2.13.0
16
+ Requires-Dist: pydantic-settings==2.11.0
17
+ Requires-Dist: packaging>=25.0.0,<26.0.0
18
+ Requires-Dist: fabric>=3.2.2,<3.3.0
19
+ Requires-Dist: gunicorn>=23.0,<24.0
20
+ Requires-Dist: psycopg[binary]>=3.1.0,<4.0.0
21
+ Requires-Dist: tomli-w>=1.2.0,<1.3.0
22
+ Requires-Python: >=3.11, <3.15
32
23
  Project-URL: changelog, https://github.com/fractal-analytics-platform/fractal-server/blob/main/CHANGELOG.md
24
+ Project-URL: documentation, https://fractal-analytics-platform.github.io/fractal-server
25
+ Project-URL: homepage, https://github.com/fractal-analytics-platform/fractal-server
26
+ Project-URL: repository, https://github.com/fractal-analytics-platform/fractal-server
33
27
  Description-Content-Type: text/markdown
34
28
 
35
29
  # Fractal Server
@@ -63,4 +57,3 @@ See https://fractal-analytics-platform.github.io/fractal-server.
63
57
  Fractal was conceived in the Liberali Lab at the Friedrich Miescher Institute for Biomedical Research and in the Pelkmans Lab at the University of Zurich by [@jluethi](https://github.com/jluethi) and [@gusqgm](https://github.com/gusqgm). The Fractal project is now developed at the [BioVisionCenter](https://www.biovisioncenter.uzh.ch/en.html) at the University of Zurich and the project lead is with [@jluethi](https://github.com/jluethi). The core development is done under contract by [eXact lab S.r.l.](https://www.exact-lab.it).
64
58
 
65
59
  Unless otherwise specified, Fractal components are released under the BSD 3-Clause License, and copyright is with the BioVisionCenter at the University of Zurich.
66
-
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.18.3"
@@ -71,8 +71,6 @@ class TaskGroupV2(SQLModel, table=True):
71
71
  )
72
72
  env_info: str | None = None
73
73
  venv_path: str | None = None
74
- venv_size_in_kB: int | None = None
75
- venv_file_number: int | None = None
76
74
 
77
75
  active: bool = True
78
76
  timestamp_created: datetime = Field(
@@ -17,6 +17,7 @@ from fractal_server.app.models import UserOAuth
17
17
  from fractal_server.app.models.v2 import HistoryRun
18
18
  from fractal_server.app.models.v2 import HistoryUnit
19
19
  from fractal_server.app.models.v2 import JobV2
20
+ from fractal_server.app.models.v2.project import ProjectV2
20
21
  from fractal_server.app.routes.auth import current_superuser_act
21
22
  from fractal_server.app.routes.aux._job import _write_shutdown_file
22
23
  from fractal_server.app.routes.aux._runner import _check_shutdown_is_supported
@@ -37,6 +38,7 @@ router = APIRouter()
37
38
  @router.get("/", response_model=PaginationResponse[JobRead])
38
39
  async def view_job(
39
40
  id: int | None = None,
41
+ resource_id: int | None = None,
40
42
  user_id: int | None = None,
41
43
  project_id: int | None = None,
42
44
  dataset_id: int | None = None,
@@ -84,6 +86,13 @@ async def view_job(
84
86
  if id is not None:
85
87
  stm = stm.where(JobV2.id == id)
86
88
  stm_count = stm_count.where(JobV2.id == id)
89
+ if resource_id is not None:
90
+ stm = stm.join(ProjectV2, ProjectV2.id == JobV2.project_id).where(
91
+ ProjectV2.resource_id == resource_id
92
+ )
93
+ stm_count = stm_count.join(
94
+ ProjectV2, ProjectV2.id == JobV2.project_id
95
+ ).where(ProjectV2.resource_id == resource_id)
87
96
  if user_id is not None:
88
97
  stm = (
89
98
  stm.join(
@@ -19,6 +19,7 @@ from fractal_server.app.routes.api.v2._aux_functions import _get_workflow_or_404
19
19
  from fractal_server.app.routes.api.v2._aux_functions import (
20
20
  _get_workflowtask_or_404,
21
21
  )
22
+ from fractal_server.app.schemas.v2.job import JobStatusType
22
23
  from fractal_server.app.schemas.v2.sharing import ProjectPermissions
23
24
  from fractal_server.logger import set_logger
24
25
  from fractal_server.zip_tools import _read_single_file_from_zip
@@ -70,6 +71,7 @@ def read_log_file(
70
71
  dataset_id: int,
71
72
  logfile: str,
72
73
  job_working_dir: str,
74
+ job_status: JobStatusType,
73
75
  ) -> str:
74
76
  """
75
77
  Returns the contents of a Job's log file, either directly from the working
@@ -93,12 +95,18 @@ def read_log_file(
93
95
  return _read_single_file_from_zip(
94
96
  file_path=relative_logfile, archive_path=archive_path
95
97
  )
96
-
97
98
  else:
98
- logger.error(
99
- f"Error while retrieving logs for {logfile=} and "
100
- f"{archive_path=}: both files do not exist."
101
- )
99
+ match job_status:
100
+ case JobStatusType.SUBMITTED:
101
+ logger.info(
102
+ f"Neither {logfile=} nor {archive_path=} exist "
103
+ "(for submitted job)."
104
+ )
105
+ case _:
106
+ logger.warning(
107
+ f"Error while retrieving logs for {logfile=} and "
108
+ f"{archive_path=}."
109
+ )
102
110
  return (
103
111
  f"Logs for task '{task_name}' in dataset "
104
112
  f"{dataset_id} are not available."
@@ -458,11 +458,11 @@ async def get_image_log(
458
458
 
459
459
  # Get job.working_dir
460
460
  res = await db.execute(
461
- select(JobV2.working_dir)
461
+ select(JobV2.working_dir, JobV2.status)
462
462
  .join(HistoryRun, HistoryRun.job_id == JobV2.id)
463
463
  .where(HistoryRun.id == history_unit.history_run_id)
464
464
  )
465
- job_working_dir = res.scalar_one_or_none()
465
+ job_working_dir, job_status = res.one()
466
466
 
467
467
  # Get log or placeholder text
468
468
  log = read_log_file(
@@ -470,6 +470,7 @@ async def get_image_log(
470
470
  task_name=wftask.task.name,
471
471
  dataset_id=request_data.dataset_id,
472
472
  job_working_dir=job_working_dir,
473
+ job_status=job_status,
473
474
  )
474
475
  return JSONResponse(content=log)
475
476
 
@@ -525,6 +526,7 @@ async def get_history_unit_log(
525
526
  task_name=wftask.task.name,
526
527
  dataset_id=dataset_id,
527
528
  job_working_dir=job.working_dir,
529
+ job_status=job.status,
528
530
  )
529
531
  return JSONResponse(content=log)
530
532
 
@@ -54,7 +54,8 @@ async def get_user_jobs(
54
54
  LinkUserProjectV2, LinkUserProjectV2.project_id == JobV2.project_id
55
55
  )
56
56
  .where(LinkUserProjectV2.user_id == user.id)
57
- .where(LinkUserProjectV2.is_owner.is_(True))
57
+ .where(LinkUserProjectV2.is_verified.is_(True))
58
+ .order_by(JobV2.start_timestamp.desc())
58
59
  )
59
60
  res = await db.execute(stm)
60
61
  job_list = res.scalars().all()
@@ -86,8 +87,11 @@ async def get_workflow_jobs(
86
87
  required_permissions=ProjectPermissions.READ,
87
88
  db=db,
88
89
  )
89
- stm = select(JobV2).where(JobV2.workflow_id == workflow_id)
90
- res = await db.execute(stm)
90
+ res = await db.execute(
91
+ select(JobV2)
92
+ .where(JobV2.workflow_id == workflow_id)
93
+ .order_by(JobV2.start_timestamp.desc())
94
+ )
91
95
  job_list = res.scalars().all()
92
96
  return job_list
93
97
 
@@ -212,8 +216,11 @@ async def get_job_list(
212
216
  db=db,
213
217
  )
214
218
 
215
- stm = select(JobV2).where(JobV2.project_id == project.id)
216
- res = await db.execute(stm)
219
+ res = await db.execute(
220
+ select(JobV2)
221
+ .where(JobV2.project_id == project.id)
222
+ .order_by(JobV2.start_timestamp.desc())
223
+ )
217
224
  job_list = res.scalars().all()
218
225
  await db.close()
219
226
  if not log:
@@ -3,6 +3,8 @@ from httpx_oauth.clients.github import GitHubOAuth2
3
3
  from httpx_oauth.clients.google import GoogleOAuth2
4
4
  from httpx_oauth.clients.openid import OpenID
5
5
  from httpx_oauth.clients.openid import OpenIDConfigurationError
6
+ from httpx_oauth.exceptions import GetIdEmailError
7
+ from httpx_oauth.exceptions import GetProfileError
6
8
 
7
9
  from fractal_server.config import OAuthSettings
8
10
  from fractal_server.config import get_oauth_settings
@@ -13,6 +15,29 @@ from . import cookie_backend
13
15
  from . import fastapi_users
14
16
 
15
17
 
18
+ class FractalOpenID(OpenID):
19
+ """
20
+ Subclass of `httpx_oauth.clients.openid.OpenID` with customizable name for
21
+ the `"email"` claim.
22
+ """
23
+
24
+ def __init__(self, *, email_claim: str, **kwargs):
25
+ super().__init__(**kwargs)
26
+ self.email_claim = email_claim
27
+
28
+ # TODO-requires-py312: add `@override` decorator
29
+ async def get_id_email(self, token: str) -> tuple[str, str | None]:
30
+ """
31
+ Identical to the parent-class method (httpx-oauth version 0.16.1),
32
+ apart from making `"email"` configurable.
33
+ """
34
+ try:
35
+ profile = await self.get_profile(token)
36
+ except GetProfileError as e:
37
+ raise GetIdEmailError(response=e.response) from e
38
+ return str(profile["sub"]), profile.get(self.email_claim)
39
+
40
+
16
41
  def _create_client_github(cfg: OAuthSettings) -> GitHubOAuth2:
17
42
  return GitHubOAuth2(
18
43
  client_id=cfg.OAUTH_CLIENT_ID.get_secret_value(),
@@ -29,10 +54,11 @@ def _create_client_google(cfg: OAuthSettings) -> GoogleOAuth2:
29
54
 
30
55
  def _create_client_oidc(cfg: OAuthSettings) -> OpenID:
31
56
  try:
32
- open_id = OpenID(
57
+ open_id = FractalOpenID(
33
58
  client_id=cfg.OAUTH_CLIENT_ID.get_secret_value(),
34
59
  client_secret=cfg.OAUTH_CLIENT_SECRET.get_secret_value(),
35
60
  openid_configuration_endpoint=cfg.OAUTH_OIDC_CONFIG_ENDPOINT.get_secret_value(), # noqa
61
+ email_claim=cfg.OAUTH_EMAIL_CLAIM,
36
62
  )
37
63
  except OpenIDConfigurationError as e:
38
64
  OAUTH_OIDC_CONFIG_ENDPOINT = (
@@ -84,9 +84,6 @@ class TaskGroupRead(BaseModel):
84
84
  pinned_package_versions_pre: dict[str, str] = Field(default_factory=dict)
85
85
  pinned_package_versions_post: dict[str, str] = Field(default_factory=dict)
86
86
 
87
- venv_size_in_kB: int | None = None
88
- venv_file_number: int | None = None
89
-
90
87
  active: bool
91
88
  timestamp_created: AwareDatetime
92
89
  timestamp_last_used: AwareDatetime
@@ -28,6 +28,11 @@ class OAuthSettings(BaseSettings):
28
28
  String to be used as `redirect_url` argument in
29
29
  `fastapi_users.get_oauth_router`, and then in
30
30
  `httpx_oauth.integrations.fastapi.OAuth2AuthorizeCallback`.
31
+ OAUTH_EMAIL_CLAIM:
32
+ Name of the OIDC claim with the user's email address. This is
33
+ `"email"` by default, but can be customized (e.g. to `"mail"`) to
34
+ fit with the response from the userinfo endpoint - see
35
+ https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
31
36
  """
32
37
 
33
38
  model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
@@ -43,6 +48,7 @@ class OAuthSettings(BaseSettings):
43
48
  OAUTH_CLIENT_SECRET: SecretStr | None = None
44
49
  OAUTH_OIDC_CONFIG_ENDPOINT: SecretStr | None = None
45
50
  OAUTH_REDIRECT_URL: str | None = None
51
+ OAUTH_EMAIL_CLAIM: str = "email"
46
52
 
47
53
  @model_validator(mode="after")
48
54
  def check_configuration(self: Self) -> Self:
@@ -0,0 +1,48 @@
1
+ """Drop TaskGroup venv size and files number
2
+
3
+ Revision ID: 068496367952
4
+ Revises: b7477cc98f45
5
+ Create Date: 2025-12-10 15:24:47.720796
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "068496367952"
14
+ down_revision = "b7477cc98f45"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade() -> None:
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
22
+ batch_op.drop_column("venv_size_in_kB")
23
+ batch_op.drop_column("venv_file_number")
24
+
25
+ # ### end Alembic commands ###
26
+
27
+
28
+ def downgrade() -> None:
29
+ # ### commands auto generated by Alembic - please adjust! ###
30
+ with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
31
+ batch_op.add_column(
32
+ sa.Column(
33
+ "venv_file_number",
34
+ sa.INTEGER(),
35
+ autoincrement=False,
36
+ nullable=True,
37
+ )
38
+ )
39
+ batch_op.add_column(
40
+ sa.Column(
41
+ "venv_size_in_kB",
42
+ sa.INTEGER(),
43
+ autoincrement=False,
44
+ nullable=True,
45
+ )
46
+ )
47
+
48
+ # ### end Alembic commands ###
@@ -35,6 +35,7 @@ class SlurmConfigSet(BaseModel):
35
35
  extra_lines:
36
36
  gpus:
37
37
  shebang_line: The shell shebang to use for SLURM jobs.
38
+ use_mem_per_cpu:
38
39
  """
39
40
 
40
41
  model_config = ConfigDict(extra="forbid")
@@ -51,6 +52,7 @@ class SlurmConfigSet(BaseModel):
51
52
  extra_lines: list[NonEmptyStr] = Field(default_factory=list)
52
53
  gpus: NonEmptyStr | None = None
53
54
  shebang_line: str = "#!/bin/sh"
55
+ use_mem_per_cpu: bool = False
54
56
 
55
57
 
56
58
  class BatchingConfigSet(BaseModel):
@@ -6,6 +6,18 @@ import subprocess # nosec
6
6
  from fractal_server.runner.exceptions import TaskExecutionError
7
7
  from fractal_server.string_tools import validate_cmd
8
8
 
9
+ MAX_LEN_STDERR = 100_000
10
+
11
+
12
+ def placeholder_if_too_long(stderr: str) -> str:
13
+ """Returns a placeholder if the string is too long"""
14
+ if len(stderr) > MAX_LEN_STDERR:
15
+ return (
16
+ f"Cannot display stderr of length {len(stderr)}. You can find the "
17
+ "detailed logs by downloading the job-log folder."
18
+ )
19
+ return stderr
20
+
9
21
 
10
22
  def call_command_wrapper(*, cmd: str, log_path: str) -> None:
11
23
  """
@@ -46,6 +58,7 @@ def call_command_wrapper(*, cmd: str, log_path: str) -> None:
46
58
  if os.path.isfile(log_path):
47
59
  with open(log_path) as fp_stderr:
48
60
  stderr = fp_stderr.read()
61
+ stderr = placeholder_if_too_long(stderr)
49
62
  raise TaskExecutionError(
50
63
  f"Task failed with returncode={result.returncode}.\n"
51
64
  f"STDERR: {stderr}"
@@ -365,7 +365,8 @@ class BaseSlurmRunner(BaseRunner):
365
365
 
366
366
  # Prepare SLURM preamble based on SlurmConfig object
367
367
  script_lines = slurm_config.to_sbatch_preamble(
368
- remote_export_dir=self.user_cache_dir
368
+ remote_export_dir=self.user_cache_dir,
369
+ use_mem_per_cpu=slurm_config.use_mem_per_cpu,
369
370
  )
370
371
 
371
372
  # Extend SLURM preamble with variable which are not in SlurmConfig, and
@@ -389,11 +390,14 @@ class BaseSlurmRunner(BaseRunner):
389
390
  script_lines.append("\n")
390
391
 
391
392
  # Include command lines
392
- mem_per_task_MB = slurm_config.mem_per_task_MB
393
393
  for cmd in cmdlines:
394
+ if slurm_config.use_mem_per_cpu:
395
+ mem_specific = f"--mem-per-cpu={slurm_config.mem_per_cpu_MB}MB"
396
+ else:
397
+ mem_specific = f"--mem={slurm_config.mem_per_task_MB}MB"
394
398
  script_lines.append(
395
399
  "srun --ntasks=1 --cpus-per-task=$SLURM_CPUS_PER_TASK "
396
- f"--mem={mem_per_task_MB}MB "
400
+ f"{mem_specific} "
397
401
  f"{cmd} &"
398
402
  )
399
403
  script_lines.append("wait\n\n")
@@ -42,6 +42,9 @@ class SlurmConfig(BaseModel):
42
42
  exclude: Corresponds to SLURM option.
43
43
  prefix: Prefix of configuration lines in SLURM submission scripts.
44
44
  shebang_line: Shebang line for SLURM submission scripts.
45
+ use_mem_per_cpu:
46
+ If `True`, use `--mem-per-cpu` rather than `--mem`, both at the job
47
+ level and for `srun` statements.
45
48
  extra_lines: Additional lines to include in SLURM submission scripts.
46
49
  tasks_per_job: Number of tasks for each SLURM job.
47
50
  parallel_tasks_per_job: Number of tasks to run in parallel for
@@ -70,9 +73,12 @@ class SlurmConfig(BaseModel):
70
73
  partition: str
71
74
  cpus_per_task: int
72
75
  mem_per_task_MB: int
76
+
73
77
  prefix: str = "#SBATCH"
74
78
  shebang_line: str = "#!/bin/sh"
75
79
 
80
+ use_mem_per_cpu: bool = False
81
+
76
82
  # Optional SLURM parameters
77
83
  job_name: str | None = None
78
84
  constraint: str | None = None
@@ -139,6 +145,7 @@ class SlurmConfig(BaseModel):
139
145
  def to_sbatch_preamble(
140
146
  self,
141
147
  remote_export_dir: str,
148
+ use_mem_per_cpu: bool = False,
142
149
  ) -> list[str]:
143
150
  """
144
151
  Compile `SlurmConfig` object into the preamble of a SLURM submission
@@ -148,6 +155,8 @@ class SlurmConfig(BaseModel):
148
155
  remote_export_dir:
149
156
  Base directory for exports defined in
150
157
  `self.user_local_exports`.
158
+ use_mem_per_cpu:
159
+ If `True`, use `--mem-per-cpu` rather than `--mem`.
151
160
  """
152
161
  if self.parallel_tasks_per_job is None:
153
162
  raise ValueError(
@@ -157,13 +166,18 @@ class SlurmConfig(BaseModel):
157
166
  if len(self.extra_lines) != len(set(self.extra_lines)):
158
167
  raise ValueError(f"{self.extra_lines=} contains repetitions")
159
168
 
160
- mem_per_job_MB = self.parallel_tasks_per_job * self.mem_per_task_MB
169
+ if use_mem_per_cpu:
170
+ memory_line = f"{self.prefix} --mem-per-cpu={self.mem_per_cpu_MB}M"
171
+ else:
172
+ mem_per_job_MB = self.parallel_tasks_per_job * self.mem_per_task_MB
173
+ memory_line = f"{self.prefix} --mem={mem_per_job_MB}M"
174
+
161
175
  lines = [
162
176
  self.shebang_line,
163
177
  f"{self.prefix} --partition={self.partition}",
164
178
  f"{self.prefix} --ntasks={self.parallel_tasks_per_job}",
165
179
  f"{self.prefix} --cpus-per-task={self.cpus_per_task}",
166
- f"{self.prefix} --mem={mem_per_job_MB}M",
180
+ memory_line,
167
181
  ]
168
182
  for key in [
169
183
  "job_name",
@@ -214,3 +228,7 @@ class SlurmConfig(BaseModel):
214
228
  @property
215
229
  def batch_size(self) -> int:
216
230
  return self.tasks_per_job
231
+
232
+ @property
233
+ def mem_per_cpu_MB(self) -> int:
234
+ return int(self.mem_per_task_MB / self.cpus_per_task)
@@ -174,15 +174,6 @@ def collect_local(
174
174
  activity.log = get_current_log(log_file_path)
175
175
  activity = add_commit_refresh(obj=activity, db=db)
176
176
 
177
- # Run script 5
178
- venv_info = _customize_and_run_template(
179
- template_filename="5_get_venv_size_and_file_number.sh",
180
- **common_args,
181
- )
182
- venv_size, venv_file_number = venv_info.split()
183
- activity.log = get_current_log(log_file_path)
184
- activity = add_commit_refresh(obj=activity, db=db)
185
-
186
177
  pkg_attrs = parse_script_pip_show_stdout(stdout)
187
178
  for key, value in pkg_attrs.items():
188
179
  logger.debug(f"Parsed from pip-show: {key}={value}")
@@ -241,18 +232,10 @@ def collect_local(
241
232
  logger.info("create_db_tasks_and_update_task_group - end")
242
233
 
243
234
  # Update task_group data
244
- logger.info(
245
- "Add env_info, venv_size and venv_file_number "
246
- "to TaskGroupV2 - start"
247
- )
235
+ logger.info("Add env_info to TaskGroupV2 - start")
248
236
  task_group.env_info = pip_freeze_stdout
249
- task_group.venv_size_in_kB = int(venv_size)
250
- task_group.venv_file_number = int(venv_file_number)
251
237
  task_group = add_commit_refresh(obj=task_group, db=db)
252
- logger.info(
253
- "Add env_info, venv_size and venv_file_number "
254
- "to TaskGroupV2 - end"
255
- )
238
+ logger.info("Add env_info to TaskGroupV2 - end")
256
239
 
257
240
  # Finalize (write metadata to DB)
258
241
  logger.info("finalising - START")
@@ -175,8 +175,6 @@ def collect_local_pixi(
175
175
  # Parse stdout
176
176
  parsed_output = parse_collect_stdout(stdout)
177
177
  package_root = parsed_output["package_root"]
178
- venv_size = parsed_output["venv_size"]
179
- venv_file_number = parsed_output["venv_file_number"]
180
178
  project_python_wrapper = parsed_output["project_python_wrapper"]
181
179
 
182
180
  # Make task folder 755
@@ -220,23 +218,15 @@ def collect_local_pixi(
220
218
  logger.info("create_db_tasks_and_update_task_group - end")
221
219
 
222
220
  # Update task_group data
223
- logger.info(
224
- "Add env_info, venv_size and venv_file_number "
225
- "to TaskGroupV2 - start"
226
- )
221
+ logger.info("Add env_info to TaskGroupV2 - start")
227
222
  with Path(source_dir, "pixi.lock").open() as f:
228
223
  pixi_lock_contents = f.read()
229
224
 
230
225
  # NOTE: see issue 2626 about whether to keep `pixi.lock` files
231
226
  # in the database
232
227
  task_group.env_info = pixi_lock_contents
233
- task_group.venv_size_in_kB = int(venv_size)
234
- task_group.venv_file_number = int(venv_file_number)
235
228
  task_group = add_commit_refresh(obj=task_group, db=db)
236
- logger.info(
237
- "Add env_info, venv_size and venv_file_number "
238
- "to TaskGroupV2 - end"
239
- )
229
+ logger.info("Add env_info to TaskGroupV2 - end")
240
230
 
241
231
  # Finalize (write metadata to DB)
242
232
  logger.info("finalising - START")
@@ -121,7 +121,7 @@ def reactivate_local(
121
121
 
122
122
  logger.debug("start - install from pip freeze")
123
123
  _customize_and_run_template(
124
- template_filename="6_pip_install_from_freeze.sh",
124
+ template_filename="5_pip_install_from_freeze.sh",
125
125
  **common_args,
126
126
  )
127
127
  logger.debug("end - install from pip freeze")
@@ -211,15 +211,6 @@ def collect_ssh(
211
211
  activity.log = get_current_log(log_file_path)
212
212
  activity = add_commit_refresh(obj=activity, db=db)
213
213
 
214
- # Run script 5
215
- venv_info = _customize_and_run_template(
216
- template_filename="5_get_venv_size_and_file_number.sh",
217
- **common_args,
218
- )
219
- venv_size, venv_file_number = venv_info.split()
220
- activity.log = get_current_log(log_file_path)
221
- activity = add_commit_refresh(obj=activity, db=db)
222
-
223
214
  pkg_attrs = parse_script_pip_show_stdout(stdout)
224
215
 
225
216
  for key, value in pkg_attrs.items():
@@ -275,18 +266,10 @@ def collect_ssh(
275
266
  logger.info("create_db_tasks_and_update_task_group - end")
276
267
 
277
268
  # Update task_group data
278
- logger.info(
279
- "Add env_info, venv_size and venv_file_number "
280
- "to TaskGroupV2 - start"
281
- )
269
+ logger.info("Add env_info to TaskGroupV2 - start")
282
270
  task_group.env_info = pip_freeze_stdout
283
- task_group.venv_size_in_kB = int(venv_size)
284
- task_group.venv_file_number = int(venv_file_number)
285
271
  task_group = add_commit_refresh(obj=task_group, db=db)
286
- logger.info(
287
- "Add env_info, venv_size and venv_file_number "
288
- "to TaskGroupV2 - end"
289
- )
272
+ logger.info("Add env_info to TaskGroupV2 - end")
290
273
 
291
274
  # Finalize (write metadata to DB)
292
275
  logger.info("finalising - START")
@@ -266,8 +266,6 @@ def collect_ssh_pixi(
266
266
  # Parse stdout
267
267
  parsed_output = parse_collect_stdout(stdout)
268
268
  package_root_remote = parsed_output["package_root"]
269
- venv_size = parsed_output["venv_size"]
270
- venv_file_number = parsed_output["venv_file_number"]
271
269
  project_python_wrapper = parsed_output[
272
270
  "project_python_wrapper"
273
271
  ]
@@ -312,18 +310,10 @@ def collect_ssh_pixi(
312
310
  )
313
311
 
314
312
  # Update task_group data
315
- logger.info(
316
- "Add env_info, venv_size and venv_file_number "
317
- "to TaskGroupV2 - start"
318
- )
313
+ logger.info("Add env_info to TaskGroupV2 - start")
319
314
  task_group.env_info = pixi_lock_contents
320
- task_group.venv_size_in_kB = int(venv_size)
321
- task_group.venv_file_number = int(venv_file_number)
322
315
  task_group = add_commit_refresh(obj=task_group, db=db)
323
- logger.info(
324
- "Add env_info, venv_size and venv_file_number "
325
- "to TaskGroupV2 - end"
326
- )
316
+ logger.info("Add env_info to TaskGroupV2 - end")
327
317
 
328
318
  # Finalize (write metadata to DB)
329
319
  logger.info("finalising - START")
@@ -167,7 +167,7 @@ def reactivate_ssh(
167
167
 
168
168
  logger.info("start - install from pip freeze")
169
169
  _customize_and_run_template(
170
- template_filename="6_pip_install_from_freeze.sh",
170
+ template_filename="5_pip_install_from_freeze.sh",
171
171
  **common_args,
172
172
  )
173
173
  logger.info("end - install from pip freeze")