fractal-server 2.14.1__tar.gz → 2.14.3a0__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 (216) hide show
  1. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/PKG-INFO +1 -1
  2. fractal_server-2.14.3a0/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/job.py +1 -1
  4. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/pre_submission_checks.py +8 -0
  5. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/status_legacy.py +2 -2
  6. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/task_collection_custom.py +22 -10
  7. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/compress_folder.py +17 -45
  8. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/remote.py +2 -16
  9. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/runner.py +136 -113
  10. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/local/collect.py +1 -1
  11. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/local/deactivate.py +1 -1
  12. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/local/reactivate.py +1 -1
  13. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/ssh/collect.py +1 -1
  14. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/ssh/deactivate.py +1 -1
  15. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/ssh/reactivate.py +1 -1
  16. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/pyproject.toml +2 -2
  17. fractal_server-2.14.1/fractal_server/__init__.py +0 -1
  18. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/LICENSE +0 -0
  19. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/README.md +0 -0
  20. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/__main__.py +0 -0
  21. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/alembic.ini +0 -0
  22. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/__init__.py +0 -0
  23. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/db/__init__.py +0 -0
  24. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/history/__init__.py +0 -0
  25. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/__init__.py +0 -0
  26. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/linkusergroup.py +0 -0
  27. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/linkuserproject.py +0 -0
  28. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/security.py +0 -0
  29. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/user_settings.py +0 -0
  30. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/__init__.py +0 -0
  31. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/accounting.py +0 -0
  32. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/dataset.py +0 -0
  33. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/history.py +0 -0
  34. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/job.py +0 -0
  35. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/project.py +0 -0
  36. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/task.py +0 -0
  37. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/task_group.py +0 -0
  38. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/workflow.py +0 -0
  39. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/models/v2/workflowtask.py +0 -0
  40. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/__init__.py +0 -0
  41. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/__init__.py +0 -0
  42. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  43. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  44. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  45. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/project.py +0 -0
  46. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/task.py +0 -0
  47. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  48. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  49. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/__init__.py +0 -0
  50. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  51. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  52. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  53. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  54. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  55. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  56. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/history.py +0 -0
  57. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/images.py +0 -0
  58. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/job.py +0 -0
  59. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/project.py +0 -0
  60. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/submit.py +0 -0
  61. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/task.py +0 -0
  62. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  63. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  64. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  65. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  66. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  67. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  68. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/__init__.py +0 -0
  69. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  70. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/current_user.py +0 -0
  71. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/group.py +0 -0
  72. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/login.py +0 -0
  73. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/oauth.py +0 -0
  74. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/register.py +0 -0
  75. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/router.py +0 -0
  76. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/auth/users.py +0 -0
  77. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/aux/__init__.py +0 -0
  78. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/aux/_job.py +0 -0
  79. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/aux/_runner.py +0 -0
  80. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  81. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/routes/pagination.py +0 -0
  82. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/__init__.py +0 -0
  83. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/components.py +0 -0
  84. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/exceptions.py +0 -0
  85. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/__init__.py +0 -0
  86. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/base_runner.py +0 -0
  87. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/local/__init__.py +0 -0
  88. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/local/get_local_config.py +0 -0
  89. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/local/runner.py +0 -0
  90. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/__init__.py +0 -0
  91. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/_batching.py +0 -0
  92. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/_job_states.py +0 -0
  93. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/_slurm_config.py +0 -0
  94. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  95. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +0 -0
  96. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  97. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_common/utils_executors.py +0 -0
  98. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_ssh/__init__.py +0 -0
  99. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_ssh/runner.py +0 -0
  100. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_sudo/__init__.py +0 -0
  101. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  102. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/executors/slurm_sudo/runner.py +0 -0
  103. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/extract_archive.py +0 -0
  104. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/filenames.py +0 -0
  105. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/run_subprocess.py +0 -0
  106. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  107. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/shutdown.py +0 -0
  108. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/task_files.py +0 -0
  109. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/__init__.py +0 -0
  110. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/_local.py +0 -0
  111. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/_slurm_ssh.py +0 -0
  112. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/_slurm_sudo.py +0 -0
  113. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/db_tools.py +0 -0
  114. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  115. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  116. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  117. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  118. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/submit_workflow.py +0 -0
  119. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/v2/task_interface.py +0 -0
  120. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/runner/versions.py +0 -0
  121. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/__init__.py +0 -0
  122. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/_filter_validators.py +0 -0
  123. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/_validators.py +0 -0
  124. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/user.py +0 -0
  125. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/user_group.py +0 -0
  126. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/user_settings.py +0 -0
  127. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/__init__.py +0 -0
  128. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/accounting.py +0 -0
  129. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/dataset.py +0 -0
  130. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/dumps.py +0 -0
  131. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/history.py +0 -0
  132. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/job.py +0 -0
  133. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/manifest.py +0 -0
  134. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/project.py +0 -0
  135. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  136. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/task.py +0 -0
  137. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  138. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/task_group.py +0 -0
  139. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/workflow.py +0 -0
  140. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  141. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/security/__init__.py +0 -0
  142. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/security/signup_email.py +0 -0
  143. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/app/user_settings.py +0 -0
  144. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/config.py +0 -0
  145. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/data_migrations/README.md +0 -0
  146. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/data_migrations/tools.py +0 -0
  147. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/gunicorn_fractal.py +0 -0
  148. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/images/__init__.py +0 -0
  149. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/images/models.py +0 -0
  150. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/images/tools.py +0 -0
  151. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/logger.py +0 -0
  152. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/main.py +0 -0
  153. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/env.py +0 -0
  154. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/naming_convention.py +0 -0
  155. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  156. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  157. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  158. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  159. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  160. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  161. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  162. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  163. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  164. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  165. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  166. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  167. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  168. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  169. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  170. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  171. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  172. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  173. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  174. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  175. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  176. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  177. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  178. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  179. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  180. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  181. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  182. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  183. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  184. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  185. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  186. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  187. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  188. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  189. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  190. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  191. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/py.typed +0 -0
  192. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/ssh/__init__.py +0 -0
  193. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/ssh/_fabric.py +0 -0
  194. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/string_tools.py +0 -0
  195. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/syringe.py +0 -0
  196. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/__init__.py +0 -0
  197. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/utils.py +0 -0
  198. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/__init__.py +0 -0
  199. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/local/__init__.py +0 -0
  200. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/local/_utils.py +0 -0
  201. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  202. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  203. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  204. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  205. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  206. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  207. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  208. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  209. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/utils_background.py +0 -0
  210. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/utils_database.py +0 -0
  211. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  212. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  213. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/tasks/v2/utils_templates.py +0 -0
  214. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/urls.py +0 -0
  215. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/fractal_server/utils.py +0 -0
  216. {fractal_server-2.14.1 → fractal_server-2.14.3a0}/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.1
3
+ Version: 2.14.3a0
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.3a0"
@@ -154,7 +154,7 @@ async def update_job(
154
154
  if job_update.status != JobStatusTypeV2.FAILED:
155
155
  raise HTTPException(
156
156
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
157
- detail=f"Cannot set job status to {job_update.status}",
157
+ detail=f"Cannot set job status to {job_update.status.value}",
158
158
  )
159
159
 
160
160
  setattr(job, "status", job_update.status)
@@ -98,11 +98,19 @@ async def check_workflowtask(
98
98
  )
99
99
 
100
100
  if db_workflow_task.order == 0:
101
+ # Skip check for first task in the workflow
101
102
  return JSONResponse(status_code=200, content=[])
102
103
 
103
104
  previous_wft = db_workflow.task_list[db_workflow_task.order - 1]
104
105
 
105
106
  if previous_wft.task.output_types != {}:
107
+ # Skip check if previous task has non-trivial `output_types`
108
+ return JSONResponse(status_code=200, content=[])
109
+ elif previous_wft.task.type in [
110
+ "converter_compound",
111
+ "converter_non_parallel",
112
+ ]:
113
+ # Skip check if previous task is converter
106
114
  return JSONResponse(status_code=200, content=[])
107
115
 
108
116
  res = await _get_dataset_check_owner(
@@ -118,8 +118,8 @@ async def get_workflowtask_status(
118
118
  )
119
119
  except ValueError:
120
120
  logger.warning(
121
- f"Job {running_job.id} is submitted but its task list does "
122
- f"not contain a {WorkflowTaskStatusTypeV2.SUBMITTED} task."
121
+ f"Job {running_job.id} is submitted but its task list does not"
122
+ f" contain a {WorkflowTaskStatusTypeV2.SUBMITTED.value} task."
123
123
  )
124
124
  first_submitted_index = 0
125
125
 
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import shlex
2
3
  import subprocess # nosec
3
4
  from pathlib import Path
@@ -65,25 +66,36 @@ async def collect_task_custom(
65
66
  detail="Cannot infer 'package_root' with 'slurm_ssh' backend.",
66
67
  )
67
68
  else:
68
- if not Path(task_collect.python_interpreter).is_file():
69
+ if not os.access(
70
+ task_collect.python_interpreter, os.X_OK
71
+ ) or not os.access(task_collect.python_interpreter, os.R_OK):
69
72
  raise HTTPException(
70
73
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
71
74
  detail=(
72
75
  f"{task_collect.python_interpreter=} "
73
- "doesn't exist or is not a file."
76
+ "is not accessible to the Fractal user "
77
+ "or it is not executable."
74
78
  ),
75
79
  )
76
- if (
77
- task_collect.package_root is not None
78
- and not Path(task_collect.package_root).is_dir()
79
- ):
80
+ if not Path(task_collect.python_interpreter).is_file():
80
81
  raise HTTPException(
81
82
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
82
- detail=(
83
- f"{task_collect.package_root=} "
84
- "doesn't exist or is not a directory."
85
- ),
83
+ detail=f"{task_collect.python_interpreter=} is not a file.",
86
84
  )
85
+ if task_collect.package_root is not None:
86
+ if not os.access(task_collect.package_root, os.R_OK):
87
+ raise HTTPException(
88
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
89
+ detail=(
90
+ f"{task_collect.package_root=} "
91
+ "is not accessible to the Fractal user."
92
+ ),
93
+ )
94
+ if not Path(task_collect.package_root).is_dir():
95
+ raise HTTPException(
96
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
97
+ detail=f"{task_collect.package_root=} is not a directory.",
98
+ )
87
99
 
88
100
  if task_collect.package_root is None:
89
101
 
@@ -20,20 +20,9 @@ from fractal_server.logger import get_logger
20
20
  from fractal_server.logger import set_logger
21
21
 
22
22
 
23
- def _copy_subfolder(src: Path, dest: Path, logger_name: str):
24
- t_start = time.perf_counter()
25
- cmd_cp = f"cp -r {src.as_posix()} {dest.as_posix()}"
26
- logger = get_logger(logger_name=logger_name)
27
- logger.debug(f"{cmd_cp=}")
28
- res = run_subprocess(cmd=cmd_cp, logger_name=logger_name)
29
- elapsed = time.perf_counter() - t_start
30
- logger.debug(f"[_copy_subfolder] END {elapsed=} s ({dest.as_posix()})")
31
- return res
32
-
33
-
34
23
  def _create_tar_archive(
35
24
  tarfile_path: str,
36
- subfolder_path_tmp_copy: Path,
25
+ subfolder_path: Path,
37
26
  logger_name: str,
38
27
  filelist_path: str | None,
39
28
  ):
@@ -44,39 +33,26 @@ def _create_tar_archive(
44
33
  if filelist_path is None:
45
34
  cmd_tar = (
46
35
  f"tar -c -z -f {tarfile_path} "
47
- f"--directory={subfolder_path_tmp_copy.as_posix()} "
36
+ f"--directory={subfolder_path.as_posix()} "
48
37
  "."
49
38
  )
50
39
  else:
51
40
  cmd_tar = (
52
41
  f"tar -c -z -f {tarfile_path} "
53
- f"--directory={subfolder_path_tmp_copy.as_posix()} "
42
+ f"--directory={subfolder_path.as_posix()} "
54
43
  f"--files-from={filelist_path} --ignore-failed-read"
55
44
  )
56
45
 
57
46
  logger.debug(f"cmd tar:\n{cmd_tar}")
58
47
 
59
- run_subprocess(cmd=cmd_tar, logger_name=logger_name, allow_char="*")
48
+ run_subprocess(
49
+ cmd=cmd_tar,
50
+ logger_name=logger_name,
51
+ )
60
52
  elapsed = time.perf_counter() - t_start
61
53
  logger.debug(f"[_create_tar_archive] END {elapsed=} s ({tarfile_path})")
62
54
 
63
55
 
64
- def _remove_temp_subfolder(subfolder_path_tmp_copy: Path, logger_name: str):
65
- logger = get_logger(logger_name)
66
- t_start = time.perf_counter()
67
- try:
68
- cmd_rm = f"rm -rf {subfolder_path_tmp_copy}"
69
- logger.debug(f"cmd rm:\n{cmd_rm}")
70
- run_subprocess(cmd=cmd_rm, logger_name=logger_name, allow_char="*")
71
- except Exception as e:
72
- logger.debug(f"ERROR during {cmd_rm}: {e}")
73
- elapsed = time.perf_counter() - t_start
74
- logger.debug(
75
- f"[_remove_temp_subfolder] END {elapsed=} s "
76
- f"({subfolder_path_tmp_copy=})"
77
- )
78
-
79
-
80
56
  def compress_folder(
81
57
  subfolder_path: Path,
82
58
  filelist_path: str | None,
@@ -110,18 +86,11 @@ def compress_folder(
110
86
  tarfile_path = (parent_dir / f"{subfolder_name}.tar.gz").as_posix()
111
87
  logger.debug(f"{tarfile_path=}")
112
88
 
113
- subfolder_path_tmp_copy = (
114
- subfolder_path.parent / f"{subfolder_path.name}_copy"
115
- )
116
89
  try:
117
- _copy_subfolder(
118
- subfolder_path,
119
- subfolder_path_tmp_copy,
120
- logger_name=logger_name,
121
- )
90
+
122
91
  _create_tar_archive(
123
92
  tarfile_path,
124
- subfolder_path_tmp_copy,
93
+ subfolder_path,
125
94
  logger_name=logger_name,
126
95
  filelist_path=filelist_path,
127
96
  )
@@ -129,12 +98,15 @@ def compress_folder(
129
98
 
130
99
  except Exception as e:
131
100
  logger.debug(f"ERROR: {e}")
132
- sys.exit(1)
101
+ cmd_rm = f"rm {tarfile_path}"
102
+ try:
103
+ run_subprocess(cmd=cmd_rm, logger_name=logger_name)
104
+ except Exception as e_rm:
105
+ logger.error(
106
+ f"Running {cmd_rm=} failed, original error: {str(e_rm)}."
107
+ )
133
108
 
134
- finally:
135
- _remove_temp_subfolder(
136
- subfolder_path_tmp_copy, logger_name=logger_name
137
- )
109
+ sys.exit(1)
138
110
 
139
111
 
140
112
  def main(
@@ -18,7 +18,6 @@ import logging
18
18
  import os
19
19
  import sys
20
20
  from typing import Literal
21
- from typing import Optional
22
21
  from typing import Union
23
22
 
24
23
  import cloudpickle
@@ -91,7 +90,6 @@ def worker(
91
90
  *,
92
91
  in_fname: str,
93
92
  out_fname: str,
94
- extra_import_paths: Optional[str] = None,
95
93
  ) -> None:
96
94
  """
97
95
  Execute a job, possibly on a remote node.
@@ -99,7 +97,6 @@ def worker(
99
97
  Arguments:
100
98
  in_fname: Absolute path to the input pickle file (must be readable).
101
99
  out_fname: Absolute path of the output pickle file (must be writeable).
102
- extra_import_paths: Additional import paths
103
100
  """
104
101
 
105
102
  # Create output folder, if missing
@@ -108,10 +105,6 @@ def worker(
108
105
  logging.debug(f"_slurm.remote.worker: create {out_dir=}")
109
106
  os.mkdir(out_dir)
110
107
 
111
- if extra_import_paths:
112
- _extra_import_paths = extra_import_paths.split(":")
113
- sys.path[:0] = _extra_import_paths
114
-
115
108
  # Execute the job and capture exceptions
116
109
  try:
117
110
  with open(in_fname, "rb") as f:
@@ -167,18 +160,11 @@ if __name__ == "__main__":
167
160
  help="Path of output pickle file",
168
161
  required=True,
169
162
  )
170
- parser.add_argument(
171
- "--extra-import-paths",
172
- type=str,
173
- help="Extra import paths",
174
- required=False,
175
- )
176
163
  parsed_args = parser.parse_args()
177
164
  logging.debug(f"{parsed_args=}")
178
165
 
179
166
  kwargs = dict(
180
- in_fname=parsed_args.input_file, out_fname=parsed_args.output_file
167
+ in_fname=parsed_args.input_file,
168
+ out_fname=parsed_args.output_file,
181
169
  )
182
- if parsed_args.extra_import_paths:
183
- kwargs["extra_import_paths"] = parsed_args.extra_import_paths
184
170
  worker(**kwargs)
@@ -9,6 +9,7 @@ from typing import Optional
9
9
 
10
10
  from sqlalchemy.orm.attributes import flag_modified
11
11
  from sqlmodel import delete
12
+ from sqlmodel import update
12
13
 
13
14
  from ....images import SingleImage
14
15
  from ....images.tools import filter_image_list
@@ -25,6 +26,7 @@ from fractal_server.app.models.v2 import AccountingRecord
25
26
  from fractal_server.app.models.v2 import DatasetV2
26
27
  from fractal_server.app.models.v2 import HistoryImageCache
27
28
  from fractal_server.app.models.v2 import HistoryRun
29
+ from fractal_server.app.models.v2 import HistoryUnit
28
30
  from fractal_server.app.models.v2 import TaskGroupV2
29
31
  from fractal_server.app.models.v2 import WorkflowTaskV2
30
32
  from fractal_server.app.runner.executors.base_runner import BaseRunner
@@ -219,139 +221,160 @@ def execute_tasks_v2(
219
221
  num_tasks = 0
220
222
 
221
223
  # POST TASK EXECUTION
222
-
223
- non_failed_task_outputs = [
224
- value.task_output
225
- for value in outcomes_dict.values()
226
- if value.task_output is not None
227
- ]
228
- if len(non_failed_task_outputs) > 0:
229
- current_task_output = merge_outputs(non_failed_task_outputs)
230
- # If `current_task_output` includes no images (to be created or
231
- # removed), then flag all the input images as modified.
232
- # See fractal-server issues #1374 and #2409.
233
- if (
234
- current_task_output.image_list_updates == []
235
- and current_task_output.image_list_removals == []
236
- ):
237
- current_task_output = TaskOutput(
238
- image_list_updates=[
239
- dict(zarr_url=img["zarr_url"])
240
- for img in filtered_images
241
- ],
242
- )
243
- else:
244
- current_task_output = TaskOutput()
245
-
246
- # Update image list
247
- num_new_images = 0
248
- current_task_output.check_zarr_urls_are_unique()
249
- # NOTE: In principle we could make the task-output processing more
250
- # granular, and also associate output-processing failures to history
251
- # status.
252
- for image_obj in current_task_output.image_list_updates:
253
- image = image_obj.model_dump()
254
- if image["zarr_url"] in [img["zarr_url"] for img in tmp_images]:
255
- img_search = find_image_by_zarr_url(
256
- images=tmp_images,
257
- zarr_url=image["zarr_url"],
258
- )
259
- if img_search is None:
260
- raise ValueError(
261
- "Unexpected error: "
262
- f"Image with zarr_url {image['zarr_url']} not found, "
263
- "while updating image list."
264
- )
265
- existing_image_index = img_search["index"]
266
-
224
+ try:
225
+ non_failed_task_outputs = [
226
+ value.task_output
227
+ for value in outcomes_dict.values()
228
+ if value.task_output is not None
229
+ ]
230
+ if len(non_failed_task_outputs) > 0:
231
+ current_task_output = merge_outputs(non_failed_task_outputs)
232
+ # If `current_task_output` includes no images (to be created or
233
+ # removed), then flag all the input images as modified.
234
+ # See fractal-server issues #1374 and #2409.
267
235
  if (
268
- image["origin"] is None
269
- or image["origin"] == image["zarr_url"]
236
+ current_task_output.image_list_updates == []
237
+ and current_task_output.image_list_removals == []
270
238
  ):
271
- # CASE 1: Edit existing image
272
- existing_image = img_search["image"]
273
- new_attributes = copy(existing_image["attributes"])
274
- new_types = copy(existing_image["types"])
275
- new_image = dict(
239
+ current_task_output = TaskOutput(
240
+ image_list_updates=[
241
+ dict(zarr_url=img["zarr_url"])
242
+ for img in filtered_images
243
+ ],
244
+ )
245
+ else:
246
+ current_task_output = TaskOutput()
247
+
248
+ # Update image list
249
+ num_new_images = 0
250
+ current_task_output.check_zarr_urls_are_unique()
251
+ # NOTE: In principle we could make the task-output processing more
252
+ # granular, and also associate output-processing failures to
253
+ # history status.
254
+ for image_obj in current_task_output.image_list_updates:
255
+ image = image_obj.model_dump()
256
+ if image["zarr_url"] in [
257
+ img["zarr_url"] for img in tmp_images
258
+ ]:
259
+ img_search = find_image_by_zarr_url(
260
+ images=tmp_images,
276
261
  zarr_url=image["zarr_url"],
277
262
  )
278
- if "origin" in existing_image.keys():
279
- new_image["origin"] = existing_image["origin"]
263
+ if img_search is None:
264
+ raise ValueError(
265
+ "Unexpected error: "
266
+ f"Image with zarr_url {image['zarr_url']} not "
267
+ "found, while updating image list."
268
+ )
269
+ existing_image_index = img_search["index"]
270
+
271
+ if (
272
+ image["origin"] is None
273
+ or image["origin"] == image["zarr_url"]
274
+ ):
275
+ # CASE 1: Edit existing image
276
+ existing_image = img_search["image"]
277
+ new_attributes = copy(existing_image["attributes"])
278
+ new_types = copy(existing_image["types"])
279
+ new_image = dict(
280
+ zarr_url=image["zarr_url"],
281
+ )
282
+ if "origin" in existing_image.keys():
283
+ new_image["origin"] = existing_image["origin"]
284
+ else:
285
+ # CASE 2: Re-create existing image based on `origin`
286
+ # Propagate attributes and types from `origin` (if any)
287
+ (
288
+ new_attributes,
289
+ new_types,
290
+ ) = get_origin_attribute_and_types(
291
+ origin_url=image["origin"],
292
+ images=tmp_images,
293
+ )
294
+ new_image = dict(
295
+ zarr_url=image["zarr_url"],
296
+ origin=image["origin"],
297
+ )
298
+ # Update attributes
299
+ new_attributes.update(image["attributes"])
300
+ new_attributes = drop_none_attributes(new_attributes)
301
+ new_image["attributes"] = new_attributes
302
+ # Update types
303
+ new_types.update(image["types"])
304
+ new_types.update(task.output_types)
305
+ new_image["types"] = new_types
306
+ # Validate new image
307
+ SingleImage(**new_image)
308
+ # Update image in the dataset image list
309
+ tmp_images[existing_image_index] = new_image
310
+
280
311
  else:
281
- # CASE 2: Re-create existing image based on `origin`
312
+ # CASE 3: Add new image
313
+ # Check that image['zarr_url'] is a subfolder of zarr_dir
314
+ if (
315
+ not image["zarr_url"].startswith(zarr_dir)
316
+ or image["zarr_url"] == zarr_dir
317
+ ):
318
+ raise JobExecutionError(
319
+ "Cannot create image if zarr_url is not a "
320
+ "subfolder of zarr_dir.\n"
321
+ f"zarr_dir: {zarr_dir}\n"
322
+ f"zarr_url: {image['zarr_url']}"
323
+ )
324
+
282
325
  # Propagate attributes and types from `origin` (if any)
283
326
  new_attributes, new_types = get_origin_attribute_and_types(
284
327
  origin_url=image["origin"],
285
328
  images=tmp_images,
286
329
  )
330
+ # Prepare new image
331
+ new_attributes.update(image["attributes"])
332
+ new_attributes = drop_none_attributes(new_attributes)
333
+ new_types.update(image["types"])
334
+ new_types.update(task.output_types)
287
335
  new_image = dict(
288
336
  zarr_url=image["zarr_url"],
289
337
  origin=image["origin"],
338
+ attributes=new_attributes,
339
+ types=new_types,
290
340
  )
291
- # Update attributes
292
- new_attributes.update(image["attributes"])
293
- new_attributes = drop_none_attributes(new_attributes)
294
- new_image["attributes"] = new_attributes
295
- # Update types
296
- new_types.update(image["types"])
297
- new_types.update(task.output_types)
298
- new_image["types"] = new_types
299
- # Validate new image
300
- SingleImage(**new_image)
301
- # Update image in the dataset image list
302
- tmp_images[existing_image_index] = new_image
341
+ # Validate new image
342
+ SingleImage(**new_image)
343
+ # Add image into the dataset image list
344
+ tmp_images.append(new_image)
345
+ num_new_images += 1
303
346
 
304
- else:
305
- # CASE 3: Add new image
306
- # Check that image['zarr_url'] is a subfolder of zarr_dir
307
- if (
308
- not image["zarr_url"].startswith(zarr_dir)
309
- or image["zarr_url"] == zarr_dir
310
- ):
347
+ # Remove images from tmp_images
348
+ for img_zarr_url in current_task_output.image_list_removals:
349
+ img_search = find_image_by_zarr_url(
350
+ images=tmp_images, zarr_url=img_zarr_url
351
+ )
352
+ if img_search is None:
311
353
  raise JobExecutionError(
312
- "Cannot create image if zarr_url is not a subfolder "
313
- "of zarr_dir.\n"
314
- f"zarr_dir: {zarr_dir}\n"
315
- f"zarr_url: {image['zarr_url']}"
354
+ "Cannot remove missing image "
355
+ f"(zarr_url={img_zarr_url})."
316
356
  )
357
+ else:
358
+ tmp_images.pop(img_search["index"])
317
359
 
318
- # Propagate attributes and types from `origin` (if any)
319
- new_attributes, new_types = get_origin_attribute_and_types(
320
- origin_url=image["origin"],
321
- images=tmp_images,
322
- )
323
- # Prepare new image
324
- new_attributes.update(image["attributes"])
325
- new_attributes = drop_none_attributes(new_attributes)
326
- new_types.update(image["types"])
327
- new_types.update(task.output_types)
328
- new_image = dict(
329
- zarr_url=image["zarr_url"],
330
- origin=image["origin"],
331
- attributes=new_attributes,
332
- types=new_types,
333
- )
334
- # Validate new image
335
- SingleImage(**new_image)
336
- # Add image into the dataset image list
337
- tmp_images.append(new_image)
338
- num_new_images += 1
339
-
340
- # Remove images from tmp_images
341
- for img_zarr_url in current_task_output.image_list_removals:
342
- img_search = find_image_by_zarr_url(
343
- images=tmp_images, zarr_url=img_zarr_url
360
+ # Update type_filters based on task-manifest output_types
361
+ type_filters_from_task_manifest = task.output_types
362
+ current_dataset_type_filters.update(
363
+ type_filters_from_task_manifest
344
364
  )
345
- if img_search is None:
346
- raise JobExecutionError(
347
- f"Cannot remove missing image (zarr_url={img_zarr_url})."
365
+ except Exception as e:
366
+ logger.error(
367
+ "Unexpected error in post-task-execution block. "
368
+ f"Original error: {str(e)}"
369
+ )
370
+ with next(get_sync_db()) as db:
371
+ db.execute(
372
+ update(HistoryUnit)
373
+ .where(HistoryUnit.history_run_id == history_run_id)
374
+ .values(status=HistoryUnitStatus.FAILED)
348
375
  )
349
- else:
350
- tmp_images.pop(img_search["index"])
351
-
352
- # Update type_filters based on task-manifest output_types
353
- type_filters_from_task_manifest = task.output_types
354
- current_dataset_type_filters.update(type_filters_from_task_manifest)
376
+ db.commit()
377
+ raise e
355
378
 
356
379
  with next(get_sync_db()) as db:
357
380
  # Write current dataset images into the database.
@@ -132,7 +132,7 @@ def collect_local(
132
132
  ).as_posix(),
133
133
  prefix=(
134
134
  f"{int(time.time())}_"
135
- f"{TaskGroupActivityActionV2.COLLECT}_"
135
+ f"{TaskGroupActivityActionV2.COLLECT.value}_"
136
136
  ),
137
137
  logger_name=LOGGER_NAME,
138
138
  )
@@ -107,7 +107,7 @@ def deactivate_local(
107
107
  ).as_posix(),
108
108
  prefix=(
109
109
  f"{int(time.time())}_"
110
- f"{TaskGroupActivityActionV2.DEACTIVATE}_"
110
+ f"{TaskGroupActivityActionV2.DEACTIVATE.value}_"
111
111
  ),
112
112
  logger_name=LOGGER_NAME,
113
113
  )
@@ -107,7 +107,7 @@ def reactivate_local(
107
107
  ).as_posix(),
108
108
  prefix=(
109
109
  f"{int(time.time())}_"
110
- f"{TaskGroupActivityActionV2.REACTIVATE}_"
110
+ f"{TaskGroupActivityActionV2.REACTIVATE.value}_"
111
111
  ),
112
112
  logger_name=LOGGER_NAME,
113
113
  )
@@ -166,7 +166,7 @@ def collect_ssh(
166
166
  script_dir_remote=script_dir_remote,
167
167
  prefix=(
168
168
  f"{int(time.time())}_"
169
- f"{TaskGroupActivityActionV2.COLLECT}"
169
+ f"{TaskGroupActivityActionV2.COLLECT.value}"
170
170
  ),
171
171
  fractal_ssh=fractal_ssh,
172
172
  logger_name=LOGGER_NAME,
@@ -136,7 +136,7 @@ def deactivate_ssh(
136
136
  script_dir_remote=script_dir_remote,
137
137
  prefix=(
138
138
  f"{int(time.time())}_"
139
- f"{TaskGroupActivityActionV2.DEACTIVATE}"
139
+ f"{TaskGroupActivityActionV2.DEACTIVATE.value}"
140
140
  ),
141
141
  fractal_ssh=fractal_ssh,
142
142
  logger_name=LOGGER_NAME,
@@ -144,7 +144,7 @@ def reactivate_ssh(
144
144
  script_dir_remote=script_dir_remote,
145
145
  prefix=(
146
146
  f"{int(time.time())}_"
147
- f"{TaskGroupActivityActionV2.REACTIVATE}"
147
+ f"{TaskGroupActivityActionV2.REACTIVATE.value}"
148
148
  ),
149
149
  fractal_ssh=fractal_ssh,
150
150
  logger_name=LOGGER_NAME,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fractal-server"
3
- version = "2.14.1"
3
+ version = "2.14.3a0"
4
4
  description = "Backend component of the Fractal analytics platform"
5
5
  authors = [
6
6
  { name="Tommaso Comparin", email="tommaso.comparin@exact-lab.it" },
@@ -95,7 +95,7 @@ filterwarnings = [
95
95
  markers = ["container", "ssh"]
96
96
 
97
97
  [tool.bumpver]
98
- current_version = "2.14.1"
98
+ current_version = "2.14.3a0"
99
99
  version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
100
100
  commit_message = "bump version {old_version} -> {new_version}"
101
101
  commit = true
@@ -1 +0,0 @@
1
- __VERSION__ = "2.14.1"