fractal-server 2.14.12__tar.gz → 2.14.13__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 (223) hide show
  1. {fractal_server-2.14.12 → fractal_server-2.14.13}/PKG-INFO +1 -1
  2. fractal_server-2.14.13/fractal_server/__init__.py +1 -0
  3. fractal_server-2.14.13/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +163 -0
  4. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/task_group.py +52 -4
  5. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/workflow_import.py +3 -70
  6. fractal_server-2.14.13/fractal_server/exceptions.py +2 -0
  7. {fractal_server-2.14.12 → fractal_server-2.14.13}/pyproject.toml +2 -2
  8. fractal_server-2.14.12/fractal_server/__init__.py +0 -1
  9. {fractal_server-2.14.12 → fractal_server-2.14.13}/LICENSE +0 -0
  10. {fractal_server-2.14.12 → fractal_server-2.14.13}/README.md +0 -0
  11. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/__main__.py +0 -0
  12. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/alembic.ini +0 -0
  13. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/__init__.py +0 -0
  14. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/db/__init__.py +0 -0
  15. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/__init__.py +0 -0
  16. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/linkusergroup.py +0 -0
  17. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/linkuserproject.py +0 -0
  18. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/security.py +0 -0
  19. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/user_settings.py +0 -0
  20. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/__init__.py +0 -0
  21. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/accounting.py +0 -0
  22. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/dataset.py +0 -0
  23. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/history.py +0 -0
  24. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/job.py +0 -0
  25. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/project.py +0 -0
  26. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/task.py +0 -0
  27. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/task_group.py +0 -0
  28. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/workflow.py +0 -0
  29. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/models/v2/workflowtask.py +0 -0
  30. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/__init__.py +0 -0
  31. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/__init__.py +0 -0
  32. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  33. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  34. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  35. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/job.py +0 -0
  36. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/project.py +0 -0
  37. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/task.py +0 -0
  38. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  39. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  40. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/__init__.py +0 -0
  41. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  42. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  43. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  44. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  45. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  46. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  47. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  48. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/history.py +0 -0
  49. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/images.py +0 -0
  50. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/job.py +0 -0
  51. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
  52. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/project.py +0 -0
  53. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  54. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/submit.py +0 -0
  55. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/task.py +0 -0
  56. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  57. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  58. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  59. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
  60. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  61. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  62. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/__init__.py +0 -0
  63. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  64. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/current_user.py +0 -0
  65. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/group.py +0 -0
  66. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/login.py +0 -0
  67. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/oauth.py +0 -0
  68. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/register.py +0 -0
  69. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/router.py +0 -0
  70. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/auth/users.py +0 -0
  71. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/aux/__init__.py +0 -0
  72. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/aux/_job.py +0 -0
  73. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/aux/_runner.py +0 -0
  74. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  75. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/routes/pagination.py +0 -0
  76. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/__init__.py +0 -0
  77. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/components.py +0 -0
  78. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/exceptions.py +0 -0
  79. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/__init__.py +0 -0
  80. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/base_runner.py +0 -0
  81. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/call_command_wrapper.py +0 -0
  82. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/local/__init__.py +0 -0
  83. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/local/get_local_config.py +0 -0
  84. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/local/runner.py +0 -0
  85. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/__init__.py +0 -0
  86. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/_batching.py +0 -0
  87. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/_job_states.py +0 -0
  88. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/_slurm_config.py +0 -0
  89. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  90. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +0 -0
  91. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/remote.py +0 -0
  92. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  93. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_ssh/__init__.py +0 -0
  94. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  95. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_ssh/runner.py +0 -0
  96. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_ssh/tar_commands.py +0 -0
  97. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_sudo/__init__.py +0 -0
  98. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  99. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/executors/slurm_sudo/runner.py +0 -0
  100. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/filenames.py +0 -0
  101. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  102. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/shutdown.py +0 -0
  103. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/task_files.py +0 -0
  104. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/__init__.py +0 -0
  105. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/_local.py +0 -0
  106. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/_slurm_ssh.py +0 -0
  107. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/_slurm_sudo.py +0 -0
  108. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/db_tools.py +0 -0
  109. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  110. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  111. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/runner.py +0 -0
  112. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  113. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/submit_workflow.py +0 -0
  114. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/v2/task_interface.py +0 -0
  115. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/runner/versions.py +0 -0
  116. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/__init__.py +0 -0
  117. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/user.py +0 -0
  118. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/user_group.py +0 -0
  119. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/user_settings.py +0 -0
  120. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/__init__.py +0 -0
  121. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/accounting.py +0 -0
  122. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/dataset.py +0 -0
  123. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/dumps.py +0 -0
  124. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/history.py +0 -0
  125. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/job.py +0 -0
  126. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/manifest.py +0 -0
  127. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/project.py +0 -0
  128. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  129. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/task.py +0 -0
  130. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  131. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/task_group.py +0 -0
  132. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/workflow.py +0 -0
  133. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  134. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/security/__init__.py +0 -0
  135. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/security/signup_email.py +0 -0
  136. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/app/user_settings.py +0 -0
  137. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/config.py +0 -0
  138. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/data_migrations/2_14_10.py +0 -0
  139. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/data_migrations/README.md +0 -0
  140. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/data_migrations/tools.py +0 -0
  141. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/gunicorn_fractal.py +0 -0
  142. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/images/__init__.py +0 -0
  143. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/images/models.py +0 -0
  144. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/images/status_tools.py +0 -0
  145. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/images/tools.py +0 -0
  146. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/logger.py +0 -0
  147. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/main.py +0 -0
  148. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/env.py +0 -0
  149. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/naming_convention.py +0 -0
  150. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  151. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  152. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  153. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  154. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  155. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  156. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  157. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  158. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  159. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  160. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  161. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  162. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  163. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  164. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  165. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  166. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  167. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
  168. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  169. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  170. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  171. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  172. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  173. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  174. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  175. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  176. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  177. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  178. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  179. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  180. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  181. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  182. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  183. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  184. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  185. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  186. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  187. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/py.typed +0 -0
  188. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/ssh/__init__.py +0 -0
  189. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/ssh/_fabric.py +0 -0
  190. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/string_tools.py +0 -0
  191. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/syringe.py +0 -0
  192. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/__init__.py +0 -0
  193. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/utils.py +0 -0
  194. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/__init__.py +0 -0
  195. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/local/__init__.py +0 -0
  196. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/local/_utils.py +0 -0
  197. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/local/collect.py +0 -0
  198. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  199. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  200. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  201. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  202. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/ssh/collect.py +0 -0
  203. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  204. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  205. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  206. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  207. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  208. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  209. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  210. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  211. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/utils_background.py +0 -0
  212. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/utils_database.py +0 -0
  213. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  214. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  215. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/tasks/v2/utils_templates.py +0 -0
  216. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/types/__init__.py +0 -0
  217. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/types/validators/__init__.py +0 -0
  218. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/types/validators/_common_validators.py +0 -0
  219. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/types/validators/_filter_validators.py +0 -0
  220. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
  221. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/urls.py +0 -0
  222. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/utils.py +0 -0
  223. {fractal_server-2.14.12 → fractal_server-2.14.13}/fractal_server/zip_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fractal-server
3
- Version: 2.14.12
3
+ Version: 2.14.13
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License: BSD-3-Clause
6
6
  Author: Tommaso Comparin
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.14.13"
@@ -0,0 +1,163 @@
1
+ import itertools
2
+
3
+ from sqlmodel import select
4
+
5
+ from fractal_server.app.db import AsyncSession
6
+ from fractal_server.app.models import LinkUserGroup
7
+ from fractal_server.app.models.v2 import TaskGroupV2
8
+ from fractal_server.exceptions import UnreachableBranchError
9
+ from fractal_server.logger import set_logger
10
+
11
+
12
+ logger = set_logger(__name__)
13
+
14
+
15
+ async def _disambiguate_task_groups(
16
+ *,
17
+ matching_task_groups: list[TaskGroupV2],
18
+ user_id: int,
19
+ default_group_id: int,
20
+ db: AsyncSession,
21
+ ) -> TaskGroupV2 | None:
22
+ """
23
+ Find ownership-based top-priority task group, if any.
24
+
25
+ Args:
26
+ matching_task_groups:
27
+ user_id:
28
+ default_group_id:
29
+ db:
30
+
31
+ Returns:
32
+ The task group or `None`.
33
+ """
34
+
35
+ # Highest priority: task groups created by user
36
+ list_user_ids = [tg.user_id for tg in matching_task_groups]
37
+ try:
38
+ ind_user_id = list_user_ids.index(user_id)
39
+ task_group = matching_task_groups[ind_user_id]
40
+ logger.debug(
41
+ "[_disambiguate_task_groups] "
42
+ f"Found task group {task_group.id} with {user_id=}, return."
43
+ )
44
+ return task_group
45
+ except ValueError:
46
+ logger.debug(
47
+ "[_disambiguate_task_groups] "
48
+ f"No task group with {user_id=}, continue."
49
+ )
50
+
51
+ # Medium priority: task groups owned by default user group
52
+ list_user_group_ids = [tg.user_group_id for tg in matching_task_groups]
53
+ try:
54
+ ind_user_group_id = list_user_group_ids.index(default_group_id)
55
+ task_group = matching_task_groups[ind_user_group_id]
56
+ logger.debug(
57
+ "[_disambiguate_task_groups] "
58
+ f"Found task group {task_group.id} with {user_id=}, return."
59
+ )
60
+ return task_group
61
+ except ValueError:
62
+ logger.debug(
63
+ "[_disambiguate_task_groups] "
64
+ "No task group with user_group_id="
65
+ f"{default_group_id}, continue."
66
+ )
67
+
68
+ # Lowest priority: task groups owned by other groups, sorted
69
+ # according to age of the user/usergroup link
70
+ logger.debug(
71
+ "[_disambiguate_task_groups] "
72
+ "Sort remaining task groups by oldest-user-link."
73
+ )
74
+ stm = (
75
+ select(LinkUserGroup.group_id)
76
+ .where(LinkUserGroup.user_id == user_id)
77
+ .where(LinkUserGroup.group_id.in_(list_user_group_ids))
78
+ .order_by(LinkUserGroup.timestamp_created.asc())
79
+ )
80
+ res = await db.execute(stm)
81
+ oldest_user_group_id = res.scalars().first()
82
+ logger.debug(
83
+ "[_disambiguate_task_groups] " f"Result: {oldest_user_group_id=}."
84
+ )
85
+ task_group = next(
86
+ iter(
87
+ task_group
88
+ for task_group in matching_task_groups
89
+ if task_group.user_group_id == oldest_user_group_id
90
+ ),
91
+ None,
92
+ )
93
+ return task_group
94
+
95
+
96
+ async def _disambiguate_task_groups_not_none(
97
+ *,
98
+ matching_task_groups: list[TaskGroupV2],
99
+ user_id: int,
100
+ default_group_id: int,
101
+ db: AsyncSession,
102
+ ) -> TaskGroupV2:
103
+ """
104
+ Find ownership-based top-priority task group, and fail otherwise.
105
+
106
+ Args:
107
+ matching_task_groups:
108
+ user_id:
109
+ default_group_id:
110
+ db:
111
+
112
+ Returns:
113
+ The top-priority task group.
114
+ """
115
+ task_group = await _disambiguate_task_groups(
116
+ matching_task_groups=matching_task_groups,
117
+ user_id=user_id,
118
+ default_group_id=default_group_id,
119
+ db=db,
120
+ )
121
+ if task_group is None:
122
+ error_msg = (
123
+ "[_disambiguate_task_groups_not_none] Could not find a task "
124
+ f"group ({user_id=}, {default_group_id=})."
125
+ )
126
+ logger.error(f"UnreachableBranchError {error_msg}")
127
+ raise UnreachableBranchError(error_msg)
128
+ else:
129
+ return task_group
130
+
131
+
132
+ async def remove_duplicate_task_groups(
133
+ *,
134
+ task_groups: list[TaskGroupV2],
135
+ user_id: int,
136
+ default_group_id: int,
137
+ db: AsyncSession,
138
+ ) -> list[TaskGroupV2]:
139
+ """
140
+ Extract a single task group for each `version`.
141
+
142
+ Args:
143
+ task_groups: A list of task groups with identical `pkg_name`
144
+ user_id: User ID
145
+
146
+ Returns:
147
+ New list of task groups with no duplicate `(pkg_name,version)` entries
148
+ """
149
+
150
+ new_task_groups = [
151
+ (
152
+ await _disambiguate_task_groups_not_none(
153
+ matching_task_groups=list(groups),
154
+ user_id=user_id,
155
+ default_group_id=default_group_id,
156
+ db=db,
157
+ )
158
+ )
159
+ for version, groups in itertools.groupby(
160
+ task_groups, key=lambda tg: tg.version
161
+ )
162
+ ]
163
+ return new_task_groups
@@ -1,8 +1,13 @@
1
+ import itertools
2
+
1
3
  from fastapi import APIRouter
2
4
  from fastapi import Depends
3
5
  from fastapi import HTTPException
4
6
  from fastapi import Response
5
7
  from fastapi import status
8
+ from packaging.version import InvalidVersion
9
+ from packaging.version import parse
10
+ from packaging.version import Version
6
11
  from pydantic.types import AwareDatetime
7
12
  from sqlmodel import or_
8
13
  from sqlmodel import select
@@ -10,6 +15,7 @@ from sqlmodel import select
10
15
  from ._aux_functions_tasks import _get_task_group_full_access
11
16
  from ._aux_functions_tasks import _get_task_group_read_access
12
17
  from ._aux_functions_tasks import _verify_non_duplication_group_constraint
18
+ from ._aux_task_group_disambiguation import remove_duplicate_task_groups
13
19
  from fractal_server.app.db import AsyncSession
14
20
  from fractal_server.app.db import get_async_db
15
21
  from fractal_server.app.models import LinkUserGroup
@@ -18,6 +24,7 @@ from fractal_server.app.models.v2 import TaskGroupActivityV2
18
24
  from fractal_server.app.models.v2 import TaskGroupV2
19
25
  from fractal_server.app.models.v2 import WorkflowTaskV2
20
26
  from fractal_server.app.routes.auth import current_active_user
27
+ from fractal_server.app.routes.auth._aux_auth import _get_default_usergroup_id
21
28
  from fractal_server.app.routes.auth._aux_auth import (
22
29
  _verify_user_belongs_to_group,
23
30
  )
@@ -33,6 +40,26 @@ router = APIRouter()
33
40
  logger = set_logger(__name__)
34
41
 
35
42
 
43
+ def _version_sort_key(
44
+ task_group: TaskGroupV2,
45
+ ) -> tuple[int, Version | str | None]:
46
+ """
47
+ Returns a tuple used as (reverse) ordering key for TaskGroups in
48
+ `get_task_group_list`.
49
+ The TaskGroups with a parsable versions are the first in order,
50
+ sorted according to the sorting rules of packaging.version.Version.
51
+ Next in order we have the TaskGroups with non-null non-parsable versions,
52
+ sorted alphabetically.
53
+ Last we have the TaskGroups with null version.
54
+ """
55
+ if task_group.version is None:
56
+ return (0, task_group.version)
57
+ try:
58
+ return (2, parse(task_group.version))
59
+ except InvalidVersion:
60
+ return (1, task_group.version)
61
+
62
+
36
63
  @router.get("/activity/", response_model=list[TaskGroupActivityV2Read])
37
64
  async def get_task_group_activity_list(
38
65
  task_group_activity_id: int | None = None,
@@ -97,14 +124,14 @@ async def get_task_group_activity(
97
124
  return activity
98
125
 
99
126
 
100
- @router.get("/", response_model=list[TaskGroupReadV2])
127
+ @router.get("/", response_model=list[tuple[str, list[TaskGroupReadV2]]])
101
128
  async def get_task_group_list(
102
129
  user: UserOAuth = Depends(current_active_user),
103
130
  db: AsyncSession = Depends(get_async_db),
104
131
  only_active: bool = False,
105
132
  only_owner: bool = False,
106
133
  args_schema: bool = True,
107
- ) -> list[TaskGroupReadV2]:
134
+ ) -> list[tuple[str, list[TaskGroupReadV2]]]:
108
135
  """
109
136
  Get all accessible TaskGroups
110
137
  """
@@ -119,7 +146,7 @@ async def get_task_group_list(
119
146
  )
120
147
  ),
121
148
  )
122
- stm = select(TaskGroupV2).where(condition)
149
+ stm = select(TaskGroupV2).where(condition).order_by(TaskGroupV2.pkg_name)
123
150
  if only_active:
124
151
  stm = stm.where(TaskGroupV2.active)
125
152
 
@@ -132,7 +159,28 @@ async def get_task_group_list(
132
159
  setattr(task, "args_schema_non_parallel", None)
133
160
  setattr(task, "args_schema_parallel", None)
134
161
 
135
- return task_groups
162
+ default_group_id = await _get_default_usergroup_id(db)
163
+ grouped_result = [
164
+ (
165
+ pkg_name,
166
+ sorted(
167
+ (
168
+ await remove_duplicate_task_groups(
169
+ task_groups=list(groups),
170
+ user_id=user.id,
171
+ default_group_id=default_group_id,
172
+ db=db,
173
+ )
174
+ ),
175
+ key=_version_sort_key,
176
+ reverse=True,
177
+ ),
178
+ )
179
+ for pkg_name, groups in itertools.groupby(
180
+ task_groups, key=lambda tg: tg.pkg_name
181
+ )
182
+ ]
183
+ return grouped_result
136
184
 
137
185
 
138
186
  @router.get("/{task_group_id}/", response_model=TaskGroupReadV2)
@@ -21,6 +21,9 @@ from ._aux_functions_tasks import _check_type_filters_compatibility
21
21
  from fractal_server.app.models import LinkUserGroup
22
22
  from fractal_server.app.models import UserOAuth
23
23
  from fractal_server.app.models.v2 import TaskGroupV2
24
+ from fractal_server.app.routes.api.v2._aux_task_group_disambiguation import (
25
+ _disambiguate_task_groups,
26
+ )
24
27
  from fractal_server.app.routes.auth import current_active_user
25
28
  from fractal_server.app.routes.auth._aux_auth import _get_default_usergroup_id
26
29
  from fractal_server.app.schemas.v2 import TaskImportV2
@@ -85,76 +88,6 @@ async def _get_task_by_source(
85
88
  return task_id
86
89
 
87
90
 
88
- async def _disambiguate_task_groups(
89
- *,
90
- matching_task_groups: list[TaskGroupV2],
91
- user_id: int,
92
- db: AsyncSession,
93
- default_group_id: int,
94
- ) -> TaskV2 | None:
95
- """
96
- Disambiguate task groups based on ownership information.
97
- """
98
- # Highest priority: task groups created by user
99
- for task_group in matching_task_groups:
100
- if task_group.user_id == user_id:
101
- logger.info(
102
- "[_disambiguate_task_groups] "
103
- f"Found task group {task_group.id} with {user_id=}, return."
104
- )
105
- return task_group
106
- logger.info(
107
- "[_disambiguate_task_groups] "
108
- f"No task group found with {user_id=}, continue."
109
- )
110
-
111
- # Medium priority: task groups owned by default user group
112
- for task_group in matching_task_groups:
113
- if task_group.user_group_id == default_group_id:
114
- logger.info(
115
- "[_disambiguate_task_groups] "
116
- f"Found task group {task_group.id} with user_group_id="
117
- f"{default_group_id}, return."
118
- )
119
- return task_group
120
- logger.info(
121
- "[_disambiguate_task_groups] "
122
- "No task group found with user_group_id="
123
- f"{default_group_id}, continue."
124
- )
125
-
126
- # Lowest priority: task groups owned by other groups, sorted
127
- # according to age of the user/usergroup link
128
- logger.info(
129
- "[_disambiguate_task_groups] "
130
- "Now sorting remaining task groups by oldest-user-link."
131
- )
132
- user_group_ids = [
133
- task_group.user_group_id for task_group in matching_task_groups
134
- ]
135
- stm = (
136
- select(LinkUserGroup.group_id)
137
- .where(LinkUserGroup.user_id == user_id)
138
- .where(LinkUserGroup.group_id.in_(user_group_ids))
139
- .order_by(LinkUserGroup.timestamp_created.asc())
140
- )
141
- res = await db.execute(stm)
142
- oldest_user_group_id = res.scalars().first()
143
- logger.info(
144
- "[_disambiguate_task_groups] "
145
- f"Result of sorting: {oldest_user_group_id=}."
146
- )
147
- task_group = next(
148
- iter(
149
- task_group
150
- for task_group in matching_task_groups
151
- if task_group.user_group_id == oldest_user_group_id
152
- ),
153
- None,
154
- )
155
- return task_group
156
-
157
-
158
91
  async def _get_task_by_taskimport(
159
92
  *,
160
93
  task_import: TaskImportV2,
@@ -0,0 +1,2 @@
1
+ class UnreachableBranchError(RuntimeError):
2
+ pass
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fractal-server"
3
- version = "2.14.12"
3
+ version = "2.14.13"
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"]
95
95
 
96
96
  [tool.bumpver]
97
- current_version = "2.14.12"
97
+ current_version = "2.14.13"
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.14.12"