fractal-server 2.17.1a1__tar.gz → 2.18.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 (287) hide show
  1. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/PKG-INFO +3 -2
  2. fractal_server-2.18.0/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/__main__.py +21 -19
  4. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/db/__init__.py +3 -3
  5. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/__init__.py +1 -0
  6. fractal_server-2.18.0/fractal_server/app/models/linkuserproject.py +53 -0
  7. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/security.py +28 -8
  8. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/__init__.py +3 -1
  9. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/accounting.py +9 -1
  10. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/dataset.py +5 -1
  11. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/history.py +15 -1
  12. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/job.py +17 -2
  13. fractal_server-2.18.0/fractal_server/app/models/v2/profile.py +45 -0
  14. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/project.py +4 -10
  15. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/resource.py +17 -0
  16. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/task_group.py +4 -3
  17. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/workflow.py +2 -1
  18. fractal_server-2.18.0/fractal_server/app/routes/admin/v2/__init__.py +27 -0
  19. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/accounting.py +3 -3
  20. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/job.py +35 -24
  21. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/profile.py +3 -2
  22. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/resource.py +5 -5
  23. fractal_server-2.18.0/fractal_server/app/routes/admin/v2/sharing.py +103 -0
  24. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/task.py +37 -26
  25. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/task_group.py +94 -17
  26. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +21 -22
  27. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/__init__.py +1 -9
  28. fractal_server-2.18.0/fractal_server/app/routes/api/v2/__init__.py +72 -0
  29. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/_aux_functions.py +132 -124
  30. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/_aux_functions_history.py +51 -23
  31. fractal_server-2.18.0/fractal_server/app/routes/api/v2/_aux_functions_sharing.py +97 -0
  32. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +6 -8
  33. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +7 -9
  34. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +1 -2
  35. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/dataset.py +95 -102
  36. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/history.py +59 -33
  37. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/images.py +24 -9
  38. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/job.py +52 -33
  39. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/pre_submission_checks.py +16 -8
  40. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/project.py +65 -37
  41. fractal_server-2.18.0/fractal_server/app/routes/api/v2/sharing.py +311 -0
  42. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/status_legacy.py +31 -41
  43. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/submit.py +82 -78
  44. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/task.py +19 -20
  45. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/task_collection.py +41 -43
  46. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/task_collection_custom.py +19 -20
  47. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/task_collection_pixi.py +10 -11
  48. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/task_group.py +25 -24
  49. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +32 -32
  50. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/task_version_update.py +23 -19
  51. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/workflow.py +50 -55
  52. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/workflow_import.py +37 -37
  53. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/workflowtask.py +32 -26
  54. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/__init__.py +1 -3
  55. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/_aux_auth.py +101 -2
  56. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/current_user.py +2 -66
  57. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/group.py +8 -35
  58. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/login.py +1 -0
  59. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/oauth.py +4 -3
  60. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/register.py +4 -2
  61. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/router.py +2 -0
  62. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/auth/users.py +19 -10
  63. fractal_server-2.18.0/fractal_server/app/routes/auth/viewer_paths.py +43 -0
  64. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/aux/_job.py +1 -1
  65. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/aux/_runner.py +2 -2
  66. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/user.py +29 -12
  67. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/user_group.py +0 -15
  68. fractal_server-2.18.0/fractal_server/app/schemas/v2/__init__.py +78 -0
  69. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/accounting.py +11 -0
  70. fractal_server-2.18.0/fractal_server/app/schemas/v2/dataset.py +126 -0
  71. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/dumps.py +10 -9
  72. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/job.py +11 -11
  73. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/manifest.py +4 -3
  74. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/profile.py +53 -2
  75. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/project.py +3 -3
  76. fractal_server-2.18.0/fractal_server/app/schemas/v2/resource.py +242 -0
  77. fractal_server-2.18.0/fractal_server/app/schemas/v2/sharing.py +99 -0
  78. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/status_legacy.py +3 -3
  79. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/task.py +6 -7
  80. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/task_collection.py +5 -5
  81. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/task_group.py +16 -16
  82. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/workflow.py +16 -16
  83. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/workflowtask.py +16 -15
  84. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/security/__init__.py +5 -8
  85. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/security/signup_email.py +4 -5
  86. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/shutdown.py +6 -6
  87. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/config/__init__.py +0 -6
  88. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/config/_database.py +19 -20
  89. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/config/_email.py +30 -38
  90. fractal_server-2.18.0/fractal_server/config/_main.py +64 -0
  91. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/config/_oauth.py +17 -21
  92. fractal_server-2.18.0/fractal_server/data_migrations/2_18_0.py +30 -0
  93. fractal_server-2.18.0/fractal_server/exceptions.py +6 -0
  94. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/images/models.py +4 -5
  95. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/images/status_tools.py +4 -2
  96. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/main.py +75 -13
  97. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +4 -8
  98. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +1 -0
  99. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +1 -0
  100. fractal_server-2.18.0/fractal_server/migrations/versions/40d6d6511b20_add_index_to_history_models.py +47 -0
  101. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +1 -0
  102. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/49d0856e9569_drop_table.py +2 -3
  103. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +2 -1
  104. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +7 -19
  105. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +4 -10
  106. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +1 -0
  107. fractal_server-2.18.0/fractal_server/migrations/versions/7910eed4cf97_user_project_dirs_and_usergroup_viewer_.py +60 -0
  108. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +1 -0
  109. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +1 -0
  110. fractal_server-2.18.0/fractal_server/migrations/versions/88270f589c9b_add_prevent_new_submissions.py +39 -0
  111. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +2 -4
  112. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +1 -0
  113. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +2 -4
  114. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +1 -0
  115. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +1 -0
  116. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +1 -0
  117. fractal_server-2.18.0/fractal_server/migrations/versions/bc0e8b3327a7_project_sharing.py +72 -0
  118. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +4 -9
  119. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +1 -0
  120. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +1 -0
  121. fractal_server-2.18.0/fractal_server/migrations/versions/e0e717ae2f26_delete_linkuserproject_ondelete_project.py +50 -0
  122. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +1 -0
  123. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +1 -0
  124. fractal_server-2.18.0/fractal_server/migrations/versions/f0702066b007_one_submitted_job_per_dataset.py +40 -0
  125. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +1 -0
  126. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +4 -9
  127. fractal_server-2.18.0/fractal_server/runner/config/_local.py +24 -0
  128. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/config/_slurm.py +39 -33
  129. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/config/slurm_mem_to_MB.py +0 -1
  130. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/base_runner.py +29 -4
  131. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/local/get_local_config.py +1 -0
  132. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/local/runner.py +14 -13
  133. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_common/_batching.py +9 -20
  134. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_common/base_slurm_runner.py +53 -27
  135. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_common/get_slurm_config.py +14 -7
  136. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_common/remote.py +3 -1
  137. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_common/slurm_config.py +2 -0
  138. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +1 -3
  139. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_ssh/runner.py +16 -11
  140. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_ssh/tar_commands.py +1 -0
  141. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +1 -0
  142. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_sudo/runner.py +16 -11
  143. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/task_files.py +9 -3
  144. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/_local.py +12 -6
  145. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/_slurm_ssh.py +14 -7
  146. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/_slurm_sudo.py +14 -7
  147. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/db_tools.py +0 -1
  148. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/deduplicate_list.py +2 -1
  149. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/runner.py +44 -28
  150. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/runner_functions.py +22 -28
  151. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/submit_workflow.py +29 -15
  152. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/ssh/_fabric.py +6 -13
  153. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/string_tools.py +0 -1
  154. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/config/_python.py +16 -9
  155. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/utils.py +0 -1
  156. fractal_server-2.18.0/fractal_server/tasks/v2/__init__.py +0 -0
  157. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/_utils.py +3 -3
  158. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/collect.py +15 -18
  159. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/collect_pixi.py +14 -16
  160. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/deactivate.py +14 -15
  161. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/deactivate_pixi.py +7 -7
  162. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/delete.py +6 -8
  163. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/reactivate.py +12 -12
  164. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/reactivate_pixi.py +12 -12
  165. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/_utils.py +3 -3
  166. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/collect.py +19 -24
  167. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/collect_pixi.py +22 -24
  168. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/deactivate.py +17 -15
  169. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +8 -7
  170. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/delete.py +12 -10
  171. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/reactivate.py +16 -16
  172. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +13 -14
  173. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/1_create_venv.sh +2 -0
  174. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/2_pip_install.sh +2 -0
  175. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +2 -0
  176. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/4_pip_show.sh +2 -0
  177. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +3 -1
  178. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +2 -0
  179. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +2 -0
  180. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/pixi_2_install.sh +2 -0
  181. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +2 -0
  182. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/utils_background.py +10 -10
  183. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/utils_database.py +5 -5
  184. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/utils_package_names.py +1 -2
  185. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/utils_pixi.py +1 -3
  186. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/types/__init__.py +98 -1
  187. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/types/validators/__init__.py +3 -0
  188. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/types/validators/_common_validators.py +33 -3
  189. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/types/validators/_workflow_task_arguments_validators.py +1 -2
  190. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/utils.py +1 -0
  191. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/zip_tools.py +34 -0
  192. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/pyproject.toml +19 -5
  193. fractal_server-2.17.1a1/fractal_server/__init__.py +0 -1
  194. fractal_server-2.17.1a1/fractal_server/app/models/linkuserproject.py +0 -11
  195. fractal_server-2.17.1a1/fractal_server/app/models/v2/profile.py +0 -16
  196. fractal_server-2.17.1a1/fractal_server/app/routes/admin/v2/__init__.py +0 -28
  197. fractal_server-2.17.1a1/fractal_server/app/routes/admin/v2/project.py +0 -41
  198. fractal_server-2.17.1a1/fractal_server/app/routes/api/v2/__init__.py +0 -73
  199. fractal_server-2.17.1a1/fractal_server/app/schemas/v2/__init__.py +0 -71
  200. fractal_server-2.17.1a1/fractal_server/app/schemas/v2/dataset.py +0 -80
  201. fractal_server-2.17.1a1/fractal_server/app/schemas/v2/resource.py +0 -137
  202. fractal_server-2.17.1a1/fractal_server/config/_data.py +0 -68
  203. fractal_server-2.17.1a1/fractal_server/config/_main.py +0 -78
  204. fractal_server-2.17.1a1/fractal_server/exceptions.py +0 -2
  205. fractal_server-2.17.1a1/fractal_server/runner/config/_local.py +0 -21
  206. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/LICENSE +0 -0
  207. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/README.md +0 -0
  208. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/alembic.ini +0 -0
  209. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/__init__.py +0 -0
  210. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/linkusergroup.py +0 -0
  211. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/task.py +0 -0
  212. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/models/v2/workflowtask.py +0 -0
  213. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/__init__.py +0 -0
  214. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/__init__.py +0 -0
  215. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/_aux_functions.py +0 -0
  216. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  217. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  218. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/aux/__init__.py +0 -0
  219. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/aux/validate_user_profile.py +0 -0
  220. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/routes/pagination.py +1 -1
  221. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/__init__.py +0 -0
  222. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/app/schemas/v2/history.py +0 -0
  223. fractal_server-2.17.1a1/fractal_server/py.typed → fractal_server-2.18.0/fractal_server/config/_data.py +0 -0
  224. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/config/_settings_config.py +0 -0
  225. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/data_migrations/README.md +0 -0
  226. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/data_migrations/tools.py +0 -0
  227. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/gunicorn_fractal.py +0 -0
  228. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/images/__init__.py +0 -0
  229. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/images/tools.py +0 -0
  230. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/logger.py +1 -1
  231. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/env.py +0 -0
  232. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/naming_convention.py +0 -0
  233. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +1 -1
  234. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +1 -1
  235. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/1a83a5260664_rename.py +1 -1
  236. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +1 -1
  237. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +1 -1
  238. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +1 -1
  239. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +1 -1
  240. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +1 -1
  241. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +1 -1
  242. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +1 -1
  243. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +1 -1
  244. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +1 -1
  245. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +1 -1
  246. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +1 -1
  247. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +1 -1
  248. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +1 -1
  249. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +1 -1
  250. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +1 -1
  251. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +1 -1
  252. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +1 -1
  253. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +1 -1
  254. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +1 -1
  255. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +1 -1
  256. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +1 -1
  257. fractal_server-2.17.1a1/fractal_server/runner/__init__.py → fractal_server-2.18.0/fractal_server/py.typed +0 -0
  258. {fractal_server-2.17.1a1/fractal_server/runner/executors → fractal_server-2.18.0/fractal_server/runner}/__init__.py +0 -0
  259. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/components.py +0 -0
  260. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/config/__init__.py +0 -0
  261. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/exceptions.py +0 -0
  262. {fractal_server-2.17.1a1/fractal_server/runner/executors/local → fractal_server-2.18.0/fractal_server/runner/executors}/__init__.py +0 -0
  263. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/call_command_wrapper.py +0 -0
  264. {fractal_server-2.17.1a1/fractal_server/runner/executors/slurm_common → fractal_server-2.18.0/fractal_server/runner/executors/local}/__init__.py +0 -0
  265. {fractal_server-2.17.1a1/fractal_server/runner/executors/slurm_ssh → fractal_server-2.18.0/fractal_server/runner/executors/slurm_common}/__init__.py +0 -0
  266. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_common/_job_states.py +0 -0
  267. {fractal_server-2.17.1a1/fractal_server/runner/executors/slurm_sudo → fractal_server-2.18.0/fractal_server/runner/executors/slurm_ssh}/__init__.py +0 -0
  268. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  269. {fractal_server-2.17.1a1/fractal_server/runner/v2 → fractal_server-2.18.0/fractal_server/runner/executors/slurm_sudo}/__init__.py +0 -0
  270. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/filenames.py +0 -0
  271. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/set_start_and_last_task_index.py +0 -0
  272. {fractal_server-2.17.1a1/fractal_server/tasks → fractal_server-2.18.0/fractal_server/runner}/v2/__init__.py +0 -0
  273. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/merge_outputs.py +0 -0
  274. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/v2/task_interface.py +0 -0
  275. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/runner/versions.py +0 -0
  276. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/ssh/__init__.py +0 -0
  277. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/syringe.py +1 -1
  278. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/__init__.py +0 -0
  279. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/config/__init__.py +0 -0
  280. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/config/_pixi.py +1 -1
  281. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/local/__init__.py +0 -0
  282. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  283. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -0
  284. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  285. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/tasks/v2/utils_templates.py +0 -0
  286. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/types/validators/_filter_validators.py +0 -0
  287. {fractal_server-2.17.1a1 → fractal_server-2.18.0}/fractal_server/urls.py +0 -0
@@ -1,16 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fractal-server
3
- Version: 2.17.1a1
3
+ Version: 2.18.0
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License-Expression: BSD-3-Clause
6
6
  License-File: LICENSE
7
7
  Author: Tommaso Comparin
8
8
  Author-email: tommaso.comparin@exact-lab.it
9
- Requires-Python: >=3.11,<3.14
9
+ Requires-Python: >=3.11,<3.15
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
14
15
  Requires-Dist: alembic (>=1.13.1,<2.0.0)
15
16
  Requires-Dist: fabric (>=3.2.2,<3.3.0)
16
17
  Requires-Dist: fastapi (>=0.120.0,<0.121.0)
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.18.0"
@@ -7,7 +7,6 @@ from pathlib import Path
7
7
  import uvicorn
8
8
  from pydantic import ValidationError
9
9
 
10
-
11
10
  parser = ap.ArgumentParser(description="fractal-server commands")
12
11
 
13
12
  subparsers = parser.add_subparsers(title="Commands", dest="cmd", required=True)
@@ -48,9 +47,7 @@ openapi_parser.add_argument(
48
47
  # fractalctl set-db
49
48
  set_db_parser = subparsers.add_parser(
50
49
  "set-db",
51
- description=(
52
- "Initialise/upgrade database schemas and create first group&user."
53
- ),
50
+ description="Initialise/upgrade database schemas.",
54
51
  )
55
52
 
56
53
  # fractalctl init-db-data
@@ -114,12 +111,13 @@ def set_db():
114
111
  Call alembic to upgrade to the latest migration.
115
112
  Ref: https://stackoverflow.com/a/56683030/283972
116
113
  """
117
- from fractal_server.syringe import Inject
118
- from fractal_server.config import get_db_settings
114
+ from pathlib import Path
119
115
 
120
116
  import alembic.config
121
- from pathlib import Path
117
+
122
118
  import fractal_server
119
+ from fractal_server.config import get_db_settings
120
+ from fractal_server.syringe import Inject
123
121
 
124
122
  # Validate DB settings
125
123
  Inject(get_db_settings)
@@ -140,15 +138,18 @@ def init_db_data(
140
138
  admin_password: str | None = None,
141
139
  admin_project_dir: str | None = None,
142
140
  ) -> None:
143
- from fractal_server.app.security import _create_first_user
144
- from fractal_server.app.security import _create_first_group
141
+ from sqlalchemy import func
142
+ from sqlalchemy import select
143
+
145
144
  from fractal_server.app.db import get_sync_db
146
- from sqlalchemy import select, func
145
+ from fractal_server.app.models import Profile
146
+ from fractal_server.app.models import Resource
147
147
  from fractal_server.app.models.security import UserOAuth
148
- from fractal_server.app.models import Resource, Profile
149
- from fractal_server.app.schemas.v2.resource import cast_serialize_resource
150
- from fractal_server.app.schemas.v2.profile import cast_serialize_profile
151
148
  from fractal_server.app.schemas.v2 import ResourceType
149
+ from fractal_server.app.schemas.v2.profile import cast_serialize_profile
150
+ from fractal_server.app.schemas.v2.resource import cast_serialize_resource
151
+ from fractal_server.app.security import _create_first_group
152
+ from fractal_server.app.security import _create_first_user
152
153
 
153
154
  # Create default group and user
154
155
  print()
@@ -166,7 +167,8 @@ def init_db_data(
166
167
  "`--admin-pwd` and `--admin-project-dir`. Exit."
167
168
  )
168
169
  sys.exit(1)
169
- if admin_password and admin_email:
170
+
171
+ if admin_email:
170
172
  asyncio.run(
171
173
  _create_first_user(
172
174
  email=admin_email,
@@ -185,9 +187,7 @@ def init_db_data(
185
187
  if resource and profile:
186
188
  with next(get_sync_db()) as db:
187
189
  # Preliminary check
188
- num_resources = db.execute(
189
- select(func.count(Resource.id))
190
- ).scalar()
190
+ num_resources = db.execute(select(func.count(Resource.id))).scalar()
191
191
  if num_resources != 0:
192
192
  print(f"There exist already {num_resources=} resources. Exit.")
193
193
  sys.exit(1)
@@ -270,10 +270,12 @@ def update_db_data():
270
270
  Apply data migrations.
271
271
  """
272
272
 
273
- import fractal_server
273
+ import os
274
274
  from importlib import import_module
275
+
275
276
  from packaging.version import parse
276
- import os
277
+
278
+ import fractal_server
277
279
 
278
280
  def _slugify_version(raw_version: str) -> str:
279
281
  v = parse(raw_version)
@@ -2,6 +2,7 @@
2
2
  `db` module, loosely adapted from
3
3
  https://testdriven.io/blog/fastapi-sqlmodel/#async-sqlmodel
4
4
  """
5
+
5
6
  from collections.abc import AsyncGenerator
6
7
  from collections.abc import Generator
7
8
 
@@ -15,7 +16,6 @@ from fractal_server.config import get_db_settings
15
16
  from fractal_server.logger import set_logger
16
17
  from fractal_server.syringe import Inject
17
18
 
18
-
19
19
  logger = set_logger(__name__)
20
20
 
21
21
 
@@ -46,7 +46,7 @@ class DB:
46
46
 
47
47
  cls._engine_async = create_async_engine(
48
48
  db_settings.DATABASE_URL,
49
- echo=db_settings.DB_ECHO,
49
+ echo=(db_settings.DB_ECHO == "true"),
50
50
  future=True,
51
51
  pool_pre_ping=True,
52
52
  )
@@ -63,7 +63,7 @@ class DB:
63
63
 
64
64
  cls._engine_sync = create_engine(
65
65
  db_settings.DATABASE_URL,
66
- echo=db_settings.DB_ECHO,
66
+ echo=(db_settings.DB_ECHO == "true"),
67
67
  future=True,
68
68
  pool_pre_ping=True,
69
69
  )
@@ -3,6 +3,7 @@ Note that this module is imported from `fractal_server/migrations/env.py`,
3
3
  thus we should always export all relevant database models from here or they
4
4
  will not be picked up by alembic.
5
5
  """
6
+
6
7
  from .linkusergroup import LinkUserGroup # noqa: F401
7
8
  from .linkuserproject import LinkUserProjectV2 # noqa: F401
8
9
  from .security import * # noqa
@@ -0,0 +1,53 @@
1
+ from sqlmodel import BOOLEAN
2
+ from sqlmodel import CheckConstraint
3
+ from sqlmodel import Column
4
+ from sqlmodel import Field
5
+ from sqlmodel import Index
6
+ from sqlmodel import SQLModel
7
+ from sqlmodel import String
8
+ from sqlmodel import column
9
+
10
+
11
+ class LinkUserProjectV2(SQLModel, table=True):
12
+ """
13
+ Crossing table between User and ProjectV2
14
+ """
15
+
16
+ project_id: int = Field(
17
+ foreign_key="projectv2.id", primary_key=True, ondelete="CASCADE"
18
+ )
19
+ user_id: int = Field(foreign_key="user_oauth.id", primary_key=True)
20
+
21
+ # TODO-2.18.1 drop server_default
22
+ is_owner: bool = Field(
23
+ sa_column=Column(BOOLEAN, server_default="true", nullable=False)
24
+ )
25
+ # TODO-2.18.1 drop server_default
26
+ is_verified: bool = Field(
27
+ sa_column=Column(BOOLEAN, server_default="true", nullable=False)
28
+ )
29
+ # TODO-2.18.1 drop server_default
30
+ permissions: str = Field(
31
+ sa_column=Column(String, server_default="'rwx'", nullable=False)
32
+ )
33
+
34
+ __table_args__ = (
35
+ Index(
36
+ "ix_linkuserprojectv2_one_owner_per_project",
37
+ "project_id",
38
+ unique=True,
39
+ postgresql_where=column("is_owner").is_(True),
40
+ ),
41
+ CheckConstraint(
42
+ "NOT (is_owner AND NOT is_verified)",
43
+ name="owner_is_verified",
44
+ ),
45
+ CheckConstraint(
46
+ "NOT (is_owner AND permissions <> 'rwx')",
47
+ name="owner_full_permissions",
48
+ ),
49
+ CheckConstraint(
50
+ "permissions IN ('r', 'rw', 'rwx')",
51
+ name="valid_permissions",
52
+ ),
53
+ )
@@ -6,7 +6,6 @@ from pydantic import EmailStr
6
6
  from sqlalchemy import Column
7
7
  from sqlalchemy import String
8
8
  from sqlalchemy.dialects.postgresql import ARRAY
9
- from sqlalchemy.dialects.postgresql import JSONB
10
9
  from sqlalchemy.types import DateTime
11
10
  from sqlmodel import Field
12
11
  from sqlmodel import Relationship
@@ -52,21 +51,39 @@ class UserOAuth(SQLModel, table=True):
52
51
  """
53
52
  ORM model for the `user_oauth` database table.
54
53
 
55
- This class is a modification of SQLModelBaseUserDB from from
56
- fastapi_users_db_sqlmodel. Original Copyright: 2022 François Voron,
57
- released under MIT licence.
54
+ This class is a modification of
55
+ [`SQLModelBaseUserDB`](https://github.com/fastapi-users/fastapi-users-db-sqlmodel/blob/83980d7f20886120f4636a102ab1822b4c366f63/fastapi_users_db_sqlmodel/__init__.py#L15-L32)
56
+ from `fastapi_users_db_sqlmodel`.
57
+ Original Copyright: 2022 François Voron, released under MIT licence.
58
+
59
+ Note that several class attributes are
60
+ [the default ones from `fastapi-users`
61
+ ](https://fastapi-users.github.io/fastapi-users/latest/configuration/schemas/).
58
62
 
59
63
  Attributes:
60
64
  id:
61
65
  email:
62
66
  hashed_password:
63
67
  is_active:
68
+ If this is `False`, the user has no access to the `/api/v2/`
69
+ endpoints.
64
70
  is_superuser:
65
71
  is_verified:
72
+ If this is `False`, the user has no access to the `/api/v2/`
73
+ endpoints.
66
74
  oauth_accounts:
67
75
  profile_id:
76
+ Foreign key linking the user to a `Profile`. If this is unset,
77
+ the user has no access to the `/api/v2/` endpoints.
68
78
  project_dir:
79
+ Absolute path of the user's project directory. This is used (A) as
80
+ a default base folder for the `zarr_dir` of new datasets (where
81
+ the output Zarr are located), and (B) as a folder which is included
82
+ by default in the paths that a user is allowed to stream (if the
83
+ `fractal-data` integration is set up).
84
+ two goals:
69
85
  slurm_accounts:
86
+ List of SLURM accounts that the user can select upon running a job.
70
87
  """
71
88
 
72
89
  model_config = ConfigDict(from_attributes=True)
@@ -95,7 +112,13 @@ class UserOAuth(SQLModel, table=True):
95
112
  ondelete="RESTRICT",
96
113
  )
97
114
 
98
- project_dir: str
115
+ # TODO-2.18.1: drop `project_dir`
116
+ project_dir: str | None = Field(default=None, nullable=True)
117
+ # TODO-2.18.1: `project_dirs: list[str] = Field(min_length=1)`
118
+ project_dirs: list[str] = Field(
119
+ sa_column=Column(ARRAY(String), nullable=False, server_default="{}"),
120
+ )
121
+
99
122
  slurm_accounts: list[str] = Field(
100
123
  sa_column=Column(ARRAY(String), server_default="{}"),
101
124
  )
@@ -117,6 +140,3 @@ class UserGroup(SQLModel, table=True):
117
140
  default_factory=get_timestamp,
118
141
  sa_column=Column(DateTime(timezone=True), nullable=False),
119
142
  )
120
- viewer_paths: list[str] = Field(
121
- sa_column=Column(JSONB, server_default="[]", nullable=False)
122
- )
@@ -1,7 +1,9 @@
1
1
  """
2
2
  v2 `models` module
3
3
  """
4
- from ..linkuserproject import LinkUserProjectV2
4
+
5
+ from fractal_server.app.models.linkuserproject import LinkUserProjectV2
6
+
5
7
  from .accounting import AccountingRecord
6
8
  from .accounting import AccountingRecordSlurm
7
9
  from .dataset import DatasetV2
@@ -7,10 +7,14 @@ from sqlalchemy.types import DateTime
7
7
  from sqlmodel import Field
8
8
  from sqlmodel import SQLModel
9
9
 
10
- from ....utils import get_timestamp
10
+ from fractal_server.utils import get_timestamp
11
11
 
12
12
 
13
13
  class AccountingRecord(SQLModel, table=True):
14
+ """
15
+ AccountingRecord table.
16
+ """
17
+
14
18
  id: int | None = Field(default=None, primary_key=True)
15
19
  user_id: int = Field(foreign_key="user_oauth.id", nullable=False)
16
20
  timestamp: datetime = Field(
@@ -22,6 +26,10 @@ class AccountingRecord(SQLModel, table=True):
22
26
 
23
27
 
24
28
  class AccountingRecordSlurm(SQLModel, table=True):
29
+ """
30
+ AccountingRecordSlurm table.
31
+ """
32
+
25
33
  id: int | None = Field(default=None, primary_key=True)
26
34
  user_id: int = Field(foreign_key="user_oauth.id", nullable=False)
27
35
  timestamp: datetime = Field(
@@ -9,10 +9,14 @@ from sqlmodel import Field
9
9
  from sqlmodel import Relationship
10
10
  from sqlmodel import SQLModel
11
11
 
12
- from ....utils import get_timestamp
12
+ from fractal_server.utils import get_timestamp
13
13
 
14
14
 
15
15
  class DatasetV2(SQLModel, table=True):
16
+ """
17
+ Dataset table.
18
+ """
19
+
16
20
  model_config = ConfigDict(arbitrary_types_allowed=True)
17
21
 
18
22
  id: int | None = Field(default=None, primary_key=True)
@@ -10,10 +10,14 @@ from sqlalchemy.types import DateTime
10
10
  from sqlmodel import Field
11
11
  from sqlmodel import SQLModel
12
12
 
13
- from ....utils import get_timestamp
13
+ from fractal_server.utils import get_timestamp
14
14
 
15
15
 
16
16
  class HistoryRun(SQLModel, table=True):
17
+ """
18
+ HistoryRun table.
19
+ """
20
+
17
21
  model_config = ConfigDict(arbitrary_types_allowed=True)
18
22
 
19
23
  id: int | None = Field(default=None, primary_key=True)
@@ -45,10 +49,15 @@ class HistoryRun(SQLModel, table=True):
45
49
 
46
50
 
47
51
  class HistoryUnit(SQLModel, table=True):
52
+ """
53
+ HistoryUnit table.
54
+ """
55
+
48
56
  id: int | None = Field(default=None, primary_key=True)
49
57
  history_run_id: int = Field(
50
58
  foreign_key="historyrun.id",
51
59
  ondelete="CASCADE",
60
+ index=True,
52
61
  )
53
62
 
54
63
  logfile: str
@@ -60,6 +69,10 @@ class HistoryUnit(SQLModel, table=True):
60
69
 
61
70
 
62
71
  class HistoryImageCache(SQLModel, table=True):
72
+ """
73
+ HistoryImageCache table.
74
+ """
75
+
63
76
  zarr_url: str = Field(primary_key=True)
64
77
  dataset_id: int = Field(
65
78
  primary_key=True,
@@ -77,4 +90,5 @@ class HistoryImageCache(SQLModel, table=True):
77
90
  latest_history_unit_id: int = Field(
78
91
  foreign_key="historyunit.id",
79
92
  ondelete="CASCADE",
93
+ index=True,
80
94
  )
@@ -6,13 +6,19 @@ from sqlalchemy import Column
6
6
  from sqlalchemy.dialects.postgresql import JSONB
7
7
  from sqlalchemy.types import DateTime
8
8
  from sqlmodel import Field
9
+ from sqlmodel import Index
9
10
  from sqlmodel import SQLModel
11
+ from sqlmodel import text
10
12
 
11
- from fractal_server.app.schemas.v2 import JobStatusTypeV2
13
+ from fractal_server.app.schemas.v2 import JobStatusType
12
14
  from fractal_server.utils import get_timestamp
13
15
 
14
16
 
15
17
  class JobV2(SQLModel, table=True):
18
+ """
19
+ Job table.
20
+ """
21
+
16
22
  model_config = ConfigDict(arbitrary_types_allowed=True)
17
23
 
18
24
  id: int | None = Field(default=None, primary_key=True)
@@ -52,7 +58,7 @@ class JobV2(SQLModel, table=True):
52
58
  end_timestamp: datetime | None = Field(
53
59
  default=None, sa_column=Column(DateTime(timezone=True))
54
60
  )
55
- status: str = JobStatusTypeV2.SUBMITTED
61
+ status: str = JobStatusType.SUBMITTED
56
62
  log: str | None = None
57
63
  executor_error_log: str | None = None
58
64
 
@@ -62,3 +68,12 @@ class JobV2(SQLModel, table=True):
62
68
  type_filters: dict[str, bool] = Field(
63
69
  sa_column=Column(JSONB, nullable=False, server_default="{}")
64
70
  )
71
+
72
+ __table_args__ = (
73
+ Index(
74
+ "ix_jobv2_one_submitted_job_per_dataset",
75
+ "dataset_id",
76
+ unique=True,
77
+ postgresql_where=text(f"status = '{JobStatusType.SUBMITTED}'"),
78
+ ),
79
+ )
@@ -0,0 +1,45 @@
1
+ from sqlmodel import Field
2
+ from sqlmodel import SQLModel
3
+
4
+
5
+ class Profile(SQLModel, table=True):
6
+ """
7
+ Profile table.
8
+ """
9
+
10
+ id: int | None = Field(default=None, primary_key=True)
11
+
12
+ resource_id: int = Field(foreign_key="resource.id", ondelete="RESTRICT")
13
+
14
+ resource_type: str
15
+ """
16
+ Type of resource (either `local`, `slurm_sudo` or `slurm_ssh`).
17
+ """
18
+
19
+ name: str = Field(unique=True)
20
+ """
21
+ Profile name.
22
+ """
23
+
24
+ username: str | None = None
25
+ """
26
+ Username to be impersonated, either via `sudo -u` or via `ssh`.
27
+ """
28
+
29
+ ssh_key_path: str | None = None
30
+ """
31
+ Path to the private SSH key of user `username` (only relevant if
32
+ `resource_type="slurm_ssh"`).
33
+ """
34
+
35
+ jobs_remote_dir: str | None = None
36
+ """
37
+ Remote path of the job folder (only relevant if
38
+ `resource_type="slurm_ssh"`).
39
+ """
40
+
41
+ tasks_remote_dir: str | None = None
42
+ """
43
+ Remote path of the task folder (only relevant if
44
+ `resource_type="slurm_ssh"`).
45
+ """
@@ -3,15 +3,16 @@ from datetime import datetime
3
3
  from sqlalchemy import Column
4
4
  from sqlalchemy.types import DateTime
5
5
  from sqlmodel import Field
6
- from sqlmodel import Relationship
7
6
  from sqlmodel import SQLModel
8
7
 
9
- from .. import LinkUserProjectV2
10
- from fractal_server.app.models import UserOAuth
11
8
  from fractal_server.utils import get_timestamp
12
9
 
13
10
 
14
11
  class ProjectV2(SQLModel, table=True):
12
+ """
13
+ Project table.
14
+ """
15
+
15
16
  id: int | None = Field(default=None, primary_key=True)
16
17
  name: str
17
18
 
@@ -20,10 +21,3 @@ class ProjectV2(SQLModel, table=True):
20
21
  default_factory=get_timestamp,
21
22
  sa_column=Column(DateTime(timezone=True), nullable=False),
22
23
  )
23
-
24
- user_list: list[UserOAuth] = Relationship(
25
- link_model=LinkUserProjectV2,
26
- sa_relationship_kwargs={
27
- "lazy": "selectin",
28
- },
29
- )
@@ -5,6 +5,7 @@ from typing import Self
5
5
  from sqlalchemy import Column
6
6
  from sqlalchemy.dialects.postgresql import JSONB
7
7
  from sqlalchemy.types import DateTime
8
+ from sqlmodel import BOOLEAN
8
9
  from sqlmodel import CheckConstraint
9
10
  from sqlmodel import Field
10
11
  from sqlmodel import SQLModel
@@ -13,6 +14,10 @@ from fractal_server.utils import get_timestamp
13
14
 
14
15
 
15
16
  class Resource(SQLModel, table=True):
17
+ """
18
+ Resource table.
19
+ """
20
+
16
21
  id: int | None = Field(default=None, primary_key=True)
17
22
 
18
23
  type: str
@@ -39,6 +44,18 @@ class Resource(SQLModel, table=True):
39
44
  Address for ssh connections, when `type="slurm_ssh"`.
40
45
  """
41
46
 
47
+ prevent_new_submissions: bool = Field(
48
+ sa_column=Column(
49
+ BOOLEAN,
50
+ server_default="false",
51
+ nullable=False,
52
+ ),
53
+ )
54
+ """
55
+ When set to true: Prevent new job submissions and stop execution of
56
+ ongoing jobs as soon as the current task is complete.
57
+ """
58
+
42
59
  jobs_local_dir: str
43
60
  """
44
61
  Base local folder for job subfolders (containing artifacts and logs).
@@ -8,9 +8,10 @@ from sqlmodel import Field
8
8
  from sqlmodel import Relationship
9
9
  from sqlmodel import SQLModel
10
10
 
11
- from .task import TaskV2
12
11
  from fractal_server.utils import get_timestamp
13
12
 
13
+ from .task import TaskV2
14
+
14
15
 
15
16
  def _check_origin_not_pixi(origin: str):
16
17
  """
@@ -22,10 +23,10 @@ def _check_origin_not_pixi(origin: str):
22
23
 
23
24
  def _create_dependency_string(pinned_versions: dict[str, str]) -> str:
24
25
  """
25
- Expand e.g. `{"a": "1.2", "b": "3"}` into `"a==1.2 b==3"`.
26
+ Expand e.g. `{"a": "1.2", "b": "3"}` into `'"a==1.2" "b==3"'`.
26
27
  """
27
28
  output = " ".join(
28
- [f"{key}=={value}" for key, value in pinned_versions.items()]
29
+ [f'"{key}=={value}"' for key, value in pinned_versions.items()]
29
30
  )
30
31
  return output
31
32
 
@@ -7,7 +7,8 @@ from sqlmodel import Field
7
7
  from sqlmodel import Relationship
8
8
  from sqlmodel import SQLModel
9
9
 
10
- from ....utils import get_timestamp
10
+ from fractal_server.utils import get_timestamp
11
+
11
12
  from .workflowtask import WorkflowTaskV2
12
13
 
13
14
 
@@ -0,0 +1,27 @@
1
+ """
2
+ `admin/v2` module
3
+ """
4
+
5
+ from fastapi import APIRouter
6
+
7
+ from .accounting import router as accounting_router
8
+ from .impersonate import router as impersonate_router
9
+ from .job import router as job_router
10
+ from .profile import router as profile_router
11
+ from .resource import router as resource_router
12
+ from .sharing import router as sharing_router
13
+ from .task import router as task_router
14
+ from .task_group import router as task_group_router
15
+ from .task_group_lifecycle import router as task_group_lifecycle_router
16
+
17
+ router_admin = APIRouter()
18
+
19
+ router_admin.include_router(accounting_router, prefix="/accounting")
20
+ router_admin.include_router(job_router, prefix="/job")
21
+ router_admin.include_router(task_router, prefix="/task")
22
+ router_admin.include_router(task_group_router, prefix="/task-group")
23
+ router_admin.include_router(task_group_lifecycle_router, prefix="/task-group")
24
+ router_admin.include_router(impersonate_router, prefix="/impersonate")
25
+ router_admin.include_router(resource_router, prefix="/resource")
26
+ router_admin.include_router(profile_router, prefix="/profile")
27
+ router_admin.include_router(sharing_router, prefix="/linkuserproject")
@@ -14,9 +14,9 @@ from fractal_server.app.models import UserOAuth
14
14
  from fractal_server.app.models.v2 import AccountingRecord
15
15
  from fractal_server.app.models.v2 import AccountingRecordSlurm
16
16
  from fractal_server.app.routes.auth import current_superuser_act
17
- from fractal_server.app.routes.pagination import get_pagination_params
18
17
  from fractal_server.app.routes.pagination import PaginationRequest
19
18
  from fractal_server.app.routes.pagination import PaginationResponse
19
+ from fractal_server.app.routes.pagination import get_pagination_params
20
20
  from fractal_server.app.schemas.v2 import AccountingRecordRead
21
21
 
22
22
 
@@ -67,11 +67,11 @@ async def query_accounting(
67
67
  res = await db.execute(stm)
68
68
  records = res.scalars().all()
69
69
 
70
- return PaginationResponse[AccountingRecordRead](
70
+ return dict(
71
71
  total_count=total_count,
72
72
  page_size=page_size,
73
73
  current_page=page,
74
- items=[record.model_dump() for record in records],
74
+ items=records,
75
75
  )
76
76
 
77
77