fractal-server 2.17.0a11__tar.gz → 2.17.1__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 (266) hide show
  1. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/PKG-INFO +1 -1
  2. fractal_server-2.17.1/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/__main__.py +1 -1
  4. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/__init__.py +0 -1
  5. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/security.py +1 -14
  6. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/project.py +1 -4
  7. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/task_group.py +1 -4
  8. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/job.py +45 -9
  9. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/task.py +49 -32
  10. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/task_collection.py +11 -3
  11. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/shutdown.py +23 -19
  12. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/config/_database.py +3 -2
  13. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/config/_main.py +1 -1
  14. fractal_server-2.17.1/fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +46 -0
  15. fractal_server-2.17.1/fractal_server/migrations/versions/49d0856e9569_drop_table.py +63 -0
  16. fractal_server-2.17.1/fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +29 -0
  17. fractal_server-2.17.1/fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +49 -0
  18. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/runner.py +24 -0
  19. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/config/_python.py +1 -1
  20. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/pyproject.toml +3 -3
  21. fractal_server-2.17.0a11/fractal_server/__init__.py +0 -1
  22. fractal_server-2.17.0a11/fractal_server/app/models/user_settings.py +0 -37
  23. fractal_server-2.17.0a11/fractal_server/data_migrations/2_17_0.py +0 -321
  24. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/LICENSE +0 -0
  25. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/README.md +0 -0
  26. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/alembic.ini +0 -0
  27. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/__init__.py +0 -0
  28. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/db/__init__.py +0 -0
  29. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/linkusergroup.py +0 -0
  30. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/linkuserproject.py +0 -0
  31. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/__init__.py +0 -0
  32. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/accounting.py +0 -0
  33. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/dataset.py +0 -0
  34. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/history.py +0 -0
  35. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/job.py +0 -0
  36. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/profile.py +0 -0
  37. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/resource.py +0 -0
  38. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/task.py +0 -0
  39. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/workflow.py +0 -0
  40. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/models/v2/workflowtask.py +0 -0
  41. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/__init__.py +0 -0
  42. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/__init__.py +0 -0
  43. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  44. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/_aux_functions.py +0 -0
  45. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  46. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  47. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/profile.py +0 -0
  48. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/project.py +0 -0
  49. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/resource.py +0 -0
  50. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  51. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  52. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/__init__.py +0 -0
  53. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  54. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  55. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  56. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  57. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  58. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  59. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
  60. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  61. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/history.py +0 -0
  62. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/images.py +0 -0
  63. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/job.py +0 -0
  64. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
  65. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/project.py +0 -0
  66. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  67. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/submit.py +0 -0
  68. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/task.py +0 -0
  69. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  70. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  71. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
  72. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  73. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  74. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
  75. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  76. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  77. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  78. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/__init__.py +0 -0
  79. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  80. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/current_user.py +0 -0
  81. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/group.py +0 -0
  82. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/login.py +0 -0
  83. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/oauth.py +0 -0
  84. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/register.py +0 -0
  85. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/router.py +0 -0
  86. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/auth/users.py +0 -0
  87. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/aux/__init__.py +0 -0
  88. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/aux/_job.py +0 -0
  89. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/aux/_runner.py +0 -0
  90. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/aux/validate_user_profile.py +0 -0
  91. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/routes/pagination.py +0 -0
  92. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/__init__.py +0 -0
  93. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/user.py +0 -0
  94. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/user_group.py +0 -0
  95. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/__init__.py +0 -0
  96. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/accounting.py +0 -0
  97. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/dataset.py +0 -0
  98. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/dumps.py +0 -0
  99. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/history.py +0 -0
  100. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/job.py +0 -0
  101. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/manifest.py +0 -0
  102. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/profile.py +0 -0
  103. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/project.py +0 -0
  104. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/resource.py +0 -0
  105. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  106. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/task.py +0 -0
  107. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/task_group.py +0 -0
  108. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/workflow.py +0 -0
  109. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  110. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/security/__init__.py +0 -0
  111. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/app/security/signup_email.py +0 -0
  112. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/config/__init__.py +0 -0
  113. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/config/_data.py +0 -0
  114. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/config/_email.py +0 -0
  115. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/config/_oauth.py +0 -0
  116. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/config/_settings_config.py +0 -0
  117. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/data_migrations/README.md +0 -0
  118. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/data_migrations/tools.py +0 -0
  119. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/exceptions.py +0 -0
  120. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/gunicorn_fractal.py +0 -0
  121. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/images/__init__.py +0 -0
  122. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/images/models.py +0 -0
  123. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/images/status_tools.py +0 -0
  124. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/images/tools.py +0 -0
  125. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/logger.py +0 -0
  126. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/main.py +0 -0
  127. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/env.py +0 -0
  128. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/naming_convention.py +0 -0
  129. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  130. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  131. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
  132. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  133. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
  134. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  135. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  136. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  137. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  138. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  139. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  140. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  141. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  142. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  143. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  144. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
  145. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +0 -0
  146. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  147. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  148. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  149. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  150. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
  151. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  152. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
  153. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  154. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  155. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  156. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  157. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  158. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  159. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  160. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
  161. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
  162. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  163. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  164. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  165. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  166. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  167. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  168. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  169. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  170. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  171. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  172. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  173. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/py.typed +0 -0
  174. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/__init__.py +0 -0
  175. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/components.py +0 -0
  176. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/config/__init__.py +0 -0
  177. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/config/_local.py +0 -0
  178. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/config/_slurm.py +0 -0
  179. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/config/slurm_mem_to_MB.py +0 -0
  180. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/exceptions.py +0 -0
  181. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/__init__.py +0 -0
  182. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/base_runner.py +0 -0
  183. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/call_command_wrapper.py +0 -0
  184. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/local/__init__.py +0 -0
  185. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/local/get_local_config.py +0 -0
  186. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/local/runner.py +0 -0
  187. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/__init__.py +0 -0
  188. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/_batching.py +0 -0
  189. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/_job_states.py +0 -0
  190. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  191. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/get_slurm_config.py +0 -0
  192. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/remote.py +0 -0
  193. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/slurm_config.py +0 -0
  194. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  195. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_ssh/__init__.py +0 -0
  196. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  197. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_ssh/runner.py +0 -0
  198. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_ssh/tar_commands.py +0 -0
  199. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_sudo/__init__.py +0 -0
  200. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  201. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/executors/slurm_sudo/runner.py +0 -0
  202. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/filenames.py +0 -0
  203. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/set_start_and_last_task_index.py +0 -0
  204. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/task_files.py +0 -0
  205. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/__init__.py +0 -0
  206. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/_local.py +0 -0
  207. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/_slurm_ssh.py +0 -0
  208. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/_slurm_sudo.py +0 -0
  209. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/db_tools.py +0 -0
  210. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/deduplicate_list.py +0 -0
  211. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/merge_outputs.py +0 -0
  212. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/runner_functions.py +0 -0
  213. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/submit_workflow.py +0 -0
  214. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/v2/task_interface.py +0 -0
  215. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/runner/versions.py +0 -0
  216. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/ssh/__init__.py +0 -0
  217. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/ssh/_fabric.py +0 -0
  218. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/string_tools.py +0 -0
  219. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/syringe.py +0 -0
  220. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/__init__.py +0 -0
  221. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/config/__init__.py +0 -0
  222. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/config/_pixi.py +0 -0
  223. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/utils.py +0 -0
  224. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/__init__.py +0 -0
  225. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/__init__.py +0 -0
  226. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/_utils.py +0 -0
  227. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/collect.py +0 -0
  228. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/collect_pixi.py +0 -0
  229. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  230. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
  231. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/delete.py +1 -1
  232. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  233. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
  234. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  235. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -0
  236. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  237. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/collect.py +0 -0
  238. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/collect_pixi.py +0 -0
  239. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  240. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
  241. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/delete.py +0 -0
  242. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  243. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +0 -0
  244. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  245. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  246. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  247. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  248. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  249. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  250. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
  251. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
  252. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -0
  253. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/utils_background.py +0 -0
  254. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/utils_database.py +0 -0
  255. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  256. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/utils_pixi.py +0 -0
  257. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  258. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/tasks/v2/utils_templates.py +0 -0
  259. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/types/__init__.py +0 -0
  260. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/types/validators/__init__.py +0 -0
  261. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/types/validators/_common_validators.py +0 -0
  262. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/types/validators/_filter_validators.py +0 -0
  263. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
  264. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/urls.py +0 -0
  265. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/utils.py +0 -0
  266. {fractal_server-2.17.0a11 → fractal_server-2.17.1}/fractal_server/zip_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fractal-server
3
- Version: 2.17.0a11
3
+ Version: 2.17.1
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License-Expression: BSD-3-Clause
6
6
  License-File: LICENSE
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.17.1"
@@ -7,7 +7,6 @@ from pathlib import Path
7
7
  import uvicorn
8
8
  from pydantic import ValidationError
9
9
 
10
- from fractal_server.app.schemas.v2 import ResourceType
11
10
 
12
11
  parser = ap.ArgumentParser(description="fractal-server commands")
13
12
 
@@ -149,6 +148,7 @@ def init_db_data(
149
148
  from fractal_server.app.models import Resource, Profile
150
149
  from fractal_server.app.schemas.v2.resource import cast_serialize_resource
151
150
  from fractal_server.app.schemas.v2.profile import cast_serialize_profile
151
+ from fractal_server.app.schemas.v2 import ResourceType
152
152
 
153
153
  # Create default group and user
154
154
  print()
@@ -6,5 +6,4 @@ will not be picked up by alembic.
6
6
  from .linkusergroup import LinkUserGroup # noqa: F401
7
7
  from .linkuserproject import LinkUserProjectV2 # noqa: F401
8
8
  from .security import * # noqa
9
- from .user_settings import UserSettings # noqa
10
9
  from .v2 import * # noqa
@@ -95,24 +95,11 @@ class UserOAuth(SQLModel, table=True):
95
95
  ondelete="RESTRICT",
96
96
  )
97
97
 
98
- # TODO-2.17.1: update to `project_dir: str`
99
- project_dir: str = Field(
100
- sa_column=Column(
101
- String,
102
- server_default="/PLACEHOLDER",
103
- nullable=False,
104
- )
105
- )
98
+ project_dir: str
106
99
  slurm_accounts: list[str] = Field(
107
100
  sa_column=Column(ARRAY(String), server_default="{}"),
108
101
  )
109
102
 
110
- # TODO-2.17.1: remove
111
- user_settings_id: int | None = Field(
112
- foreign_key="user_settings.id",
113
- default=None,
114
- )
115
-
116
103
 
117
104
  class UserGroup(SQLModel, table=True):
118
105
  """
@@ -15,10 +15,7 @@ class ProjectV2(SQLModel, table=True):
15
15
  id: int | None = Field(default=None, primary_key=True)
16
16
  name: str
17
17
 
18
- # TODO-2.17.1: make `resource_id` not nullable
19
- resource_id: int | None = Field(
20
- foreign_key="resource.id", default=None, ondelete="RESTRICT"
21
- )
18
+ resource_id: int = Field(foreign_key="resource.id", ondelete="RESTRICT")
22
19
  timestamp_created: datetime = Field(
23
20
  default_factory=get_timestamp,
24
21
  sa_column=Column(DateTime(timezone=True), nullable=False),
@@ -42,10 +42,7 @@ class TaskGroupV2(SQLModel, table=True):
42
42
  user_group_id: int | None = Field(
43
43
  foreign_key="usergroup.id", default=None, ondelete="SET NULL"
44
44
  )
45
- # TODO-2.17.1: make `resource_id` not nullable
46
- resource_id: int | None = Field(
47
- foreign_key="resource.id", default=None, ondelete="RESTRICT"
48
- )
45
+ resource_id: int = Field(foreign_key="resource.id", ondelete="RESTRICT")
49
46
 
50
47
  origin: str
51
48
  pkg_name: str
@@ -7,6 +7,7 @@ from fastapi import Response
7
7
  from fastapi import status
8
8
  from fastapi.responses import StreamingResponse
9
9
  from pydantic.types import AwareDatetime
10
+ from sqlalchemy import func
10
11
  from sqlmodel import select
11
12
 
12
13
  from fractal_server.app.db import AsyncSession
@@ -19,6 +20,9 @@ from fractal_server.app.models.v2 import ProjectV2
19
20
  from fractal_server.app.routes.auth import current_superuser_act
20
21
  from fractal_server.app.routes.aux._job import _write_shutdown_file
21
22
  from fractal_server.app.routes.aux._runner import _check_shutdown_is_supported
23
+ from fractal_server.app.routes.pagination import get_pagination_params
24
+ from fractal_server.app.routes.pagination import PaginationRequest
25
+ from fractal_server.app.routes.pagination import PaginationResponse
22
26
  from fractal_server.app.schemas.v2 import HistoryUnitStatus
23
27
  from fractal_server.app.schemas.v2 import JobReadV2
24
28
  from fractal_server.app.schemas.v2 import JobStatusTypeV2
@@ -30,7 +34,7 @@ from fractal_server.zip_tools import _zip_folder_to_byte_stream_iterator
30
34
  router = APIRouter()
31
35
 
32
36
 
33
- @router.get("/", response_model=list[JobReadV2])
37
+ @router.get("/", response_model=PaginationResponse[JobReadV2])
34
38
  async def view_job(
35
39
  id: int | None = None,
36
40
  user_id: int | None = None,
@@ -43,9 +47,10 @@ async def view_job(
43
47
  end_timestamp_min: AwareDatetime | None = None,
44
48
  end_timestamp_max: AwareDatetime | None = None,
45
49
  log: bool = True,
50
+ pagination: PaginationRequest = Depends(get_pagination_params),
46
51
  user: UserOAuth = Depends(current_superuser_act),
47
52
  db: AsyncSession = Depends(get_async_db),
48
- ) -> list[JobReadV2]:
53
+ ) -> PaginationResponse[JobReadV2]:
49
54
  """
50
55
  Query `ApplyWorkflow` table.
51
56
 
@@ -68,43 +73,74 @@ async def view_job(
68
73
  `job.log` is set to `None`.
69
74
  """
70
75
 
71
- stm = select(JobV2)
76
+ # Assign pagination parameters
77
+ page = pagination.page
78
+ page_size = pagination.page_size
72
79
 
80
+ # Prepare statements
81
+ stm = select(JobV2).order_by(JobV2.start_timestamp.desc())
82
+ stm_count = select(func.count(JobV2.id))
73
83
  if id is not None:
74
84
  stm = stm.where(JobV2.id == id)
85
+ stm_count = stm_count.where(JobV2.id == id)
75
86
  if user_id is not None:
76
87
  stm = stm.join(ProjectV2).where(
77
88
  ProjectV2.user_list.any(UserOAuth.id == user_id)
78
89
  )
90
+ stm_count = stm_count.join(ProjectV2).where(
91
+ ProjectV2.user_list.any(UserOAuth.id == user_id)
92
+ )
79
93
  if project_id is not None:
80
94
  stm = stm.where(JobV2.project_id == project_id)
95
+ stm_count = stm_count.where(JobV2.project_id == project_id)
81
96
  if dataset_id is not None:
82
97
  stm = stm.where(JobV2.dataset_id == dataset_id)
98
+ stm_count = stm_count.where(JobV2.dataset_id == dataset_id)
83
99
  if workflow_id is not None:
84
100
  stm = stm.where(JobV2.workflow_id == workflow_id)
101
+ stm_count = stm_count.where(JobV2.workflow_id == workflow_id)
85
102
  if status is not None:
86
103
  stm = stm.where(JobV2.status == status)
104
+ stm_count = stm_count.where(JobV2.status == status)
87
105
  if start_timestamp_min is not None:
88
- start_timestamp_min = start_timestamp_min
89
106
  stm = stm.where(JobV2.start_timestamp >= start_timestamp_min)
107
+ stm_count = stm_count.where(
108
+ JobV2.start_timestamp >= start_timestamp_min
109
+ )
90
110
  if start_timestamp_max is not None:
91
- start_timestamp_max = start_timestamp_max
92
111
  stm = stm.where(JobV2.start_timestamp <= start_timestamp_max)
112
+ stm_count = stm_count.where(
113
+ JobV2.start_timestamp <= start_timestamp_max
114
+ )
93
115
  if end_timestamp_min is not None:
94
- end_timestamp_min = end_timestamp_min
95
116
  stm = stm.where(JobV2.end_timestamp >= end_timestamp_min)
117
+ stm_count = stm_count.where(JobV2.end_timestamp >= end_timestamp_min)
96
118
  if end_timestamp_max is not None:
97
- end_timestamp_max = end_timestamp_max
98
119
  stm = stm.where(JobV2.end_timestamp <= end_timestamp_max)
120
+ stm_count = stm_count.where(JobV2.end_timestamp <= end_timestamp_max)
99
121
 
122
+ # Find total number of elements
123
+ res_total_count = await db.execute(stm_count)
124
+ total_count = res_total_count.scalar()
125
+ if page_size is None:
126
+ page_size = total_count
127
+ else:
128
+ stm = stm.offset((page - 1) * page_size).limit(page_size)
129
+
130
+ # Get `page_size` rows
100
131
  res = await db.execute(stm)
101
132
  job_list = res.scalars().all()
102
- await db.close()
133
+
103
134
  if not log:
104
135
  for job in job_list:
105
136
  setattr(job, "log", None)
106
137
 
107
- return job_list
138
+ return PaginationResponse[JobReadV2](
139
+ total_count=total_count,
140
+ page_size=page_size,
141
+ current_page=page,
142
+ items=[job.model_dump() for job in job_list],
143
+ )
108
144
 
109
145
 
110
146
  @router.get("/{job_id}/", response_model=JobReadV2)
@@ -1,7 +1,5 @@
1
1
  from fastapi import APIRouter
2
2
  from fastapi import Depends
3
- from fastapi import HTTPException
4
- from fastapi import status
5
3
  from pydantic import BaseModel
6
4
  from pydantic import EmailStr
7
5
  from pydantic import Field
@@ -16,6 +14,10 @@ from fractal_server.app.models.v2 import TaskV2
16
14
  from fractal_server.app.models.v2 import WorkflowTaskV2
17
15
  from fractal_server.app.models.v2 import WorkflowV2
18
16
  from fractal_server.app.routes.auth import current_superuser_act
17
+ from fractal_server.app.routes.pagination import get_pagination_params
18
+ from fractal_server.app.routes.pagination import PaginationRequest
19
+ from fractal_server.app.routes.pagination import PaginationResponse
20
+ from fractal_server.app.schemas.v2.task import TaskType
19
21
 
20
22
  router = APIRouter()
21
23
 
@@ -49,75 +51,85 @@ class TaskV2Info(BaseModel):
49
51
  relationships: list[TaskV2Relationship]
50
52
 
51
53
 
52
- @router.get("/", response_model=list[TaskV2Info])
54
+ @router.get("/", response_model=PaginationResponse[TaskV2Info])
53
55
  async def query_tasks(
54
56
  id: int | None = None,
55
57
  source: str | None = None,
56
58
  version: str | None = None,
57
59
  name: str | None = None,
58
- max_number_of_results: int = 25,
60
+ task_type: TaskType | None = None,
59
61
  category: str | None = None,
60
62
  modality: str | None = None,
61
63
  author: str | None = None,
62
64
  resource_id: int | None = None,
65
+ pagination: PaginationRequest = Depends(get_pagination_params),
63
66
  user: UserOAuth = Depends(current_superuser_act),
64
67
  db: AsyncSession = Depends(get_async_db),
65
- ) -> list[TaskV2Info]:
68
+ ) -> PaginationResponse[TaskV2Info]:
66
69
  """
67
- Query `TaskV2` table and get information 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
- category:
78
- modality:
79
- author:
80
- resource_id:
70
+ Query `TaskV2` and get information about related workflows and projects.
81
71
  """
82
72
 
83
- stm = select(TaskV2)
73
+ # Assign pagination parameters
74
+ page = pagination.page
75
+ page_size = pagination.page_size
84
76
 
77
+ # Prepare statements
78
+ stm = select(TaskV2).order_by(TaskV2.id)
79
+ stm_count = select(func.count(TaskV2.id))
85
80
  if id is not None:
86
81
  stm = stm.where(TaskV2.id == id)
82
+ stm_count = stm_count.where(TaskV2.id == id)
87
83
  if source is not None:
88
84
  stm = stm.where(TaskV2.source.icontains(source))
85
+ stm_count = stm_count.where(TaskV2.source.icontains(source))
89
86
  if version is not None:
90
87
  stm = stm.where(TaskV2.version == version)
88
+ stm_count = stm_count.where(TaskV2.version == version)
91
89
  if name is not None:
92
90
  stm = stm.where(TaskV2.name.icontains(name))
91
+ stm_count = stm_count.where(TaskV2.name.icontains(name))
92
+ if task_type is not None:
93
+ stm = stm.where(TaskV2.type == task_type)
94
+ stm_count = stm_count.where(TaskV2.type == task_type)
93
95
  if category is not None:
94
96
  stm = stm.where(func.lower(TaskV2.category) == category.lower())
97
+ stm_count = stm_count.where(
98
+ func.lower(TaskV2.category) == category.lower()
99
+ )
95
100
  if modality is not None:
96
101
  stm = stm.where(func.lower(TaskV2.modality) == modality.lower())
102
+ stm_count = stm_count.where(
103
+ func.lower(TaskV2.modality) == modality.lower()
104
+ )
97
105
  if author is not None:
98
106
  stm = stm.where(TaskV2.authors.icontains(author))
107
+ stm_count = stm_count.where(TaskV2.authors.icontains(author))
99
108
  if resource_id is not None:
100
109
  stm = (
101
110
  stm.join(TaskGroupV2)
102
111
  .where(TaskGroupV2.id == TaskV2.taskgroupv2_id)
103
112
  .where(TaskGroupV2.resource_id == resource_id)
104
113
  )
114
+ stm_count = (
115
+ stm_count.join(TaskGroupV2)
116
+ .where(TaskGroupV2.id == TaskV2.taskgroupv2_id)
117
+ .where(TaskGroupV2.resource_id == resource_id)
118
+ )
119
+
120
+ # Find total number of elements
121
+ res_total_count = await db.execute(stm_count)
122
+ total_count = res_total_count.scalar()
123
+ if page_size is None:
124
+ page_size = total_count
125
+ else:
126
+ stm = stm.offset((page - 1) * page_size).limit(page_size)
105
127
 
106
- stm = stm.order_by(TaskV2.id)
128
+ # Get `page_size` rows
107
129
  res = await db.execute(stm)
108
130
  task_list = res.scalars().all()
109
- if len(task_list) > max_number_of_results:
110
- await db.close()
111
- raise HTTPException(
112
- status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
113
- detail=(
114
- f"Too many Tasks ({len(task_list)} > {max_number_of_results})."
115
- " Please add more query filters."
116
- ),
117
- )
118
131
 
119
132
  task_info_list = []
120
-
121
133
  for task in task_list:
122
134
  stm = (
123
135
  select(WorkflowV2)
@@ -147,4 +159,9 @@ async def query_tasks(
147
159
  )
148
160
  )
149
161
 
150
- return task_info_list
162
+ return PaginationResponse[TaskV2Info](
163
+ total_count=total_count,
164
+ page_size=page_size,
165
+ current_page=page,
166
+ items=task_info_list,
167
+ )
@@ -51,9 +51,17 @@ class TaskCollectPipV2(BaseModel):
51
51
  package: NonEmptyStr | None = None
52
52
  package_version: NonEmptyStr | None = None
53
53
  package_extras: NonEmptyStr | None = None
54
- python_version: Literal[
55
- "3.9", "3.10", "3.11", "3.12", "3.13"
56
- ] | None = None
54
+ python_version: (
55
+ Literal[
56
+ "3.9",
57
+ "3.10",
58
+ "3.11",
59
+ "3.12",
60
+ "3.13",
61
+ "3.14",
62
+ ]
63
+ | None
64
+ ) = None
57
65
  pinned_package_versions_pre: DictStrStr | None = None
58
66
  pinned_package_versions_post: DictStrStr | None = None
59
67
 
@@ -12,44 +12,48 @@ from fractal_server.syringe import Inject
12
12
 
13
13
 
14
14
  async def cleanup_after_shutdown(*, jobsV2: list[int], logger_name: str):
15
+ settings = Inject(get_settings)
15
16
  logger = get_logger(logger_name)
16
17
  logger.info("Cleanup function after shutdown")
17
- stm_v2 = (
18
+ stm_objects = (
18
19
  select(JobV2)
19
20
  .where(JobV2.id.in_(jobsV2))
20
21
  .where(JobV2.status == JobStatusTypeV2.SUBMITTED)
21
22
  )
23
+ stm_ids = (
24
+ select(JobV2.id)
25
+ .where(JobV2.id.in_(jobsV2))
26
+ .where(JobV2.status == JobStatusTypeV2.SUBMITTED)
27
+ )
22
28
 
23
29
  async for session in get_async_db():
24
- jobsV2_db = (await session.execute(stm_v2)).scalars().all()
25
-
26
- for job in jobsV2_db:
30
+ # Write shutdown file for all jobs
31
+ jobs = (await session.execute(stm_objects)).scalars().all()
32
+ for job in jobs:
27
33
  _write_shutdown_file(job=job)
28
34
 
29
- settings = Inject(get_settings)
30
-
35
+ # Wait for completion of all job - with a timeout
36
+ interval = settings.FRACTAL_GRACEFUL_SHUTDOWN_TIME / 20
31
37
  t_start = time.perf_counter()
32
38
  while (
33
39
  time.perf_counter() - t_start
34
- ) < settings.FRACTAL_GRACEFUL_SHUTDOWN_TIME: # 30 seconds
35
- logger.info("Waiting 3 seconds before checking")
36
- time.sleep(3)
37
- jobsV2_db = (await session.execute(stm_v2)).scalars().all()
38
-
39
- if len(jobsV2_db) == 0:
40
- logger.info(
41
- "All jobs associated to this app are "
42
- "either done or failed. Exit."
43
- )
40
+ ) <= settings.FRACTAL_GRACEFUL_SHUTDOWN_TIME:
41
+ job_ids = (await session.execute(stm_ids)).scalars().all()
42
+ if len(job_ids) == 0:
43
+ logger.info("All jobs are either done or failed. Exit.")
44
44
  return
45
45
  else:
46
- logger.info(f"Some jobs are still 'submitted' {jobsV2_db=}")
46
+ logger.info(f"Some jobs are still 'submitted': {job_ids=}")
47
+ logger.info(f"Wait {interval:.4f} seconds before next check.")
48
+ time.sleep(interval)
47
49
  logger.info(
48
50
  "Graceful shutdown reached its maximum time, "
49
- "but some jobs are still submitted"
51
+ "but some jobs are still submitted."
50
52
  )
51
53
 
52
- for job in jobsV2_db:
54
+ # Mark jobs as failed and update their logs.
55
+ jobs = (await session.execute(stm_objects)).scalars().all()
56
+ for job in jobs:
53
57
  job.status = "failed"
54
58
  job.log = (job.log or "") + "\nJob stopped due to app shutdown\n"
55
59
  session.add(job)
@@ -1,4 +1,5 @@
1
1
  from pydantic import SecretStr
2
+ from pydantic.types import NonNegativeInt
2
3
  from pydantic_settings import BaseSettings
3
4
  from pydantic_settings import SettingsConfigDict
4
5
  from sqlalchemy.engine import URL
@@ -27,11 +28,11 @@ class DatabaseSettings(BaseSettings):
27
28
  """
28
29
  Password to use when connecting to the PostgreSQL database.
29
30
  """
30
- POSTGRES_HOST: NonEmptyStr | None = "localhost"
31
+ POSTGRES_HOST: NonEmptyStr = "localhost"
31
32
  """
32
33
  URL to the PostgreSQL server or path to a UNIX domain socket.
33
34
  """
34
- POSTGRES_PORT: NonEmptyStr | None = "5432"
35
+ POSTGRES_PORT: NonNegativeInt = 5432
35
36
  """
36
37
  Port number to use when connecting to the PostgreSQL server.
37
38
  """
@@ -57,7 +57,7 @@ class Settings(BaseSettings):
57
57
  `app.state`.
58
58
  """
59
59
 
60
- FRACTAL_GRACEFUL_SHUTDOWN_TIME: int = 30
60
+ FRACTAL_GRACEFUL_SHUTDOWN_TIME: float = 30.0
61
61
  """
62
62
  Waiting time for the shutdown phase of executors
63
63
  """
@@ -0,0 +1,46 @@
1
+ """Make resource_id FK non-nullable
2
+
3
+ Revision ID: 45fbb391d7af
4
+ Revises: caba9fb1ea5e
5
+ Create Date: 2025-11-11 16:39:12.813766
6
+
7
+ """
8
+ import sqlalchemy as sa
9
+ from alembic import op
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "45fbb391d7af"
14
+ down_revision = "caba9fb1ea5e"
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("projectv2", schema=None) as batch_op:
22
+ batch_op.alter_column(
23
+ "resource_id", existing_type=sa.INTEGER(), nullable=False
24
+ )
25
+
26
+ with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
27
+ batch_op.alter_column(
28
+ "resource_id", existing_type=sa.INTEGER(), nullable=False
29
+ )
30
+
31
+ # ### end Alembic commands ###
32
+
33
+
34
+ def downgrade() -> None:
35
+ # ### commands auto generated by Alembic - please adjust! ###
36
+ with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
37
+ batch_op.alter_column(
38
+ "resource_id", existing_type=sa.INTEGER(), nullable=True
39
+ )
40
+
41
+ with op.batch_alter_table("projectv2", schema=None) as batch_op:
42
+ batch_op.alter_column(
43
+ "resource_id", existing_type=sa.INTEGER(), nullable=True
44
+ )
45
+
46
+ # ### end Alembic commands ###
@@ -0,0 +1,63 @@
1
+ """Drop table
2
+
3
+ Revision ID: 49d0856e9569
4
+ Revises: 45fbb391d7af
5
+ Create Date: 2025-11-11 16:39:41.497832
6
+
7
+ """
8
+ import sqlalchemy as sa
9
+ from alembic import op
10
+ from sqlalchemy.dialects import postgresql
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "49d0856e9569"
14
+ down_revision = "45fbb391d7af"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade() -> None:
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.drop_table("user_settings")
22
+ # ### end Alembic commands ###
23
+
24
+
25
+ def downgrade() -> None:
26
+ # ### commands auto generated by Alembic - please adjust! ###
27
+ op.create_table(
28
+ "user_settings",
29
+ sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
30
+ sa.Column(
31
+ "slurm_accounts",
32
+ postgresql.JSONB(astext_type=sa.Text()),
33
+ server_default=sa.text("'[]'::json"),
34
+ autoincrement=False,
35
+ nullable=False,
36
+ ),
37
+ sa.Column(
38
+ "ssh_host", sa.VARCHAR(), autoincrement=False, nullable=True
39
+ ),
40
+ sa.Column(
41
+ "ssh_username", sa.VARCHAR(), autoincrement=False, nullable=True
42
+ ),
43
+ sa.Column(
44
+ "ssh_private_key_path",
45
+ sa.VARCHAR(),
46
+ autoincrement=False,
47
+ nullable=True,
48
+ ),
49
+ sa.Column(
50
+ "ssh_tasks_dir", sa.VARCHAR(), autoincrement=False, nullable=True
51
+ ),
52
+ sa.Column(
53
+ "ssh_jobs_dir", sa.VARCHAR(), autoincrement=False, nullable=True
54
+ ),
55
+ sa.Column(
56
+ "slurm_user", sa.VARCHAR(), autoincrement=False, nullable=True
57
+ ),
58
+ sa.Column(
59
+ "project_dir", sa.VARCHAR(), autoincrement=False, nullable=True
60
+ ),
61
+ sa.PrimaryKeyConstraint("id", name=op.f("pk_user_settings")),
62
+ )
63
+ # ### end Alembic commands ###
@@ -0,0 +1,29 @@
1
+ """Remove project_dir server_default
2
+
3
+ Revision ID: 7673fe18c05d
4
+ Revises: 49d0856e9569
5
+ Create Date: 2025-11-11 16:50:20.079193
6
+
7
+ """
8
+ from alembic import op
9
+
10
+
11
+ # revision identifiers, used by Alembic.
12
+ revision = "7673fe18c05d"
13
+ down_revision = "49d0856e9569"
14
+ branch_labels = None
15
+ depends_on = None
16
+
17
+
18
+ def upgrade() -> None:
19
+ """
20
+ Remove `server_default` for `project_dir` column - see
21
+ https://alembic.sqlalchemy.org/en/latest/ops.html#alembic.operations.Operations.alter_column.params.server_default
22
+ """
23
+ with op.batch_alter_table("user_oauth") as batch_op:
24
+ batch_op.alter_column("project_dir", server_default=None)
25
+
26
+
27
+ def downgrade() -> None:
28
+ with op.batch_alter_table("user_oauth") as batch_op:
29
+ batch_op.alter_column("project_dir", server_default="/PLACEHOLDER")
@@ -0,0 +1,49 @@
1
+ """Drop UserOAuth.user_settings_id
2
+
3
+ Revision ID: caba9fb1ea5e
4
+ Revises: 83bc2ad3ffcc
5
+ Create Date: 2025-11-11 16:38:27.243693
6
+
7
+ """
8
+ import sqlalchemy as sa
9
+ from alembic import op
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "caba9fb1ea5e"
14
+ down_revision = "83bc2ad3ffcc"
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("user_oauth", schema=None) as batch_op:
22
+ batch_op.drop_constraint(
23
+ batch_op.f("fk_user_oauth_user_settings_id_user_settings"),
24
+ type_="foreignkey",
25
+ )
26
+ batch_op.drop_column("user_settings_id")
27
+
28
+ # ### end Alembic commands ###
29
+
30
+
31
+ def downgrade() -> None:
32
+ # ### commands auto generated by Alembic - please adjust! ###
33
+ with op.batch_alter_table("user_oauth", schema=None) as batch_op:
34
+ batch_op.add_column(
35
+ sa.Column(
36
+ "user_settings_id",
37
+ sa.INTEGER(),
38
+ autoincrement=False,
39
+ nullable=True,
40
+ )
41
+ )
42
+ batch_op.create_foreign_key(
43
+ batch_op.f("fk_user_oauth_user_settings_id_user_settings"),
44
+ "user_settings",
45
+ ["user_settings_id"],
46
+ ["id"],
47
+ )
48
+
49
+ # ### end Alembic commands ###