fractal-server 2.12.0a1__tar.gz → 2.13.0__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 (211) hide show
  1. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/PKG-INFO +10 -11
  2. fractal_server-2.13.0/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/__main__.py +17 -63
  4. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/security.py +9 -12
  5. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/dataset.py +2 -2
  6. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/job.py +11 -9
  7. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/task.py +2 -3
  8. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/task_group.py +6 -2
  9. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/workflowtask.py +15 -8
  10. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/admin/v2/task.py +1 -1
  11. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/admin/v2/task_group.py +1 -1
  12. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/dataset.py +4 -4
  13. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/images.py +11 -23
  14. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/project.py +2 -2
  15. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/status.py +1 -1
  16. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/submit.py +8 -6
  17. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/task.py +4 -2
  18. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/task_collection.py +3 -2
  19. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/task_group.py +2 -2
  20. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/workflow.py +3 -3
  21. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/workflow_import.py +3 -3
  22. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/workflowtask.py +3 -1
  23. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/_aux_auth.py +4 -1
  24. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/current_user.py +3 -5
  25. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/group.py +1 -1
  26. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/users.py +2 -4
  27. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/aux/_runner.py +1 -1
  28. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/aux/validate_user_settings.py +1 -2
  29. fractal_server-2.13.0/fractal_server/app/runner/executors/_job_states.py +13 -0
  30. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/_slurm_config.py +26 -18
  31. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +31 -22
  32. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +2 -6
  33. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/ssh/executor.py +35 -50
  34. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +1 -2
  35. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +37 -47
  36. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/sudo/executor.py +77 -41
  37. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/__init__.py +0 -9
  38. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_local/_local_config.py +5 -4
  39. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +4 -4
  40. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +2 -2
  41. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/deduplicate_list.py +1 -1
  42. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/runner.py +9 -4
  43. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/task_interface.py +15 -7
  44. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/_filter_validators.py +6 -3
  45. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/_validators.py +7 -5
  46. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/user.py +23 -18
  47. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/user_group.py +25 -11
  48. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/user_settings.py +31 -24
  49. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/dataset.py +48 -35
  50. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/dumps.py +16 -14
  51. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/job.py +49 -29
  52. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/manifest.py +32 -28
  53. fractal_server-2.13.0/fractal_server/app/schemas/v2/project.py +39 -0
  54. fractal_server-2.13.0/fractal_server/app/schemas/v2/task.py +222 -0
  55. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/task_collection.py +41 -30
  56. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/task_group.py +39 -20
  57. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/workflow.py +24 -12
  58. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/workflowtask.py +63 -61
  59. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/security/__init__.py +7 -4
  60. fractal_server-2.13.0/fractal_server/app/security/signup_email.py +48 -0
  61. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/config.py +123 -75
  62. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/images/models.py +18 -12
  63. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/main.py +13 -10
  64. fractal_server-2.13.0/fractal_server/migrations/env.py +49 -0
  65. fractal_server-2.13.0/fractal_server/py.typed +0 -0
  66. fractal_server-2.13.0/fractal_server/tasks/v2/__init__.py +0 -0
  67. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/local/collect.py +9 -8
  68. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/local/deactivate.py +3 -0
  69. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/local/reactivate.py +3 -0
  70. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/ssh/collect.py +8 -8
  71. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/ssh/deactivate.py +3 -0
  72. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/ssh/reactivate.py +9 -6
  73. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/utils_background.py +1 -1
  74. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/utils_database.py +1 -1
  75. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/pyproject.toml +13 -13
  76. fractal_server-2.12.0a1/fractal_server/__init__.py +0 -1
  77. fractal_server-2.12.0a1/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -3
  78. fractal_server-2.12.0a1/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -3
  79. fractal_server-2.12.0a1/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -121
  80. fractal_server-2.12.0a1/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -108
  81. fractal_server-2.12.0a1/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -42
  82. fractal_server-2.12.0a1/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -157
  83. fractal_server-2.12.0a1/fractal_server/app/schemas/v2/project.py +0 -29
  84. fractal_server-2.12.0a1/fractal_server/app/schemas/v2/task.py +0 -211
  85. fractal_server-2.12.0a1/fractal_server/app/security/signup_email.py +0 -39
  86. fractal_server-2.12.0a1/fractal_server/migrations/env.py +0 -96
  87. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/LICENSE +0 -0
  88. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/README.md +0 -0
  89. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/alembic.ini +0 -0
  90. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/__init__.py +0 -0
  91. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/db/__init__.py +0 -0
  92. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/__init__.py +0 -0
  93. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/linkusergroup.py +0 -0
  94. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/linkuserproject.py +0 -0
  95. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/user_settings.py +0 -0
  96. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/__init__.py +0 -0
  97. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/project.py +0 -0
  98. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/models/v2/workflow.py +0 -0
  99. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/__init__.py +0 -0
  100. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/admin/__init__.py +0 -0
  101. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  102. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/admin/v2/job.py +0 -0
  103. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/admin/v2/project.py +0 -0
  104. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  105. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/__init__.py +0 -0
  106. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  107. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  108. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  109. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  110. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/job.py +0 -0
  111. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  112. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  113. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/__init__.py +0 -0
  114. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/login.py +0 -0
  115. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/oauth.py +0 -0
  116. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/register.py +0 -0
  117. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/auth/router.py +0 -0
  118. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/aux/__init__.py +0 -0
  119. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/routes/aux/_job.py +0 -0
  120. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/__init__.py +0 -0
  121. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/components.py +0 -0
  122. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/compress_folder.py +0 -0
  123. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/exceptions.py +0 -0
  124. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/__init__.py +0 -0
  125. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
  126. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
  127. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
  128. {fractal_server-2.12.0a1/fractal_server/app/runner/v2/_slurm_common → fractal_server-2.13.0/fractal_server/app/runner/executors/slurm/ssh}/__init__.py +0 -0
  129. {fractal_server-2.12.0a1/fractal_server/tasks/v2 → fractal_server-2.13.0/fractal_server/app/runner/executors/slurm/sudo}/__init__.py +0 -0
  130. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
  131. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/executors/slurm/utils_executors.py +0 -0
  132. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/extract_archive.py +0 -0
  133. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/filenames.py +0 -0
  134. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/run_subprocess.py +0 -0
  135. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  136. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/shutdown.py +0 -0
  137. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/task_files.py +0 -0
  138. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
  139. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
  140. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_local/executor.py +0 -0
  141. /fractal_server-2.12.0a1/fractal_server/py.typed → /fractal_server-2.13.0/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
  142. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
  143. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
  144. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
  145. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
  146. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  147. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  148. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  149. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/runner/versions.py +0 -0
  150. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/__init__.py +0 -0
  151. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/__init__.py +0 -0
  152. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/schemas/v2/status.py +0 -0
  153. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/app/user_settings.py +0 -0
  154. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/data_migrations/README.md +0 -0
  155. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/data_migrations/tools.py +0 -0
  156. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/gunicorn_fractal.py +0 -0
  157. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/images/__init__.py +0 -0
  158. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/images/tools.py +0 -0
  159. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/logger.py +0 -0
  160. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/naming_convention.py +0 -0
  161. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  162. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  163. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  164. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  165. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  166. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  167. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  168. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  169. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  170. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  171. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  172. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  173. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  174. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  175. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  176. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  177. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  178. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  179. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  180. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  181. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  182. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  183. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  184. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  185. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  186. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  187. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  188. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  189. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  190. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/ssh/__init__.py +0 -0
  191. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/ssh/_fabric.py +0 -0
  192. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/string_tools.py +0 -0
  193. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/syringe.py +0 -0
  194. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/__init__.py +0 -0
  195. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/utils.py +0 -0
  196. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/local/__init__.py +0 -0
  197. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/local/_utils.py +0 -0
  198. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  199. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  200. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  201. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  202. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  203. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  204. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  205. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  206. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  207. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  208. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/tasks/v2/utils_templates.py +0 -0
  209. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/urls.py +0 -0
  210. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/fractal_server/utils.py +0 -0
  211. {fractal_server-2.12.0a1 → fractal_server-2.13.0}/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.12.0a1
3
+ Version: 2.13.0
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  Home-page: https://github.com/fractal-analytics-platform/fractal-server
6
6
  License: BSD-3-Clause
@@ -13,22 +13,21 @@ Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Requires-Dist: alembic (>=1.13.1,<2.0.0)
16
- Requires-Dist: cloudpickle (>=3.0.0,<3.1.0)
17
- Requires-Dist: clusterfutures (==0.5)
18
- Requires-Dist: cryptography (>=44.0.0,<44.1.0)
16
+ Requires-Dist: cloudpickle (>=3.1.0,<3.2.0)
17
+ Requires-Dist: cryptography (>=44.0.1,<44.1.0)
19
18
  Requires-Dist: fabric (>=3.2.2,<3.3.0)
20
19
  Requires-Dist: fastapi (>=0.115.0,<0.116.0)
21
20
  Requires-Dist: fastapi-users[oauth] (>=14,<15)
22
- Requires-Dist: gunicorn (>=21.2,<23.0)
23
- Requires-Dist: packaging (>=23.2.0,<24.0.0)
24
- Requires-Dist: psutil (==5.9.8)
21
+ Requires-Dist: gunicorn (>=23.0,<24.0)
22
+ Requires-Dist: packaging (>=24.0.0,<25.0.0)
25
23
  Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0)
26
- Requires-Dist: pydantic (>=1.10.8,<2)
24
+ Requires-Dist: pydantic (>=2.10.0,<2.11.0)
25
+ Requires-Dist: pydantic-settings (>=2.7.0)
27
26
  Requires-Dist: python-dotenv (>=1.0.0,<1.1.0)
28
27
  Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
29
- Requires-Dist: sqlmodel (==0.0.21)
30
- Requires-Dist: uvicorn (==0.29.0)
31
- Requires-Dist: uvicorn-worker (==0.2.0)
28
+ Requires-Dist: sqlmodel (==0.0.22)
29
+ Requires-Dist: uvicorn (>=0.29.0,<0.35.0)
30
+ Requires-Dist: uvicorn-worker (==0.3.0)
32
31
  Project-URL: Documentation, https://fractal-analytics-platform.github.io/fractal-server
33
32
  Project-URL: Repository, https://github.com/fractal-analytics-platform/fractal-server
34
33
  Project-URL: changelog, https://github.com/fractal-analytics-platform/fractal-server/blob/main/CHANGELOG.md
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.13.0"
@@ -63,45 +63,18 @@ update_db_data_parser = subparsers.add_parser(
63
63
  description="Apply data-migration script to an existing database.",
64
64
  )
65
65
 
66
- # fractalctl email-settings
67
- email_settings_parser = subparsers.add_parser(
68
- "email-settings",
66
+ # fractalctl encrypt-email-password
67
+ encrypt_email_password_parser = subparsers.add_parser(
68
+ "encrypt-email-password",
69
69
  description=(
70
70
  "Generate valid values for environment variables "
71
- "`FRACTAL_EMAIL_SETTINGS` and `FRACTAL_EMAIL_SETTINGS_KEY`."
71
+ "FRACTAL_EMAIL_PASSWORD and FRACTAL_EMAIL_PASSWORD_KEY."
72
72
  ),
73
73
  )
74
- email_settings_parser.add_argument(
75
- "sender",
76
- type=str,
77
- help="Email of the sender",
78
- )
79
- email_settings_parser.add_argument(
80
- "server",
81
- type=str,
82
- help="SMPT server used to send emails",
83
- )
84
- email_settings_parser.add_argument(
85
- "port",
86
- type=int,
87
- help="Port of the SMPT server",
88
- )
89
- email_settings_parser.add_argument(
90
- "instance",
91
- type=str,
92
- help="Name of the Fractal instance sending emails",
93
- )
94
- email_settings_parser.add_argument(
95
- "--skip-starttls",
96
- action="store_true",
97
- default=False,
98
- help="If set, skip the execution of `starttls` when sending emails",
99
- )
100
74
 
101
75
 
102
76
  def save_openapi(dest="openapi.json"):
103
77
  from fractal_server.main import start_application
104
- import json
105
78
 
106
79
  app = start_application()
107
80
  openapi_schema = app.openapi()
@@ -129,6 +102,11 @@ def set_db(skip_init_data: bool = False):
129
102
  from pathlib import Path
130
103
  import fractal_server
131
104
 
105
+ # Check settings
106
+ settings = Inject(get_settings)
107
+ settings.check_db()
108
+
109
+ # Perform migrations
132
110
  alembic_ini = Path(fractal_server.__file__).parent / "alembic.ini"
133
111
  alembic_args = ["-c", alembic_ini.as_posix(), "upgrade", "head"]
134
112
  print(f"START: Run alembic.config, with argv={alembic_args}")
@@ -138,12 +116,10 @@ def set_db(skip_init_data: bool = False):
138
116
  if skip_init_data:
139
117
  return
140
118
 
141
- # Insert default group
119
+ # Create default group and user
142
120
  print()
143
121
  _create_first_group()
144
122
  print()
145
- # NOTE: It will be fixed with #1739
146
- settings = Inject(get_settings)
147
123
  asyncio.run(
148
124
  _create_first_user(
149
125
  email=settings.FRACTAL_DEFAULT_ADMIN_EMAIL,
@@ -224,31 +200,15 @@ def update_db_data():
224
200
  current_update_db_data_module.fix_db()
225
201
 
226
202
 
227
- def print_mail_settings(
228
- sender: str,
229
- server: str,
230
- port: int,
231
- instance: str,
232
- skip_starttls: bool,
233
- ):
203
+ def print_encrypted_password():
234
204
  from cryptography.fernet import Fernet
235
205
 
236
- password = input(f"Insert email password for sender '{sender}': ")
206
+ password = input("Insert email password: ").encode("utf-8")
237
207
  key = Fernet.generate_key().decode("utf-8")
238
- fractal_mail_settings = json.dumps(
239
- dict(
240
- sender=sender,
241
- password=password,
242
- smtp_server=server,
243
- port=port,
244
- instance_name=instance,
245
- use_starttls=(not skip_starttls),
246
- )
247
- ).encode("utf-8")
248
- email_settings = Fernet(key).encrypt(fractal_mail_settings).decode("utf-8")
208
+ encrypted_password = Fernet(key).encrypt(password).decode("utf-8")
249
209
 
250
- print(f"\nFRACTAL_EMAIL_SETTINGS: {email_settings}")
251
- print(f"FRACTAL_EMAIL_SETTINGS_KEY: {key}")
210
+ print(f"\nFRACTAL_EMAIL_PASSWORD={encrypted_password}")
211
+ print(f"FRACTAL_EMAIL_PASSWORD_KEY={key}")
252
212
 
253
213
 
254
214
  def run():
@@ -267,14 +227,8 @@ def run():
267
227
  port=args.port,
268
228
  reload=args.reload,
269
229
  )
270
- elif args.cmd == "email-settings":
271
- print_mail_settings(
272
- sender=args.sender,
273
- server=args.server,
274
- port=args.port,
275
- instance=args.instance,
276
- skip_starttls=args.skip_starttls,
277
- )
230
+ elif args.cmd == "encrypt-email-password":
231
+ print_encrypted_password()
278
232
  else:
279
233
  sys.exit(f"Error: invalid command '{args.cmd}'.")
280
234
 
@@ -12,6 +12,7 @@
12
12
  from datetime import datetime
13
13
  from typing import Optional
14
14
 
15
+ from pydantic import ConfigDict
15
16
  from pydantic import EmailStr
16
17
  from sqlalchemy import Column
17
18
  from sqlalchemy.types import DateTime
@@ -50,13 +51,11 @@ class OAuthAccount(SQLModel, table=True):
50
51
  user: Optional["UserOAuth"] = Relationship(back_populates="oauth_accounts")
51
52
  oauth_name: str = Field(index=True, nullable=False)
52
53
  access_token: str = Field(nullable=False)
53
- expires_at: Optional[int] = Field(nullable=True)
54
- refresh_token: Optional[str] = Field(nullable=True)
54
+ expires_at: Optional[int] = Field(nullable=True, default=None)
55
+ refresh_token: Optional[str] = Field(nullable=True, default=None)
55
56
  account_id: str = Field(index=True, nullable=False)
56
57
  account_email: str = Field(nullable=False)
57
-
58
- class Config:
59
- orm_mode = True
58
+ model_config = ConfigDict(from_attributes=True)
60
59
 
61
60
 
62
61
  class UserOAuth(SQLModel, table=True):
@@ -88,11 +87,11 @@ class UserOAuth(SQLModel, table=True):
88
87
  sa_column_kwargs={"unique": True, "index": True}, nullable=False
89
88
  )
90
89
  hashed_password: str
91
- is_active: bool = Field(True, nullable=False)
92
- is_superuser: bool = Field(False, nullable=False)
93
- is_verified: bool = Field(False, nullable=False)
90
+ is_active: bool = Field(default=True, nullable=False)
91
+ is_superuser: bool = Field(default=False, nullable=False)
92
+ is_verified: bool = Field(default=False, nullable=False)
94
93
 
95
- username: Optional[str]
94
+ username: Optional[str] = None
96
95
 
97
96
  oauth_accounts: list["OAuthAccount"] = Relationship(
98
97
  back_populates="user",
@@ -105,9 +104,7 @@ class UserOAuth(SQLModel, table=True):
105
104
  settings: Optional[UserSettings] = Relationship(
106
105
  sa_relationship_kwargs=dict(lazy="selectin", cascade="all, delete")
107
106
  )
108
-
109
- class Config:
110
- orm_mode = True
107
+ model_config = ConfigDict(from_attributes=True)
111
108
 
112
109
 
113
110
  class UserGroup(SQLModel, table=True):
@@ -2,6 +2,7 @@ from datetime import datetime
2
2
  from typing import Any
3
3
  from typing import Optional
4
4
 
5
+ from pydantic import ConfigDict
5
6
  from sqlalchemy import Column
6
7
  from sqlalchemy.types import DateTime
7
8
  from sqlalchemy.types import JSON
@@ -14,8 +15,7 @@ from fractal_server.images.models import AttributeFiltersType
14
15
 
15
16
 
16
17
  class DatasetV2(SQLModel, table=True):
17
- class Config:
18
- arbitrary_types_allowed = True
18
+ model_config = ConfigDict(arbitrary_types_allowed=True)
19
19
 
20
20
  id: Optional[int] = Field(default=None, primary_key=True)
21
21
  name: str
@@ -2,6 +2,7 @@ from datetime import datetime
2
2
  from typing import Any
3
3
  from typing import Optional
4
4
 
5
+ from pydantic import ConfigDict
5
6
  from sqlalchemy import Column
6
7
  from sqlalchemy.types import DateTime
7
8
  from sqlalchemy.types import JSON
@@ -14,16 +15,17 @@ from fractal_server.images.models import AttributeFiltersType
14
15
 
15
16
 
16
17
  class JobV2(SQLModel, table=True):
17
- class Config:
18
- arbitrary_types_allowed = True
18
+ model_config = ConfigDict(arbitrary_types_allowed=True)
19
19
 
20
20
  id: Optional[int] = Field(default=None, primary_key=True)
21
- project_id: Optional[int] = Field(foreign_key="projectv2.id")
22
- workflow_id: Optional[int] = Field(foreign_key="workflowv2.id")
23
- dataset_id: Optional[int] = Field(foreign_key="datasetv2.id")
21
+ project_id: Optional[int] = Field(foreign_key="projectv2.id", default=None)
22
+ workflow_id: Optional[int] = Field(
23
+ foreign_key="workflowv2.id", default=None
24
+ )
25
+ dataset_id: Optional[int] = Field(foreign_key="datasetv2.id", default=None)
24
26
 
25
27
  user_email: str = Field(nullable=False)
26
- slurm_account: Optional[str]
28
+ slurm_account: Optional[str] = None
27
29
 
28
30
  dataset_dump: dict[str, Any] = Field(
29
31
  sa_column=Column(JSON, nullable=False)
@@ -35,9 +37,9 @@ class JobV2(SQLModel, table=True):
35
37
  sa_column=Column(JSON, nullable=False)
36
38
  )
37
39
 
38
- worker_init: Optional[str]
39
- working_dir: Optional[str]
40
- working_dir_user: Optional[str]
40
+ worker_init: Optional[str] = None
41
+ working_dir: Optional[str] = None
42
+ working_dir_user: Optional[str] = None
41
43
  first_task_index: int
42
44
  last_task_index: int
43
45
 
@@ -1,7 +1,6 @@
1
1
  from typing import Any
2
2
  from typing import Optional
3
3
 
4
- from pydantic import HttpUrl
5
4
  from sqlalchemy import Column
6
5
  from sqlalchemy.types import JSON
7
6
  from sqlmodel import Field
@@ -31,9 +30,9 @@ class TaskV2(SQLModel, table=True):
31
30
  args_schema_parallel: Optional[dict[str, Any]] = Field(
32
31
  sa_column=Column(JSON), default=None
33
32
  )
34
- args_schema_version: Optional[str]
33
+ args_schema_version: Optional[str] = None
35
34
  docs_info: Optional[str] = None
36
- docs_link: Optional[HttpUrl] = None
35
+ docs_link: Optional[str] = None
37
36
 
38
37
  input_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
39
38
  output_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
@@ -22,7 +22,9 @@ class TaskGroupV2(SQLModel, table=True):
22
22
  )
23
23
 
24
24
  user_id: int = Field(foreign_key="user_oauth.id")
25
- user_group_id: Optional[int] = Field(foreign_key="usergroup.id")
25
+ user_group_id: Optional[int] = Field(
26
+ foreign_key="usergroup.id", default=None
27
+ )
26
28
 
27
29
  origin: str
28
30
  pkg_name: str
@@ -97,7 +99,9 @@ class TaskGroupActivityV2(SQLModel, table=True):
97
99
 
98
100
  id: Optional[int] = Field(default=None, primary_key=True)
99
101
  user_id: int = Field(foreign_key="user_oauth.id")
100
- taskgroupv2_id: Optional[int] = Field(foreign_key="taskgroupv2.id")
102
+ taskgroupv2_id: Optional[int] = Field(
103
+ default=None, foreign_key="taskgroupv2.id"
104
+ )
101
105
  timestamp_started: datetime = Field(
102
106
  default_factory=get_timestamp,
103
107
  sa_column=Column(DateTime(timezone=True), nullable=False),
@@ -1,6 +1,7 @@
1
1
  from typing import Any
2
2
  from typing import Optional
3
3
 
4
+ from pydantic import ConfigDict
4
5
  from sqlalchemy import Column
5
6
  from sqlalchemy.types import JSON
6
7
  from sqlmodel import Field
@@ -11,18 +12,24 @@ from .task import TaskV2
11
12
 
12
13
 
13
14
  class WorkflowTaskV2(SQLModel, table=True):
14
- class Config:
15
- arbitrary_types_allowed = True
16
- fields = {"parent": {"exclude": True}}
15
+ model_config = ConfigDict(arbitrary_types_allowed=True)
17
16
 
18
17
  id: Optional[int] = Field(default=None, primary_key=True)
19
18
 
20
19
  workflow_id: int = Field(foreign_key="workflowv2.id")
21
- order: Optional[int]
22
- meta_parallel: Optional[dict[str, Any]] = Field(sa_column=Column(JSON))
23
- meta_non_parallel: Optional[dict[str, Any]] = Field(sa_column=Column(JSON))
24
- args_parallel: Optional[dict[str, Any]] = Field(sa_column=Column(JSON))
25
- args_non_parallel: Optional[dict[str, Any]] = Field(sa_column=Column(JSON))
20
+ order: Optional[int] = None
21
+ meta_parallel: Optional[dict[str, Any]] = Field(
22
+ sa_column=Column(JSON), default=None
23
+ )
24
+ meta_non_parallel: Optional[dict[str, Any]] = Field(
25
+ sa_column=Column(JSON), default=None
26
+ )
27
+ args_parallel: Optional[dict[str, Any]] = Field(
28
+ sa_column=Column(JSON), default=None
29
+ )
30
+ args_non_parallel: Optional[dict[str, Any]] = Field(
31
+ sa_column=Column(JSON), default=None
32
+ )
26
33
 
27
34
  type_filters: dict[str, bool] = Field(
28
35
  sa_column=Column(JSON, nullable=False, server_default="{}")
@@ -28,7 +28,7 @@ class TaskV2Minimal(BaseModel):
28
28
  type: str
29
29
  taskgroupv2_id: int
30
30
  command_non_parallel: Optional[str] = None
31
- command_parallel: Optional[str]
31
+ command_parallel: Optional[str] = None
32
32
  source: Optional[str] = None
33
33
  version: Optional[str] = None
34
34
 
@@ -163,7 +163,7 @@ async def patch_task_group(
163
163
  detail=f"TaskGroupV2 {task_group_id} not found",
164
164
  )
165
165
 
166
- for key, value in task_group_update.dict(exclude_unset=True).items():
166
+ for key, value in task_group_update.model_dump(exclude_unset=True).items():
167
167
  if (key == "user_group_id") and (value is not None):
168
168
  await _verify_user_belongs_to_group(
169
169
  user_id=user.id, user_group_id=value, db=db
@@ -60,7 +60,7 @@ async def create_dataset(
60
60
  db_dataset = DatasetV2(
61
61
  project_id=project_id,
62
62
  zarr_dir="__PLACEHOLDER__",
63
- **dataset.dict(exclude={"zarr_dir"}),
63
+ **dataset.model_dump(exclude={"zarr_dir"}),
64
64
  )
65
65
  db.add(db_dataset)
66
66
  await db.commit()
@@ -77,7 +77,7 @@ async def create_dataset(
77
77
  await db.commit()
78
78
  await db.refresh(db_dataset)
79
79
  else:
80
- db_dataset = DatasetV2(project_id=project_id, **dataset.dict())
80
+ db_dataset = DatasetV2(project_id=project_id, **dataset.model_dump())
81
81
  db.add(db_dataset)
82
82
  await db.commit()
83
83
  await db.refresh(db_dataset)
@@ -172,7 +172,7 @@ async def update_dataset(
172
172
  ),
173
173
  )
174
174
 
175
- for key, value in dataset_update.dict(exclude_unset=True).items():
175
+ for key, value in dataset_update.model_dump(exclude_unset=True).items():
176
176
  setattr(db_dataset, key, value)
177
177
 
178
178
  await db.commit()
@@ -316,7 +316,7 @@ async def import_dataset(
316
316
  # Create new Dataset
317
317
  db_dataset = DatasetV2(
318
318
  project_id=project_id,
319
- **dataset.dict(exclude_none=True),
319
+ **dataset.model_dump(exclude_none=True),
320
320
  )
321
321
  db.add(db_dataset)
322
322
  await db.commit()
@@ -8,8 +8,8 @@ from fastapi import Response
8
8
  from fastapi import status
9
9
  from pydantic import BaseModel
10
10
  from pydantic import Field
11
- from pydantic import root_validator
12
- from pydantic import validator
11
+ from pydantic import field_validator
12
+ from pydantic import model_validator
13
13
  from sqlalchemy.orm.attributes import flag_modified
14
14
 
15
15
  from ._aux_functions import _get_dataset_check_owner
@@ -44,18 +44,18 @@ class ImagePage(BaseModel):
44
44
 
45
45
 
46
46
  class ImageQuery(BaseModel):
47
- zarr_url: Optional[str]
47
+ zarr_url: Optional[str] = None
48
48
  type_filters: dict[str, bool] = Field(default_factory=dict)
49
49
  attribute_filters: AttributeFiltersType = Field(default_factory=dict)
50
50
 
51
- _dict_keys = root_validator(pre=True, allow_reuse=True)(
52
- root_validate_dict_keys
51
+ _dict_keys = model_validator(mode="before")(
52
+ classmethod(root_validate_dict_keys)
53
53
  )
54
- _type_filters = validator("type_filters", allow_reuse=True)(
55
- validate_type_filters
54
+ _type_filters = field_validator("type_filters")(
55
+ classmethod(validate_type_filters)
56
56
  )
57
- _attribute_filters = validator("attribute_filters", allow_reuse=True)(
58
- validate_attribute_filters
57
+ _attribute_filters = field_validator("attribute_filters")(
58
+ classmethod(validate_attribute_filters)
59
59
  )
60
60
 
61
61
 
@@ -102,7 +102,7 @@ async def post_new_image(
102
102
  ),
103
103
  )
104
104
 
105
- dataset.images.append(new_image.dict())
105
+ dataset.images.append(new_image.model_dump())
106
106
  flag_modified(dataset, "images")
107
107
 
108
108
  await db.commit()
@@ -118,7 +118,6 @@ async def post_new_image(
118
118
  async def query_dataset_images(
119
119
  project_id: int,
120
120
  dataset_id: int,
121
- use_dataset_filters: bool = False, # query param
122
121
  page: int = 1, # query param
123
122
  page_size: Optional[int] = None, # query param
124
123
  query: Optional[ImageQuery] = None, # body
@@ -138,17 +137,6 @@ async def query_dataset_images(
138
137
  dataset = output["dataset"]
139
138
  images = dataset.images
140
139
 
141
- if use_dataset_filters is True:
142
- images = [
143
- image
144
- for image in images
145
- if match_filter(
146
- image=image,
147
- type_filters=dataset.type_filters,
148
- attribute_filters=dataset.attribute_filters,
149
- )
150
- ]
151
-
152
140
  attributes = {}
153
141
  for image in images:
154
142
  for k, v in image["attributes"].items():
@@ -290,7 +278,7 @@ async def patch_dataset_image(
290
278
  )
291
279
  index = ret["index"]
292
280
 
293
- for key, value in image_update.dict(
281
+ for key, value in image_update.model_dump(
294
282
  exclude_none=True, exclude={"zarr_url"}
295
283
  ).items():
296
284
  db_dataset.images[index][key] = value
@@ -62,7 +62,7 @@ async def create_project(
62
62
  project_name=project.name, user_id=user.id, db=db
63
63
  )
64
64
 
65
- db_project = ProjectV2(**project.dict())
65
+ db_project = ProjectV2(**project.model_dump())
66
66
  db_project.user_list.append(user)
67
67
 
68
68
  db.add(db_project)
@@ -106,7 +106,7 @@ async def update_project(
106
106
  project_name=project_update.name, user_id=user.id, db=db
107
107
  )
108
108
 
109
- for key, value in project_update.dict(exclude_unset=True).items():
109
+ for key, value in project_update.model_dump(exclude_unset=True).items():
110
110
  setattr(project, key, value)
111
111
 
112
112
  await db.commit()
@@ -154,7 +154,7 @@ async def get_workflowtask_status(
154
154
  if wf_task_status is None:
155
155
  # If a wftask ID was not found, ignore it and continue
156
156
  continue
157
- clean_workflow_tasks_status_dict[wf_task.id] = wf_task_status
157
+ clean_workflow_tasks_status_dict[str(wf_task.id)] = wf_task_status
158
158
  if wf_task_status == WorkflowTaskStatusTypeV2.FAILED:
159
159
  # Starting from the beginning of `workflow.task_list`, stop the
160
160
  # first time that you hit a failed job
@@ -165,11 +165,15 @@ async def apply_workflow(
165
165
  # The 'filters' field is not supported any more but still exists as a
166
166
  # database column, therefore we manually exclude it from dumps.
167
167
  dataset_dump=json.loads(
168
- dataset.json(exclude={"images", "history", "filters"})
168
+ dataset.model_dump_json(exclude={"images", "history", "filters"})
169
169
  ),
170
- workflow_dump=json.loads(workflow.json(exclude={"task_list"})),
171
- project_dump=json.loads(project.json(exclude={"user_list"})),
172
- **job_create.dict(),
170
+ workflow_dump=json.loads(
171
+ workflow.model_dump_json(exclude={"task_list"})
172
+ ),
173
+ project_dump=json.loads(
174
+ project.model_dump_json(exclude={"user_list"})
175
+ ),
176
+ **job_create.model_dump(),
173
177
  )
174
178
 
175
179
  db.add(job)
@@ -202,8 +206,6 @@ async def apply_workflow(
202
206
  # Define user-side job directory
203
207
  if FRACTAL_RUNNER_BACKEND == "local":
204
208
  WORKFLOW_DIR_REMOTE = WORKFLOW_DIR_LOCAL
205
- elif FRACTAL_RUNNER_BACKEND == "local_experimental":
206
- WORKFLOW_DIR_REMOTE = WORKFLOW_DIR_LOCAL
207
209
  elif FRACTAL_RUNNER_BACKEND == "slurm":
208
210
  WORKFLOW_DIR_REMOTE = cache_dir / WORKFLOW_DIR_LOCAL.name
209
211
  elif FRACTAL_RUNNER_BACKEND == "slurm_ssh":
@@ -107,7 +107,7 @@ async def patch_task(
107
107
  db_task = await _get_task_full_access(
108
108
  task_id=task_id, user_id=user.id, db=db
109
109
  )
110
- update = task_update.dict(exclude_unset=True)
110
+ update = task_update.model_dump(exclude_unset=True)
111
111
 
112
112
  # Forbid changes that set a previously unset command
113
113
  if db_task.type == "non_parallel" and "command_parallel" in update:
@@ -182,7 +182,8 @@ async def create_task(
182
182
  )
183
183
 
184
184
  # Add task
185
- db_task = TaskV2(**task.dict(), type=task_type)
185
+
186
+ db_task = TaskV2(**task.model_dump(exclude_unset=True), type=task_type)
186
187
  pkg_name = db_task.name
187
188
  await _verify_non_duplication_user_constraint(
188
189
  db=db, pkg_name=pkg_name, user_id=user.id, version=db_task.version
@@ -206,6 +207,7 @@ async def create_task(
206
207
  await db.commit()
207
208
  await db.refresh(db_task)
208
209
  await db.close()
210
+
209
211
  return db_task
210
212
 
211
213
 
@@ -13,7 +13,7 @@ from fastapi import Response
13
13
  from fastapi import status
14
14
  from fastapi import UploadFile
15
15
  from pydantic import BaseModel
16
- from pydantic import root_validator
16
+ from pydantic import model_validator
17
17
  from pydantic import ValidationError
18
18
  from sqlmodel import select
19
19
 
@@ -68,7 +68,8 @@ class CollectionRequestData(BaseModel):
68
68
  file: Optional[UploadFile] = None
69
69
  origin: TaskGroupV2OriginEnum
70
70
 
71
- @root_validator(pre=True)
71
+ @model_validator(mode="before")
72
+ @classmethod
72
73
  def validate_data(cls, values):
73
74
  file = values.get("file")
74
75
  package = values.get("task_collect").package
@@ -223,7 +223,7 @@ async def patch_task_group(
223
223
  db=db,
224
224
  )
225
225
  if (
226
- "user_group_id" in task_group_update.dict(exclude_unset=True)
226
+ "user_group_id" in task_group_update.model_dump(exclude_unset=True)
227
227
  and task_group_update.user_group_id != task_group.user_group_id
228
228
  ):
229
229
  await _verify_non_duplication_group_constraint(
@@ -232,7 +232,7 @@ async def patch_task_group(
232
232
  version=task_group.version,
233
233
  user_group_id=task_group_update.user_group_id,
234
234
  )
235
- for key, value in task_group_update.dict(exclude_unset=True).items():
235
+ for key, value in task_group_update.model_dump(exclude_unset=True).items():
236
236
  if (key == "user_group_id") and (value is not None):
237
237
  await _verify_user_belongs_to_group(
238
238
  user_id=user.id, user_group_id=value, db=db
@@ -82,7 +82,7 @@ async def create_workflow(
82
82
  name=workflow.name, project_id=project_id, db=db
83
83
  )
84
84
 
85
- db_workflow = WorkflowV2(project_id=project_id, **workflow.dict())
85
+ db_workflow = WorkflowV2(project_id=project_id, **workflow.model_dump())
86
86
  db.add(db_workflow)
87
87
  await db.commit()
88
88
  await db.refresh(db_workflow)
@@ -149,7 +149,7 @@ async def update_workflow(
149
149
  name=patch.name, project_id=project_id, db=db
150
150
  )
151
151
 
152
- for key, value in patch.dict(exclude_unset=True).items():
152
+ for key, value in patch.model_dump(exclude_unset=True).items():
153
153
  if key == "reordered_workflowtask_ids":
154
154
  current_workflowtask_ids = [
155
155
  wftask.id for wftask in workflow.task_list
@@ -262,7 +262,7 @@ async def export_worfklow(
262
262
  wf_task_list = []
263
263
  for wftask in workflow.task_list:
264
264
  task_group = await db.get(TaskGroupV2, wftask.task.taskgroupv2_id)
265
- wf_task_list.append(wftask.dict())
265
+ wf_task_list.append(wftask.model_dump())
266
266
  wf_task_list[-1]["task"] = dict(
267
267
  pkg_name=task_group.pkg_name,
268
268
  version=task_group.version,