fractal-server 2.14.3a0__tar.gz → 2.14.4a0__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 (227) hide show
  1. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/PKG-INFO +1 -1
  2. fractal_server-2.14.4a0/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/job.py +2 -2
  4. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/images.py +4 -20
  5. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/pre_submission_checks.py +2 -2
  6. {fractal_server-2.14.3a0/fractal_server/app/runner → fractal_server-2.14.4a0/fractal_server/app/runner/executors/slurm_ssh}/run_subprocess.py +11 -6
  7. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_ssh/runner.py +11 -56
  8. fractal_server-2.14.4a0/fractal_server/app/runner/executors/slurm_ssh/tar_commands.py +65 -0
  9. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/_local.py +2 -2
  10. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/_slurm_ssh.py +2 -2
  11. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/_slurm_sudo.py +2 -2
  12. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/runner.py +2 -2
  13. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/task_interface.py +3 -14
  14. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/user.py +11 -35
  15. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/user_group.py +3 -23
  16. fractal_server-2.14.4a0/fractal_server/app/schemas/user_settings.py +69 -0
  17. fractal_server-2.14.4a0/fractal_server/app/schemas/v2/dataset.py +81 -0
  18. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/job.py +19 -60
  19. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/manifest.py +10 -25
  20. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/project.py +3 -11
  21. fractal_server-2.14.4a0/fractal_server/app/schemas/v2/task.py +147 -0
  22. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/task_collection.py +31 -81
  23. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/task_group.py +14 -34
  24. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/workflow.py +13 -28
  25. fractal_server-2.14.4a0/fractal_server/app/schemas/v2/workflowtask.py +117 -0
  26. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/config.py +20 -73
  27. fractal_server-2.14.4a0/fractal_server/images/models.py +51 -0
  28. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/images/tools.py +3 -3
  29. fractal_server-2.14.4a0/fractal_server/types/__init__.py +87 -0
  30. fractal_server-2.14.4a0/fractal_server/types/validators/__init__.py +6 -0
  31. fractal_server-2.14.4a0/fractal_server/types/validators/_common_validators.py +42 -0
  32. fractal_server-2.14.4a0/fractal_server/types/validators/_filter_validators.py +24 -0
  33. fractal_server-2.14.4a0/fractal_server/types/validators/_workflow_task_arguments_validators.py +10 -0
  34. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/pyproject.toml +2 -2
  35. fractal_server-2.14.3a0/fractal_server/__init__.py +0 -1
  36. fractal_server-2.14.3a0/fractal_server/app/runner/compress_folder.py +0 -144
  37. fractal_server-2.14.3a0/fractal_server/app/runner/extract_archive.py +0 -99
  38. fractal_server-2.14.3a0/fractal_server/app/schemas/_filter_validators.py +0 -46
  39. fractal_server-2.14.3a0/fractal_server/app/schemas/_validators.py +0 -86
  40. fractal_server-2.14.3a0/fractal_server/app/schemas/user_settings.py +0 -95
  41. fractal_server-2.14.3a0/fractal_server/app/schemas/v2/dataset.py +0 -121
  42. fractal_server-2.14.3a0/fractal_server/app/schemas/v2/task.py +0 -217
  43. fractal_server-2.14.3a0/fractal_server/app/schemas/v2/workflowtask.py +0 -225
  44. fractal_server-2.14.3a0/fractal_server/images/models.py +0 -117
  45. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/LICENSE +0 -0
  46. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/README.md +0 -0
  47. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/__main__.py +0 -0
  48. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/alembic.ini +0 -0
  49. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/__init__.py +0 -0
  50. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/db/__init__.py +0 -0
  51. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/history/__init__.py +0 -0
  52. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/__init__.py +0 -0
  53. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/linkusergroup.py +0 -0
  54. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/linkuserproject.py +0 -0
  55. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/security.py +0 -0
  56. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/user_settings.py +0 -0
  57. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/__init__.py +0 -0
  58. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/accounting.py +0 -0
  59. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/dataset.py +0 -0
  60. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/history.py +0 -0
  61. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/project.py +0 -0
  62. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/task.py +0 -0
  63. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/task_group.py +0 -0
  64. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/workflow.py +0 -0
  65. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/models/v2/workflowtask.py +0 -0
  66. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/__init__.py +0 -0
  67. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/__init__.py +0 -0
  68. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  69. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  70. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  71. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/job.py +0 -0
  72. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/project.py +0 -0
  73. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/task.py +0 -0
  74. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  75. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  76. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/__init__.py +0 -0
  77. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  78. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  79. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  80. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  81. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  82. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  83. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/history.py +0 -0
  84. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/job.py +0 -0
  85. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/project.py +0 -0
  86. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  87. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/submit.py +0 -0
  88. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/task.py +0 -0
  89. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  90. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  91. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  92. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  93. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  94. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  95. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  96. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/__init__.py +0 -0
  97. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  98. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/current_user.py +0 -0
  99. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/group.py +0 -0
  100. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/login.py +0 -0
  101. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/oauth.py +0 -0
  102. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/register.py +0 -0
  103. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/router.py +0 -0
  104. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/auth/users.py +0 -0
  105. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/aux/__init__.py +0 -0
  106. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/aux/_job.py +0 -0
  107. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/aux/_runner.py +0 -0
  108. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  109. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/routes/pagination.py +0 -0
  110. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/__init__.py +0 -0
  111. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/components.py +0 -0
  112. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/exceptions.py +0 -0
  113. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/__init__.py +0 -0
  114. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/base_runner.py +0 -0
  115. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/local/__init__.py +0 -0
  116. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/local/get_local_config.py +0 -0
  117. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/local/runner.py +0 -0
  118. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/__init__.py +0 -0
  119. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/_batching.py +0 -0
  120. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/_job_states.py +0 -0
  121. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/_slurm_config.py +0 -0
  122. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  123. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +0 -0
  124. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/remote.py +0 -0
  125. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  126. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_common/utils_executors.py +0 -0
  127. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_ssh/__init__.py +0 -0
  128. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_sudo/__init__.py +0 -0
  129. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  130. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/executors/slurm_sudo/runner.py +0 -0
  131. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/filenames.py +0 -0
  132. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  133. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/shutdown.py +0 -0
  134. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/task_files.py +0 -0
  135. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/__init__.py +0 -0
  136. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/db_tools.py +0 -0
  137. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  138. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  139. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  140. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  141. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/v2/submit_workflow.py +0 -0
  142. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/runner/versions.py +0 -0
  143. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/__init__.py +0 -0
  144. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/__init__.py +0 -0
  145. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/accounting.py +0 -0
  146. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/dumps.py +0 -0
  147. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/history.py +0 -0
  148. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  149. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/security/__init__.py +0 -0
  150. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/security/signup_email.py +0 -0
  151. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/app/user_settings.py +0 -0
  152. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/data_migrations/README.md +0 -0
  153. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/data_migrations/tools.py +0 -0
  154. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/gunicorn_fractal.py +0 -0
  155. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/images/__init__.py +0 -0
  156. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/logger.py +0 -0
  157. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/main.py +0 -0
  158. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/env.py +0 -0
  159. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/naming_convention.py +0 -0
  160. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  161. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  162. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  163. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  164. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  165. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  166. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  167. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  168. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  169. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  170. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  171. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  172. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  173. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  174. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  175. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  176. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  177. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  178. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  179. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  180. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  181. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  182. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  183. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  184. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  185. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  186. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  187. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  188. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  189. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  190. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  191. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  192. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  193. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  194. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  195. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  196. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/py.typed +0 -0
  197. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/ssh/__init__.py +0 -0
  198. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/ssh/_fabric.py +0 -0
  199. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/string_tools.py +0 -0
  200. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/syringe.py +0 -0
  201. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/__init__.py +0 -0
  202. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/utils.py +0 -0
  203. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/__init__.py +0 -0
  204. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/local/__init__.py +0 -0
  205. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/local/_utils.py +0 -0
  206. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/local/collect.py +0 -0
  207. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  208. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  209. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  210. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  211. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/ssh/collect.py +0 -0
  212. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  213. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  214. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  215. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  216. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  217. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  218. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  219. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  220. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/utils_background.py +0 -0
  221. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/utils_database.py +0 -0
  222. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  223. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  224. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/tasks/v2/utils_templates.py +0 -0
  225. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/urls.py +0 -0
  226. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/fractal_server/utils.py +0 -0
  227. {fractal_server-2.14.3a0 → fractal_server-2.14.4a0}/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.3a0
3
+ Version: 2.14.4a0
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.4a0"
@@ -11,7 +11,7 @@ from sqlmodel import SQLModel
11
11
 
12
12
  from ....utils import get_timestamp
13
13
  from ...schemas.v2 import JobStatusTypeV2
14
- from fractal_server.images.models import AttributeFiltersType
14
+ from fractal_server.types import AttributeFilters
15
15
 
16
16
 
17
17
  class JobV2(SQLModel, table=True):
@@ -57,7 +57,7 @@ class JobV2(SQLModel, table=True):
57
57
  status: str = JobStatusTypeV2.SUBMITTED
58
58
  log: Optional[str] = None
59
59
 
60
- attribute_filters: AttributeFiltersType = Field(
60
+ attribute_filters: AttributeFilters = Field(
61
61
  sa_column=Column(JSON, nullable=False, server_default="{}")
62
62
  )
63
63
  type_filters: dict[str, bool] = Field(
@@ -8,8 +8,6 @@ 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 field_validator
12
- from pydantic import model_validator
13
11
  from sqlalchemy.orm.attributes import flag_modified
14
12
  from sqlmodel import delete
15
13
 
@@ -22,18 +20,14 @@ from fractal_server.app.routes.auth import current_active_user
22
20
  from fractal_server.app.routes.pagination import get_pagination_params
23
21
  from fractal_server.app.routes.pagination import PaginationRequest
24
22
  from fractal_server.app.routes.pagination import PaginationResponse
25
- from fractal_server.app.schemas._filter_validators import (
26
- validate_attribute_filters,
27
- )
28
- from fractal_server.app.schemas._filter_validators import validate_type_filters
29
- from fractal_server.app.schemas._validators import root_validate_dict_keys
30
23
  from fractal_server.images import SingleImage
31
24
  from fractal_server.images import SingleImageUpdate
32
- from fractal_server.images.models import AttributeFiltersType
33
25
  from fractal_server.images.tools import aggregate_attributes
34
26
  from fractal_server.images.tools import aggregate_types
35
27
  from fractal_server.images.tools import find_image_by_zarr_url
36
28
  from fractal_server.images.tools import match_filter
29
+ from fractal_server.types import AttributeFilters
30
+ from fractal_server.types import TypeFilters
37
31
 
38
32
  router = APIRouter()
39
33
 
@@ -45,18 +39,8 @@ class ImagePage(PaginationResponse[SingleImage]):
45
39
 
46
40
 
47
41
  class ImageQuery(BaseModel):
48
- type_filters: dict[str, bool] = Field(default_factory=dict)
49
- attribute_filters: AttributeFiltersType = Field(default_factory=dict)
50
-
51
- _dict_keys = model_validator(mode="before")(
52
- classmethod(root_validate_dict_keys)
53
- )
54
- _type_filters = field_validator("type_filters")(
55
- classmethod(validate_type_filters)
56
- )
57
- _attribute_filters = field_validator("attribute_filters")(
58
- classmethod(validate_attribute_filters)
59
- )
42
+ type_filters: TypeFilters = Field(default_factory=dict)
43
+ attribute_filters: AttributeFilters = Field(default_factory=dict)
60
44
 
61
45
 
62
46
  class ImageQueryWithZarrUrl(ImageQuery):
@@ -18,9 +18,9 @@ from fractal_server.app.models.v2 import HistoryImageCache
18
18
  from fractal_server.app.models.v2 import HistoryUnit
19
19
  from fractal_server.app.routes.auth import current_active_user
20
20
  from fractal_server.app.schemas.v2 import HistoryUnitStatus
21
- from fractal_server.images.models import AttributeFiltersType
22
21
  from fractal_server.images.tools import aggregate_types
23
22
  from fractal_server.images.tools import filter_image_list
23
+ from fractal_server.types import AttributeFilters
24
24
 
25
25
  router = APIRouter()
26
26
 
@@ -71,7 +71,7 @@ async def verify_unique_types(
71
71
 
72
72
 
73
73
  class NonProcessedImagesPayload(BaseModel):
74
- attribute_filters: AttributeFiltersType = Field(default_factory=dict)
74
+ attribute_filters: AttributeFilters = Field(default_factory=dict)
75
75
  type_filters: dict[str, bool] = Field(default_factory=dict)
76
76
 
77
77
 
@@ -15,17 +15,22 @@ def run_subprocess(
15
15
  logger = get_logger(logger_name)
16
16
  try:
17
17
  res = subprocess.run( # nosec
18
- shlex.split(cmd), check=True, capture_output=True, encoding="utf-8"
18
+ shlex.split(cmd),
19
+ check=True,
20
+ capture_output=True,
21
+ encoding="utf-8",
19
22
  )
20
23
  return res
21
24
  except subprocess.CalledProcessError as e:
22
- logger.debug(
25
+ logger.info(
23
26
  f"Command '{e.cmd}' returned non-zero exit status {e.returncode}."
24
27
  )
25
- logger.debug(f"stdout: {e.stdout}")
26
- logger.debug(f"stderr: {e.stderr}")
28
+ logger.info(f"stdout: {e.stdout}")
29
+ logger.info(f"stderr: {e.stderr}")
27
30
  raise e
28
31
  except Exception as e:
29
- logger.debug(f"An error occurred while running command: {cmd}")
30
- logger.debug(str(e))
32
+ logger.warning(
33
+ f"An unexpected error occurred while running command: {cmd}"
34
+ )
35
+ logger.warning(str(e))
31
36
  raise e
@@ -4,8 +4,9 @@ from typing import Optional
4
4
 
5
5
  from ..slurm_common.base_slurm_runner import BaseSlurmRunner
6
6
  from ..slurm_common.slurm_job_task_models import SlurmJob
7
- from fractal_server.app.runner.compress_folder import compress_folder
8
- from fractal_server.app.runner.extract_archive import extract_archive
7
+ from .run_subprocess import run_subprocess
8
+ from .tar_commands import get_tar_compression_cmd
9
+ from .tar_commands import get_tar_extraction_cmd
9
10
  from fractal_server.config import get_settings
10
11
  from fractal_server.logger import set_logger
11
12
  from fractal_server.ssh._fabric import FractalSSH
@@ -84,12 +85,8 @@ class SlurmSSHRunner(BaseSlurmRunner):
84
85
  workdir_remote = finished_slurm_jobs[0].workdir_remote
85
86
 
86
87
  # Define local/remote tarfile paths
87
- tarfile_path_local = (
88
- workdir_local.parent / f"{workdir_local.name}.tar.gz"
89
- ).as_posix()
90
- tarfile_path_remote = (
91
- workdir_remote.parent / f"{workdir_remote.name}.tar.gz"
92
- ).as_posix()
88
+ tarfile_path_local = workdir_local.with_suffix(".tar.gz").as_posix()
89
+ tarfile_path_remote = workdir_remote.with_suffix(".tar.gz").as_posix()
93
90
 
94
91
  # Create file list
95
92
  # NOTE: see issue 2483
@@ -130,11 +127,9 @@ class SlurmSSHRunner(BaseSlurmRunner):
130
127
 
131
128
  # Create remote tarfile
132
129
  t_0_tar = time.perf_counter()
133
- tar_command = (
134
- f"{self.python_worker_interpreter} "
135
- "-m fractal_server.app.runner.compress_folder "
136
- f"{workdir_remote.as_posix()} "
137
- f"--filelist {tmp_filelist_path}"
130
+ tar_command = get_tar_compression_cmd(
131
+ subfolder_path=workdir_remote,
132
+ filelist_path=tmp_filelist_path,
138
133
  )
139
134
  self.fractal_ssh.run_command(cmd=tar_command)
140
135
  t_1_tar = time.perf_counter()
@@ -157,54 +152,14 @@ class SlurmSSHRunner(BaseSlurmRunner):
157
152
  )
158
153
 
159
154
  # Extract tarfile locally
160
- extract_archive(Path(tarfile_path_local))
161
-
162
- # Remove local tarfile
155
+ target_dir, cmd_tar = get_tar_extraction_cmd(Path(tarfile_path_local))
156
+ target_dir.mkdir(exist_ok=True)
157
+ run_subprocess(cmd=cmd_tar, logger_name=logger.name)
163
158
  Path(tarfile_path_local).unlink(missing_ok=True)
164
159
 
165
160
  t_1 = time.perf_counter()
166
161
  logger.info(f"[_fetch_artifacts] End - elapsed={t_1 - t_0:.3f} s")
167
162
 
168
- def _send_inputs(self, jobs: list[SlurmJob]) -> None:
169
- """
170
- Transfer the jobs subfolder to the remote host.
171
- """
172
- for job in jobs:
173
- # Create local archive
174
- tarfile_path_local = compress_folder(
175
- job.workdir_local,
176
- filelist_path=None,
177
- )
178
- tarfile_name = Path(tarfile_path_local).name
179
- logger.info(f"Subfolder archive created at {tarfile_path_local}")
180
-
181
- # Transfer archive
182
- tarfile_path_remote = (
183
- job.workdir_remote.parent / tarfile_name
184
- ).as_posix()
185
- t_0_put = time.perf_counter()
186
- self.fractal_ssh.send_file(
187
- local=tarfile_path_local,
188
- remote=tarfile_path_remote,
189
- )
190
- t_1_put = time.perf_counter()
191
- logger.info(
192
- f"Subfolder archive transferred to {tarfile_path_remote}"
193
- f" - elapsed={t_1_put - t_0_put:.3f} s"
194
- )
195
-
196
- # Remove local archive
197
- Path(tarfile_path_local).unlink()
198
- logger.debug(f"Local archive {tarfile_path_local} removed")
199
-
200
- # Uncompress remote archive
201
- tar_command = (
202
- f"{self.python_worker_interpreter} -m "
203
- "fractal_server.app.runner.extract_archive "
204
- f"{tarfile_path_remote}"
205
- )
206
- self.fractal_ssh.run_command(cmd=tar_command)
207
-
208
163
  def _run_remote_cmd(self, cmd: str) -> str:
209
164
  stdout = self.fractal_ssh.run_command(cmd=cmd)
210
165
  return stdout
@@ -0,0 +1,65 @@
1
+ """
2
+ Prepare tar commands for task-subfolder compression/extraction.
3
+ """
4
+ from pathlib import Path
5
+
6
+
7
+ def get_tar_compression_cmd(
8
+ subfolder_path: Path,
9
+ filelist_path: Path | None,
10
+ ) -> tuple[str, str]:
11
+ """
12
+ Prepare command to compress e.g. `/path/dir` into `/path/dir.tar.gz`.
13
+
14
+ Note that `/path/dir.tar.gz` may already exist. In this case, it will
15
+ be overwritten.
16
+
17
+ Args:
18
+ subfolder_path: Absolute path to the folder to compress.
19
+ filelist_path: If set, to be used in the `--files-from` option.
20
+ expected_tarfile: If set, it should match to the returned one.
21
+
22
+ Returns:
23
+ tar command
24
+ """
25
+ tarfile_path = subfolder_path.with_suffix(".tar.gz")
26
+ if filelist_path is None:
27
+ cmd_tar = (
28
+ f"tar -c -z "
29
+ f"-f {tarfile_path} "
30
+ f"--directory={subfolder_path.as_posix()} "
31
+ "."
32
+ )
33
+ else:
34
+ cmd_tar = (
35
+ f"tar -c -z -f {tarfile_path} "
36
+ f"--directory={subfolder_path.as_posix()} "
37
+ f"--files-from={filelist_path.as_posix()} --ignore-failed-read"
38
+ )
39
+
40
+ return cmd_tar
41
+
42
+
43
+ def get_tar_extraction_cmd(archive_path: Path) -> tuple[Path, str]:
44
+ """
45
+ Prepare command to extract e.g. `/path/dir.tar.gz` into `/path/dir`.
46
+
47
+ Args:
48
+ archive_path: Absolute path to the tar.gz archive.
49
+
50
+ Returns:
51
+ Target extraction folder and tar command
52
+ """
53
+
54
+ # Prepare subfolder path
55
+ if archive_path.suffixes[-2:] != [".tar", ".gz"]:
56
+ raise ValueError(
57
+ "Archive path must end with `.tar.gz` "
58
+ f"(given: {archive_path.as_posix()})"
59
+ )
60
+ subfolder_path = archive_path.with_suffix("").with_suffix("")
61
+
62
+ cmd_tar = (
63
+ f"tar -xzvf {archive_path} --directory={subfolder_path.as_posix()}"
64
+ )
65
+ return subfolder_path, cmd_tar
@@ -7,7 +7,7 @@ from ..executors.local.get_local_config import get_local_backend_config
7
7
  from ..executors.local.runner import LocalRunner
8
8
  from ..set_start_and_last_task_index import set_start_and_last_task_index
9
9
  from .runner import execute_tasks_v2
10
- from fractal_server.images.models import AttributeFiltersType
10
+ from fractal_server.types import AttributeFilters
11
11
 
12
12
 
13
13
  def process_workflow(
@@ -20,7 +20,7 @@ def process_workflow(
20
20
  first_task_index: Optional[int] = None,
21
21
  last_task_index: Optional[int] = None,
22
22
  logger_name: str,
23
- job_attribute_filters: AttributeFiltersType,
23
+ job_attribute_filters: AttributeFilters,
24
24
  job_type_filters: dict[str, bool],
25
25
  user_id: int,
26
26
  **kwargs,
@@ -27,8 +27,8 @@ from ..executors.slurm_common.get_slurm_config import get_slurm_config
27
27
  from ..executors.slurm_ssh.runner import SlurmSSHRunner
28
28
  from ..set_start_and_last_task_index import set_start_and_last_task_index
29
29
  from .runner import execute_tasks_v2
30
- from fractal_server.images.models import AttributeFiltersType
31
30
  from fractal_server.logger import set_logger
31
+ from fractal_server.types import AttributeFilters
32
32
 
33
33
  logger = set_logger(__name__)
34
34
 
@@ -43,7 +43,7 @@ def process_workflow(
43
43
  first_task_index: Optional[int] = None,
44
44
  last_task_index: Optional[int] = None,
45
45
  logger_name: str,
46
- job_attribute_filters: AttributeFiltersType,
46
+ job_attribute_filters: AttributeFilters,
47
47
  job_type_filters: dict[str, bool],
48
48
  fractal_ssh: FractalSSH,
49
49
  worker_init: Optional[str] = None,
@@ -25,7 +25,7 @@ from ..executors.slurm_common.get_slurm_config import get_slurm_config
25
25
  from ..executors.slurm_sudo.runner import SudoSlurmRunner
26
26
  from ..set_start_and_last_task_index import set_start_and_last_task_index
27
27
  from .runner import execute_tasks_v2
28
- from fractal_server.images.models import AttributeFiltersType
28
+ from fractal_server.types import AttributeFilters
29
29
 
30
30
 
31
31
  def process_workflow(
@@ -38,7 +38,7 @@ def process_workflow(
38
38
  first_task_index: Optional[int] = None,
39
39
  last_task_index: Optional[int] = None,
40
40
  logger_name: str,
41
- job_attribute_filters: AttributeFiltersType,
41
+ job_attribute_filters: AttributeFilters,
42
42
  job_type_filters: dict[str, bool],
43
43
  user_id: int,
44
44
  # Slurm-specific
@@ -34,8 +34,8 @@ from fractal_server.app.runner.v2.db_tools import update_status_of_history_run
34
34
  from fractal_server.app.schemas.v2 import HistoryUnitStatus
35
35
  from fractal_server.app.schemas.v2 import TaskDumpV2
36
36
  from fractal_server.app.schemas.v2 import TaskGroupDumpV2
37
- from fractal_server.images.models import AttributeFiltersType
38
37
  from fractal_server.images.tools import merge_type_filters
38
+ from fractal_server.types import AttributeFilters
39
39
 
40
40
 
41
41
  def drop_none_attributes(attributes: dict[str, Any]) -> dict[str, Any]:
@@ -87,7 +87,7 @@ def execute_tasks_v2(
87
87
  Any,
88
88
  ],
89
89
  job_type_filters: dict[str, bool],
90
- job_attribute_filters: AttributeFiltersType,
90
+ job_attribute_filters: AttributeFilters,
91
91
  ) -> None:
92
92
  logger = logging.getLogger(logger_name)
93
93
 
@@ -4,12 +4,11 @@ from typing import Optional
4
4
  from pydantic import BaseModel
5
5
  from pydantic import ConfigDict
6
6
  from pydantic import Field
7
- from pydantic import field_validator
8
7
  from pydantic import ValidationError
9
8
 
10
9
  from ....images import SingleImageTaskOutput
11
10
  from fractal_server.app.runner.exceptions import TaskOutputValidationError
12
- from fractal_server.urls import normalize_url
11
+ from fractal_server.types import ZarrUrlStr
13
12
 
14
13
 
15
14
  class TaskOutput(BaseModel):
@@ -19,7 +18,7 @@ class TaskOutput(BaseModel):
19
18
  image_list_updates: list[SingleImageTaskOutput] = Field(
20
19
  default_factory=list
21
20
  )
22
- image_list_removals: list[str] = Field(default_factory=list)
21
+ image_list_removals: list[ZarrUrlStr] = Field(default_factory=list)
23
22
 
24
23
  def check_zarr_urls_are_unique(self) -> None:
25
24
  zarr_urls = [img.zarr_url for img in self.image_list_updates]
@@ -40,24 +39,14 @@ class TaskOutput(BaseModel):
40
39
  msg = f"{msg}\n{duplicate}"
41
40
  raise ValueError(msg)
42
41
 
43
- @field_validator("image_list_removals")
44
- @classmethod
45
- def normalize_paths(cls, v: list[str]) -> list[str]:
46
- return [normalize_url(zarr_url) for zarr_url in v]
47
-
48
42
 
49
43
  class InitArgsModel(BaseModel):
50
44
 
51
45
  model_config = ConfigDict(extra="forbid")
52
46
 
53
- zarr_url: str
47
+ zarr_url: ZarrUrlStr
54
48
  init_args: dict[str, Any] = Field(default_factory=dict)
55
49
 
56
- @field_validator("zarr_url")
57
- @classmethod
58
- def normalize_path(cls, v: str) -> str:
59
- return normalize_url(v)
60
-
61
50
 
62
51
  class InitTaskOutput(BaseModel):
63
52
 
@@ -3,12 +3,11 @@ from typing import Optional
3
3
  from fastapi_users import schemas
4
4
  from pydantic import BaseModel
5
5
  from pydantic import ConfigDict
6
+ from pydantic import EmailStr
6
7
  from pydantic import Field
7
- from pydantic import field_validator
8
- from pydantic import ValidationInfo
9
8
 
10
- from ._validators import NonEmptyString
11
- from ._validators import val_unique_list
9
+ from fractal_server.types import ListUniqueNonNegativeInt
10
+ from fractal_server.types import NonEmptyStr
12
11
 
13
12
  __all__ = (
14
13
  "UserRead",
@@ -56,24 +55,12 @@ class UserUpdate(schemas.BaseUserUpdate):
56
55
  """
57
56
 
58
57
  model_config = ConfigDict(extra="forbid")
59
-
60
- username: Optional[NonEmptyString] = None
61
-
62
- # Validators
63
-
64
- @field_validator(
65
- "username",
66
- "is_active",
67
- "is_verified",
68
- "is_superuser",
69
- "email",
70
- "password",
71
- )
72
- @classmethod
73
- def cant_set_none(cls, v, info: ValidationInfo):
74
- if v is None:
75
- raise ValueError(f"Cannot set {info.field_name}=None")
76
- return v
58
+ username: NonEmptyStr = None
59
+ password: NonEmptyStr = None
60
+ email: EmailStr = None
61
+ is_active: bool = None
62
+ is_superuser: bool = None
63
+ is_verified: bool = None
77
64
 
78
65
 
79
66
  class UserUpdateStrict(BaseModel):
@@ -94,14 +81,7 @@ class UserCreate(schemas.BaseUserCreate):
94
81
  username:
95
82
  """
96
83
 
97
- username: Optional[NonEmptyString] = None
98
-
99
- @field_validator("username")
100
- @classmethod
101
- def cant_set_none(cls, v, info: ValidationInfo):
102
- if v is None:
103
- raise ValueError(f"Cannot set {info.field_name}=None")
104
- return v
84
+ username: NonEmptyStr = None
105
85
 
106
86
 
107
87
  class UserUpdateGroups(BaseModel):
@@ -112,8 +92,4 @@ class UserUpdateGroups(BaseModel):
112
92
 
113
93
  model_config = ConfigDict(extra="forbid")
114
94
 
115
- group_ids: list[int] = Field(min_length=1)
116
-
117
- _group_ids = field_validator("group_ids")(
118
- classmethod(val_unique_list("group_ids"))
119
- )
95
+ group_ids: ListUniqueNonNegativeInt = Field(min_length=1)
@@ -5,11 +5,9 @@ from pydantic import BaseModel
5
5
  from pydantic import ConfigDict
6
6
  from pydantic import Field
7
7
  from pydantic import field_serializer
8
- from pydantic import field_validator
9
8
  from pydantic.types import AwareDatetime
10
9
 
11
- from ._validators import val_absolute_path
12
- from ._validators import val_unique_list
10
+ from fractal_server.types import ListUniqueAbsolutePathStr
13
11
 
14
12
  __all__ = (
15
13
  "UserGroupRead",
@@ -54,15 +52,7 @@ class UserGroupCreate(BaseModel):
54
52
  model_config = ConfigDict(extra="forbid")
55
53
 
56
54
  name: str
57
- viewer_paths: list[str] = Field(default_factory=list)
58
-
59
- @field_validator("viewer_paths")
60
- @classmethod
61
- def viewer_paths_validator(cls, value):
62
- for i, path in enumerate(value):
63
- value[i] = val_absolute_path(f"viewer_paths[{i}]")(cls, path)
64
- value = val_unique_list("viewer_paths")(cls, value)
65
- return value
55
+ viewer_paths: ListUniqueAbsolutePathStr = Field(default_factory=list)
66
56
 
67
57
 
68
58
  class UserGroupUpdate(BaseModel):
@@ -72,14 +62,4 @@ class UserGroupUpdate(BaseModel):
72
62
 
73
63
  model_config = ConfigDict(extra="forbid")
74
64
 
75
- viewer_paths: Optional[list[str]] = None
76
-
77
- @field_validator("viewer_paths")
78
- @classmethod
79
- def viewer_paths_validator(cls, value):
80
- if value is None:
81
- raise ValueError("Cannot set `viewer_paths=None`.")
82
- for i, path in enumerate(value):
83
- value[i] = val_absolute_path(f"viewer_paths[{i}]")(cls, path)
84
- value = val_unique_list("viewer_paths")(cls, value)
85
- return value
65
+ viewer_paths: ListUniqueAbsolutePathStr = None
@@ -0,0 +1,69 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel
4
+ from pydantic import ConfigDict
5
+ from pydantic import field_validator
6
+
7
+ from fractal_server.string_tools import validate_cmd
8
+ from fractal_server.types import AbsolutePathStr
9
+ from fractal_server.types import ListUniqueNonEmptyString
10
+ from fractal_server.types import NonEmptyStr
11
+
12
+ __all__ = (
13
+ "UserSettingsRead",
14
+ "UserSettingsReadStrict",
15
+ "UserSettingsUpdate",
16
+ "UserSettingsUpdateStrict",
17
+ )
18
+
19
+
20
+ class UserSettingsRead(BaseModel):
21
+ """
22
+ Schema reserved for superusers
23
+ """
24
+
25
+ id: int
26
+ ssh_host: Optional[str] = None
27
+ ssh_username: Optional[str] = None
28
+ ssh_private_key_path: Optional[str] = None
29
+ ssh_tasks_dir: Optional[str] = None
30
+ ssh_jobs_dir: Optional[str] = None
31
+ slurm_user: Optional[str] = None
32
+ slurm_accounts: list[str]
33
+ project_dir: Optional[str] = None
34
+
35
+
36
+ class UserSettingsReadStrict(BaseModel):
37
+ slurm_user: Optional[str] = None
38
+ slurm_accounts: list[str]
39
+ ssh_username: Optional[str] = None
40
+ project_dir: Optional[str] = None
41
+
42
+
43
+ class UserSettingsUpdate(BaseModel):
44
+ """
45
+ Schema reserved for superusers
46
+ """
47
+
48
+ model_config = ConfigDict(extra="forbid")
49
+
50
+ ssh_host: Optional[NonEmptyStr] = None
51
+ ssh_username: Optional[NonEmptyStr] = None
52
+ ssh_private_key_path: Optional[AbsolutePathStr] = None
53
+ ssh_tasks_dir: Optional[AbsolutePathStr] = None
54
+ ssh_jobs_dir: Optional[AbsolutePathStr] = None
55
+ slurm_user: Optional[NonEmptyStr] = None
56
+ slurm_accounts: Optional[ListUniqueNonEmptyString] = None
57
+ project_dir: Optional[AbsolutePathStr] = None
58
+
59
+ @field_validator("project_dir", mode="after")
60
+ @classmethod
61
+ def validate_project_dir(cls, value):
62
+ if value is not None:
63
+ validate_cmd(value)
64
+ return value
65
+
66
+
67
+ class UserSettingsUpdateStrict(BaseModel):
68
+ model_config = ConfigDict(extra="forbid")
69
+ slurm_accounts: Optional[ListUniqueNonEmptyString] = None