fractal-server 2.17.0a11__tar.gz → 2.17.1a0__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 (262) hide show
  1. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/PKG-INFO +1 -1
  2. fractal_server-2.17.1a0/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/__main__.py +1 -1
  4. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/job.py +45 -9
  5. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/task.py +49 -32
  6. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/task_collection.py +11 -3
  7. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/config/_database.py +3 -2
  8. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/data_migrations/2_17_0.py +64 -46
  9. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/runner.py +24 -0
  10. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/config/_python.py +1 -1
  11. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/pyproject.toml +2 -2
  12. fractal_server-2.17.0a11/fractal_server/__init__.py +0 -1
  13. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/LICENSE +0 -0
  14. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/README.md +0 -0
  15. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/alembic.ini +0 -0
  16. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/__init__.py +0 -0
  17. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/db/__init__.py +0 -0
  18. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/__init__.py +0 -0
  19. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/linkusergroup.py +0 -0
  20. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/linkuserproject.py +0 -0
  21. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/security.py +0 -0
  22. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/user_settings.py +0 -0
  23. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/__init__.py +0 -0
  24. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/accounting.py +0 -0
  25. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/dataset.py +0 -0
  26. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/history.py +0 -0
  27. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/job.py +0 -0
  28. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/profile.py +0 -0
  29. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/project.py +0 -0
  30. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/resource.py +0 -0
  31. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/task.py +0 -0
  32. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/task_group.py +0 -0
  33. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/workflow.py +0 -0
  34. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/workflowtask.py +0 -0
  35. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/__init__.py +0 -0
  36. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/__init__.py +0 -0
  37. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  38. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/_aux_functions.py +0 -0
  39. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  40. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  41. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/profile.py +0 -0
  42. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/project.py +0 -0
  43. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/resource.py +0 -0
  44. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  45. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  46. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/__init__.py +0 -0
  47. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  48. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  49. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  50. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  51. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  52. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  53. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
  54. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  55. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/history.py +0 -0
  56. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/images.py +0 -0
  57. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/job.py +0 -0
  58. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
  59. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/project.py +0 -0
  60. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  61. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/submit.py +0 -0
  62. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task.py +0 -0
  63. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  64. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  65. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
  66. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  67. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  68. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
  69. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  70. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  71. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  72. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/__init__.py +0 -0
  73. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  74. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/current_user.py +0 -0
  75. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/group.py +0 -0
  76. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/login.py +0 -0
  77. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/oauth.py +0 -0
  78. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/register.py +0 -0
  79. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/router.py +0 -0
  80. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/users.py +0 -0
  81. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/__init__.py +0 -0
  82. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/_job.py +0 -0
  83. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/_runner.py +0 -0
  84. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/validate_user_profile.py +0 -0
  85. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/routes/pagination.py +0 -0
  86. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/__init__.py +0 -0
  87. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/user.py +0 -0
  88. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/user_group.py +0 -0
  89. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/__init__.py +0 -0
  90. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/accounting.py +0 -0
  91. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/dataset.py +0 -0
  92. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/dumps.py +0 -0
  93. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/history.py +0 -0
  94. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/job.py +0 -0
  95. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/manifest.py +0 -0
  96. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/profile.py +0 -0
  97. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/project.py +0 -0
  98. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/resource.py +0 -0
  99. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  100. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/task.py +0 -0
  101. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/task_group.py +0 -0
  102. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/workflow.py +0 -0
  103. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  104. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/security/__init__.py +0 -0
  105. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/security/signup_email.py +0 -0
  106. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/app/shutdown.py +0 -0
  107. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/config/__init__.py +0 -0
  108. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/config/_data.py +0 -0
  109. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/config/_email.py +0 -0
  110. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/config/_main.py +0 -0
  111. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/config/_oauth.py +0 -0
  112. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/config/_settings_config.py +0 -0
  113. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/data_migrations/README.md +0 -0
  114. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/data_migrations/tools.py +0 -0
  115. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/exceptions.py +0 -0
  116. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/gunicorn_fractal.py +0 -0
  117. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/images/__init__.py +0 -0
  118. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/images/models.py +0 -0
  119. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/images/status_tools.py +0 -0
  120. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/images/tools.py +0 -0
  121. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/logger.py +0 -0
  122. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/main.py +0 -0
  123. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/env.py +0 -0
  124. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/naming_convention.py +0 -0
  125. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  126. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  127. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
  128. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  129. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
  130. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  131. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  132. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  133. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  134. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  135. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  136. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  137. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  138. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  139. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  140. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
  141. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +0 -0
  142. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  143. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  144. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  145. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  146. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
  147. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  148. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
  149. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  150. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  151. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  152. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  153. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  154. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  155. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  156. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
  157. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
  158. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  159. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  160. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  161. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  162. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  163. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  164. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  165. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  166. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  167. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  168. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  169. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/py.typed +0 -0
  170. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/__init__.py +0 -0
  171. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/components.py +0 -0
  172. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/config/__init__.py +0 -0
  173. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/config/_local.py +0 -0
  174. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/config/_slurm.py +0 -0
  175. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/config/slurm_mem_to_MB.py +0 -0
  176. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/exceptions.py +0 -0
  177. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/__init__.py +0 -0
  178. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/base_runner.py +0 -0
  179. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/call_command_wrapper.py +0 -0
  180. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/local/__init__.py +0 -0
  181. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/local/get_local_config.py +0 -0
  182. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/local/runner.py +0 -0
  183. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/__init__.py +0 -0
  184. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/_batching.py +0 -0
  185. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/_job_states.py +0 -0
  186. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  187. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/get_slurm_config.py +0 -0
  188. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/remote.py +0 -0
  189. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/slurm_config.py +0 -0
  190. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  191. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/__init__.py +0 -0
  192. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  193. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/runner.py +0 -0
  194. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/tar_commands.py +0 -0
  195. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_sudo/__init__.py +0 -0
  196. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  197. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_sudo/runner.py +0 -0
  198. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/filenames.py +0 -0
  199. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/set_start_and_last_task_index.py +0 -0
  200. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/task_files.py +0 -0
  201. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/__init__.py +0 -0
  202. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/_local.py +0 -0
  203. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/_slurm_ssh.py +0 -0
  204. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/_slurm_sudo.py +0 -0
  205. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/db_tools.py +0 -0
  206. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/deduplicate_list.py +0 -0
  207. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/merge_outputs.py +0 -0
  208. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/runner_functions.py +0 -0
  209. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/submit_workflow.py +0 -0
  210. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/v2/task_interface.py +0 -0
  211. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/runner/versions.py +0 -0
  212. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/ssh/__init__.py +0 -0
  213. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/ssh/_fabric.py +0 -0
  214. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/string_tools.py +0 -0
  215. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/syringe.py +0 -0
  216. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/__init__.py +0 -0
  217. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/config/__init__.py +0 -0
  218. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/config/_pixi.py +0 -0
  219. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/utils.py +0 -0
  220. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/__init__.py +0 -0
  221. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/__init__.py +0 -0
  222. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/_utils.py +0 -0
  223. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/collect.py +0 -0
  224. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/collect_pixi.py +0 -0
  225. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  226. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
  227. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/delete.py +1 -1
  228. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  229. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
  230. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  231. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -0
  232. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  233. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/collect.py +0 -0
  234. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/collect_pixi.py +0 -0
  235. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  236. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
  237. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/delete.py +0 -0
  238. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  239. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +0 -0
  240. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  241. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  242. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  243. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  244. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  245. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  246. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
  247. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
  248. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -0
  249. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_background.py +0 -0
  250. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_database.py +0 -0
  251. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  252. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_pixi.py +0 -0
  253. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  254. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_templates.py +0 -0
  255. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/types/__init__.py +0 -0
  256. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/types/validators/__init__.py +0 -0
  257. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/types/validators/_common_validators.py +0 -0
  258. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/types/validators/_filter_validators.py +0 -0
  259. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
  260. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/urls.py +0 -0
  261. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/fractal_server/utils.py +0 -0
  262. {fractal_server-2.17.0a11 → fractal_server-2.17.1a0}/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.1a0
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.1a0"
@@ -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()
@@ -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
 
@@ -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
  """
@@ -1,28 +1,9 @@
1
- """
2
-
3
- PRELIMINARY CHECKS (TO DO WITH 2.16)
4
- * All users who are meant to actually use Fractal must be marked as active and verified.
5
- * All users who are not active and verified will still be able to log in, but they won't have access to the rest of the API.
6
- * All active users must have `project_dir` set, in their user settings.
7
- * `FRACTAL_SLURM_WORKER_PYTHON` must be included explicitly in the old env file.
8
-
9
- DATA-MIGRATION REQUIREMENTS
10
- * Old `.fractal_server.env`, renamed into `.fractal_server.env.old`.
11
- * New `.fractal_server.env` - see XXX for list of changes.
12
- * Old JSON file with SLURM configuration.
13
- * Old JSON file with pixi configuration - if applicable.
14
-
15
-
16
- MANUAL FIXES POST DATA MIGRATION:
17
- * Rename resource
18
- * Rename profiles - if needed
19
- """
20
1
  import json
21
2
  import logging
22
3
  import sys
4
+ from pathlib import Path
23
5
  from typing import Any
24
6
 
25
- from devtools import debug
26
7
  from dotenv.main import DotEnv
27
8
  from pydantic import BaseModel
28
9
  from sqlalchemy.orm import Session
@@ -40,6 +21,7 @@ from fractal_server.app.models import UserSettings
40
21
  from fractal_server.app.schemas.v2.profile import cast_serialize_profile
41
22
  from fractal_server.app.schemas.v2.resource import cast_serialize_resource
42
23
  from fractal_server.config import get_settings
24
+ from fractal_server.runner.config import JobRunnerConfigLocal
43
25
  from fractal_server.runner.config import JobRunnerConfigSLURM
44
26
  from fractal_server.tasks.config import TasksPixiSettings
45
27
  from fractal_server.tasks.config import TasksPythonSettings
@@ -47,8 +29,7 @@ from fractal_server.types import AbsolutePathStr
47
29
  from fractal_server.types import ListUniqueNonEmptyString
48
30
  from fractal_server.urls import normalize_url
49
31
 
50
- logger = logging.getLogger("fix_db")
51
- logger.setLevel(logging.INFO)
32
+ logging.basicConfig(level=logging.INFO)
52
33
 
53
34
 
54
35
  class UserUpdateInfo(BaseModel):
@@ -100,6 +81,8 @@ def prepare_profile_and_user_updates() -> dict[str, ProfileUsersUpdateInfo]:
100
81
 
101
82
  # Prepare profile data and user update
102
83
  new_profile_data = dict()
84
+ if settings.FRACTAL_RUNNER_BACKEND == "local":
85
+ username = None
103
86
  if settings.FRACTAL_RUNNER_BACKEND == "slurm_sudo":
104
87
  assert_user_setting_key(user, user_settings, ["slurm_user"])
105
88
  username = user_settings.slurm_user
@@ -128,7 +111,6 @@ def prepare_profile_and_user_updates() -> dict[str, ProfileUsersUpdateInfo]:
128
111
  username=username,
129
112
  resource_type=settings.FRACTAL_RUNNER_BACKEND,
130
113
  )
131
- debug(new_profile_data)
132
114
  cast_serialize_profile(new_profile_data)
133
115
 
134
116
  user_update_info = UserUpdateInfo(
@@ -139,10 +121,13 @@ def prepare_profile_and_user_updates() -> dict[str, ProfileUsersUpdateInfo]:
139
121
 
140
122
  if username in profiles_and_users.keys():
141
123
  if profiles_and_users[username].data != new_profile_data:
142
- # FIXME
143
- debug(new_profile_data)
144
- debug(profiles_and_users[username].data)
145
- raise ValueError()
124
+ error_msg = (
125
+ "Profile data mismatch.\n"
126
+ f"{profiles_and_users[username].data=}\n"
127
+ f"{new_profile_data=}"
128
+ )
129
+ logging.error(error_msg)
130
+ sys.exit(error_msg)
146
131
  profiles_and_users[username].user_updates.append(
147
132
  user_update_info
148
133
  )
@@ -207,6 +192,19 @@ def get_JobRunnerConfigSLURM(
207
192
  return old_slurm_config
208
193
 
209
194
 
195
+ def get_JobRunnerConfigLocal(
196
+ old_config: dict[str, str | None]
197
+ ) -> dict[str, Any]:
198
+ local_file = old_config.get("FRACTAL_LOCAL_CONFIG_FILE", None)
199
+ if local_file is None or not Path(local_file).exists():
200
+ return JobRunnerConfigLocal().model_dump()
201
+ else:
202
+ with open(local_file) as f:
203
+ old_local_config = json.load(f)
204
+ JobRunnerConfigLocal(**old_local_config)
205
+ return old_local_config
206
+
207
+
210
208
  def get_ssh_host() -> str:
211
209
  with next(get_sync_db()) as db:
212
210
  res = db.execute(
@@ -231,15 +229,30 @@ def prepare_resource_data(old_config: dict[str, str | None]) -> dict[str, Any]:
231
229
  name="Resource Name",
232
230
  tasks_python_config=get_TasksPythonSettings(old_config),
233
231
  tasks_pixi_config=get_TasksPixiSettings(old_config),
234
- jobs_runner_config=get_JobRunnerConfigSLURM(old_config),
235
232
  tasks_local_dir=old_config["FRACTAL_TASKS_DIR"],
236
233
  jobs_local_dir=old_config["FRACTAL_RUNNER_WORKING_BASE_DIR"],
237
- jobs_slurm_python_worker=old_config["FRACTAL_SLURM_WORKER_PYTHON"],
238
234
  jobs_poll_interval=int(
239
235
  old_config.get("FRACTAL_SLURM_POLL_INTERVAL", 15)
240
236
  ),
241
237
  )
242
- if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
238
+ if settings.FRACTAL_RUNNER_BACKEND == "local":
239
+ resource_data["jobs_runner_config"] = get_JobRunnerConfigLocal(
240
+ old_config
241
+ )
242
+ elif settings.FRACTAL_RUNNER_BACKEND == "slurm_sudo":
243
+ resource_data["jobs_slurm_python_worker"] = old_config[
244
+ "FRACTAL_SLURM_WORKER_PYTHON"
245
+ ]
246
+ resource_data["jobs_runner_config"] = get_JobRunnerConfigSLURM(
247
+ old_config
248
+ )
249
+ else:
250
+ resource_data["jobs_slurm_python_worker"] = old_config[
251
+ "FRACTAL_SLURM_WORKER_PYTHON"
252
+ ]
253
+ resource_data["jobs_runner_config"] = get_JobRunnerConfigSLURM(
254
+ old_config
255
+ )
243
256
  resource_data["host"] = get_ssh_host()
244
257
 
245
258
  resource_data = cast_serialize_resource(resource_data)
@@ -248,29 +261,23 @@ def prepare_resource_data(old_config: dict[str, str | None]) -> dict[str, Any]:
248
261
 
249
262
 
250
263
  def fix_db():
251
- # READ-ONLY CHECK
252
-
253
- settings = get_settings()
254
-
255
- # Verify that we are in a SLURM instance
256
- if settings.FRACTAL_RUNNER_BACKEND == "local":
257
- sys.exit(
258
- "ERROR: FRACTAL_RUNNER_BACKEND='local' is not "
259
- "supported for this data migration."
260
- )
264
+ logging.info("START preliminary checks.")
261
265
 
262
266
  # Read old env file
263
267
  old_config = get_old_dotenv_variables()
264
268
 
265
269
  # Prepare resource data
270
+ logging.info("START prepare_resource_data")
266
271
  resource_data = prepare_resource_data(old_config)
272
+ logging.info("END prepare_resource_data")
267
273
 
268
274
  # Prepare profile/users data
275
+ logging.info("START prepare_profile_and_user_updates")
269
276
  profile_and_user_updates = prepare_profile_and_user_updates()
277
+ logging.info("END prepare_profile_and_user_updates")
270
278
 
271
- # ---------------------------------------
272
-
273
- # WRITES
279
+ logging.info("END preliminary checks.")
280
+ print()
274
281
 
275
282
  with next(get_sync_db()) as db:
276
283
  # Create new resource
@@ -280,7 +287,7 @@ def fix_db():
280
287
  db.refresh(resource)
281
288
  db.expunge(resource)
282
289
  resource_id = resource.id
283
- debug(f"CREATED RESOURCE with {resource_id=}")
290
+ logging.info(f"Created resource with {resource_id=}.")
284
291
 
285
292
  # Update task groups
286
293
  res = db.execute(select(TaskGroupV2).order_by(TaskGroupV2.id))
@@ -288,6 +295,7 @@ def fix_db():
288
295
  taskgroup.resource_id = resource_id
289
296
  db.add(taskgroup)
290
297
  db.commit()
298
+ logging.info(f"Set {resource_id=} foreign key for all task groups.")
291
299
 
292
300
  # Update projects
293
301
  res = db.execute(select(ProjectV2).order_by(ProjectV2.id))
@@ -295,12 +303,12 @@ def fix_db():
295
303
  project.resource_id = resource_id
296
304
  db.add(project)
297
305
  db.commit()
306
+ logging.info(f"Set {resource_id=} foreign key for all projects.")
307
+ print()
298
308
 
299
309
  db.expunge_all()
300
310
 
301
311
  for _, info in profile_and_user_updates.items():
302
- debug(info)
303
-
304
312
  # Create profile
305
313
  profile_data = info.data
306
314
  profile_data["resource_id"] = resource_id
@@ -310,6 +318,9 @@ def fix_db():
310
318
  db.refresh(profile)
311
319
  db.expunge(profile)
312
320
  profile_id = profile.id
321
+ logging.info(
322
+ f"Created profile '{profile.name}', with {profile.id=}."
323
+ )
313
324
 
314
325
  # Update users
315
326
  for user_update in info.user_updates:
@@ -318,4 +329,11 @@ def fix_db():
318
329
  user.project_dir = user_update.project_dir
319
330
  user.slurm_accounts = user_update.slurm_accounts
320
331
  db.add(user)
332
+ logging.info(f"Updated {user.email} with {user.project_dir=}.")
333
+ logging.info(
334
+ f"Associated {user.email} to profile {profile.name}."
335
+ )
336
+ print()
321
337
  db.commit()
338
+
339
+ logging.info("END - all ok.")
@@ -192,6 +192,30 @@ def execute_tasks_v2(
192
192
  job_db.executor_error_log = None
193
193
  db.merge(job_db)
194
194
  db.commit()
195
+ db.expunge_all()
196
+
197
+ # Fail when running a non-converter task on an empty image list
198
+ if (
199
+ wftask.task_type
200
+ in [
201
+ TaskType.COMPOUND,
202
+ TaskType.PARALLEL,
203
+ TaskType.NON_PARALLEL,
204
+ ]
205
+ and len(filtered_images) == 0
206
+ ):
207
+ error_msg = (
208
+ f"Cannot run task '{task.name}' for an empty image list "
209
+ f"(obtained after applying {type_filters=} and "
210
+ f"attribute_filters={job_attribute_filters})."
211
+ )
212
+ logger.info(error_msg)
213
+ update_status_of_history_run(
214
+ history_run_id=history_run_id,
215
+ status=HistoryUnitStatus.FAILED,
216
+ db_sync=db,
217
+ )
218
+ raise JobExecutionError(error_msg)
195
219
 
196
220
  # TASK EXECUTION (V2)
197
221
  try:
@@ -45,7 +45,7 @@ class TasksPythonSettings(BaseModel):
45
45
  if self.default_version not in self.versions.keys():
46
46
  raise ValueError(
47
47
  f"The default Python version ('{self.default_version}') is "
48
- f"not available versions in {list(self.versions.keys())}."
48
+ f"not available in {list(self.versions.keys())}."
49
49
  )
50
50
 
51
51
  return self
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fractal-server"
3
- version = "2.17.0a11"
3
+ version = "2.17.1a0"
4
4
  description = "Backend component of the Fractal analytics platform"
5
5
  authors = [
6
6
  { name="Tommaso Comparin", email="tommaso.comparin@exact-lab.it" },
@@ -94,7 +94,7 @@ filterwarnings = [
94
94
  markers = ["container", "ssh", "fails_on_macos", "oauth"]
95
95
 
96
96
  [tool.bumpver]
97
- current_version = "2.17.0a11"
97
+ current_version = "2.17.1a0"
98
98
  version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
99
99
  commit_message = "bump version {old_version} -> {new_version}"
100
100
  commit = true
@@ -1 +0,0 @@
1
- __VERSION__ = "2.17.0a11"