fractal-server 2.0.0a5__tar.gz → 2.0.0a8__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 (166) hide show
  1. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/PKG-INFO +1 -1
  2. fractal_server-2.0.0a8/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v2/dataset.py +0 -1
  4. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v2/project.py +0 -1
  5. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/dataset.py +9 -0
  6. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/images.py +56 -0
  7. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/submit.py +0 -9
  8. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/task_interface.py +10 -0
  9. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/_validators.py +7 -6
  10. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/dataset.py +13 -5
  11. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/dumps.py +0 -2
  12. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/project.py +0 -3
  13. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/workflow.py +2 -2
  14. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/images/__init__.py +1 -0
  15. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/images/models.py +39 -0
  16. fractal_server-2.0.0a5/fractal_server/migrations/versions/d71e732236cd_v2.py → fractal_server-2.0.0a8/fractal_server/migrations/versions/80e12e1bc4fd_v2.py +4 -6
  17. fractal_server-2.0.0a8/fractal_server/urls.py +13 -0
  18. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/pyproject.toml +2 -2
  19. fractal_server-2.0.0a5/fractal_server/__init__.py +0 -1
  20. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/LICENSE +0 -0
  21. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/README.md +0 -0
  22. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/__main__.py +0 -0
  23. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/alembic.ini +0 -0
  24. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/__init__.py +0 -0
  25. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/db/__init__.py +0 -0
  26. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/__init__.py +0 -0
  27. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/linkuserproject.py +0 -0
  28. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/security.py +0 -0
  29. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/state.py +0 -0
  30. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v1/__init__.py +0 -0
  31. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v1/dataset.py +0 -0
  32. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v1/job.py +0 -0
  33. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v1/project.py +0 -0
  34. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v1/task.py +0 -0
  35. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v1/workflow.py +0 -0
  36. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v2/__init__.py +0 -0
  37. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v2/job.py +0 -0
  38. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v2/task.py +0 -0
  39. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v2/workflow.py +0 -0
  40. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/models/v2/workflowtask.py +0 -0
  41. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/__init__.py +0 -0
  42. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/admin/__init__.py +0 -0
  43. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/admin/v1.py +0 -0
  44. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/admin/v2.py +0 -0
  45. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/__init__.py +0 -0
  46. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/__init__.py +0 -0
  47. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/_aux_functions.py +0 -0
  48. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/dataset.py +0 -0
  49. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/job.py +0 -0
  50. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/project.py +0 -0
  51. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/task.py +0 -0
  52. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/task_collection.py +0 -0
  53. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/workflow.py +0 -0
  54. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v1/workflowtask.py +0 -0
  55. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  56. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  57. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/job.py +0 -0
  58. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/project.py +0 -0
  59. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/task.py +0 -0
  60. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  61. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/task_legacy.py +0 -0
  62. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  63. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  64. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/auth.py +0 -0
  65. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/aux/__init__.py +0 -0
  66. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/aux/_job.py +0 -0
  67. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/routes/aux/_runner.py +0 -0
  68. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/.gitignore +0 -0
  69. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/__init__.py +0 -0
  70. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/async_wrap.py +0 -0
  71. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/components.py +0 -0
  72. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/exceptions.py +0 -0
  73. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/__init__.py +0 -0
  74. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
  75. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
  76. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/_check_jobs_status.py +0 -0
  77. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/_executor_wait_thread.py +0 -0
  78. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
  79. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/_subprocess_run_as_user.py +0 -0
  80. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/executor.py +0 -0
  81. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
  82. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/filenames.py +0 -0
  83. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  84. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/task_files.py +0 -0
  85. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/__init__.py +0 -0
  86. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_common.py +0 -0
  87. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
  88. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
  89. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
  90. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_local/executor.py +0 -0
  91. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
  92. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
  93. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
  94. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/common.py +0 -0
  95. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
  96. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/__init__.py +0 -0
  97. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
  98. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
  99. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
  100. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/_local/executor.py +0 -0
  101. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/_slurm/__init__.py +0 -0
  102. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/_slurm/_submit_setup.py +0 -0
  103. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/_slurm/get_slurm_config.py +0 -0
  104. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  105. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
  106. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  107. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/runner.py +0 -0
  108. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  109. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  110. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/runner/v2/v1_compat.py +0 -0
  111. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/__init__.py +0 -0
  112. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/state.py +0 -0
  113. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/user.py +0 -0
  114. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/__init__.py +0 -0
  115. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/applyworkflow.py +0 -0
  116. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/dataset.py +0 -0
  117. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/dumps.py +0 -0
  118. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/manifest.py +0 -0
  119. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/project.py +0 -0
  120. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/task.py +0 -0
  121. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/task_collection.py +0 -0
  122. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v1/workflow.py +0 -0
  123. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/__init__.py +0 -0
  124. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/job.py +0 -0
  125. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/manifest.py +0 -0
  126. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/task.py +0 -0
  127. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  128. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  129. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/app/security/__init__.py +0 -0
  130. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/config.py +0 -0
  131. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/data_migrations/README.md +0 -0
  132. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/images/tools.py +0 -0
  133. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/logger.py +0 -0
  134. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/main.py +0 -0
  135. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/README +0 -0
  136. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/env.py +0 -0
  137. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/script.py.mako +0 -0
  138. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  139. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  140. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  141. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  142. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  143. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  144. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  145. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  146. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  147. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  148. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  149. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  150. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  151. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  152. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  153. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/py.typed +0 -0
  154. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/syringe.py +0 -0
  155. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/__init__.py +0 -0
  156. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/endpoint_operations.py +0 -0
  157. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/utils.py +0 -0
  158. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v1/_TaskCollectPip.py +0 -0
  159. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v1/__init__.py +0 -0
  160. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v1/background_operations.py +0 -0
  161. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v1/get_collection_data.py +0 -0
  162. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v2/_TaskCollectPip.py +0 -0
  163. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v2/__init__.py +0 -0
  164. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v2/background_operations.py +0 -0
  165. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/tasks/v2/get_collection_data.py +0 -0
  166. {fractal_server-2.0.0a5 → fractal_server-2.0.0a8}/fractal_server/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fractal-server
3
- Version: 2.0.0a5
3
+ Version: 2.0.0a8
4
4
  Summary: Server component of the Fractal analytics platform
5
5
  Home-page: https://github.com/fractal-analytics-platform/fractal-server
6
6
  License: BSD-3-Clause
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.0.0a8"
@@ -28,7 +28,6 @@ class DatasetV2(SQLModel, table=True):
28
28
  history: list[dict[str, Any]] = Field(
29
29
  sa_column=Column(JSON, server_default="[]", nullable=False)
30
30
  )
31
- read_only: bool = False
32
31
 
33
32
  timestamp_created: datetime = Field(
34
33
  default_factory=get_timestamp,
@@ -16,7 +16,6 @@ class ProjectV2(SQLModel, table=True):
16
16
 
17
17
  id: Optional[int] = Field(default=None, primary_key=True)
18
18
  name: str
19
- read_only: bool = False
20
19
  timestamp_created: datetime = Field(
21
20
  default_factory=get_timestamp,
22
21
  sa_column=Column(DateTime(timezone=True), nullable=False),
@@ -134,6 +134,15 @@ async def update_dataset(
134
134
  )
135
135
  db_dataset = output["dataset"]
136
136
 
137
+ if (dataset_update.zarr_dir is not None) and (len(db_dataset.images) != 0):
138
+ raise HTTPException(
139
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
140
+ detail=(
141
+ "Cannot modify `zarr_dir` because the dataset has a non-empty "
142
+ "image list."
143
+ ),
144
+ )
145
+
137
146
  for key, value in dataset_update.dict(exclude_unset=True).items():
138
147
  setattr(db_dataset, key, value)
139
148
 
@@ -17,6 +17,8 @@ from fractal_server.app.security import current_active_user
17
17
  from fractal_server.app.security import User
18
18
  from fractal_server.images import Filters
19
19
  from fractal_server.images import SingleImage
20
+ from fractal_server.images import SingleImageUpdate
21
+ from fractal_server.images.tools import find_image_by_zarr_url
20
22
  from fractal_server.images.tools import match_filter
21
23
 
22
24
  router = APIRouter()
@@ -56,6 +58,15 @@ async def post_new_image(
56
58
  )
57
59
  dataset = output["dataset"]
58
60
 
61
+ if not new_image.zarr_url.startswith(dataset.zarr_dir):
62
+ raise HTTPException(
63
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
64
+ detail=(
65
+ "Cannot create image with zarr_url which is not relative to "
66
+ f"{dataset.zarr_dir}."
67
+ ),
68
+ )
69
+
59
70
  if new_image.zarr_url in dataset.image_zarr_urls:
60
71
  raise HTTPException(
61
72
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
@@ -213,3 +224,48 @@ async def delete_dataset_images(
213
224
  await db.commit()
214
225
 
215
226
  return Response(status_code=status.HTTP_204_NO_CONTENT)
227
+
228
+
229
+ @router.patch(
230
+ "/project/{project_id}/dataset/{dataset_id}/images/",
231
+ response_model=SingleImage,
232
+ status_code=status.HTTP_200_OK,
233
+ )
234
+ async def patch_dataset_image(
235
+ project_id: int,
236
+ dataset_id: int,
237
+ image_update: SingleImageUpdate,
238
+ user: User = Depends(current_active_user),
239
+ db: AsyncSession = Depends(get_async_db),
240
+ ):
241
+ output = await _get_dataset_check_owner(
242
+ project_id=project_id,
243
+ dataset_id=dataset_id,
244
+ user_id=user.id,
245
+ db=db,
246
+ )
247
+ db_dataset = output["dataset"]
248
+
249
+ ret = find_image_by_zarr_url(
250
+ images=db_dataset.images, zarr_url=image_update.zarr_url
251
+ )
252
+ if ret is None:
253
+ raise HTTPException(
254
+ status_code=status.HTTP_404_NOT_FOUND,
255
+ detail=(
256
+ f"No image with zarr_url '{image_update.zarr_url}' in "
257
+ f"DatasetV2 {dataset_id}."
258
+ ),
259
+ )
260
+ index = ret["index"]
261
+
262
+ for key, value in image_update.dict(
263
+ exclude_none=True, exclude={"zarr_url"}
264
+ ).items():
265
+ db_dataset.images[index][key] = value
266
+
267
+ flag_modified(db_dataset, "images")
268
+
269
+ await db.commit()
270
+ await db.close()
271
+ return db_dataset.images[index]
@@ -59,15 +59,6 @@ async def apply_workflow(
59
59
  project = output["project"]
60
60
  dataset = output["dataset"]
61
61
 
62
- if dataset.read_only:
63
- raise HTTPException(
64
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
65
- detail=(
66
- "Cannot apply workflow because dataset "
67
- f"({dataset_id=}) is read_only."
68
- ),
69
- )
70
-
71
62
  workflow = await _get_workflow_check_owner(
72
63
  project_id=project_id, workflow_id=workflow_id, user_id=user.id, db=db
73
64
  )
@@ -2,9 +2,11 @@ from typing import Any
2
2
 
3
3
  from pydantic import BaseModel
4
4
  from pydantic import Field
5
+ from pydantic import validator
5
6
 
6
7
  from ....images import SingleImageTaskOutput
7
8
  from fractal_server.images import Filters
9
+ from fractal_server.urls import normalize_url
8
10
 
9
11
 
10
12
  class TaskOutput(BaseModel):
@@ -34,6 +36,10 @@ class TaskOutput(BaseModel):
34
36
  msg = f"{msg}\n{duplicate}"
35
37
  raise ValueError(msg)
36
38
 
39
+ @validator("image_list_removals")
40
+ def normalize_paths(cls, v: list[str]) -> list[str]:
41
+ return [normalize_url(zarr_url) for zarr_url in v]
42
+
37
43
 
38
44
  class InitArgsModel(BaseModel):
39
45
  class Config:
@@ -42,6 +48,10 @@ class InitArgsModel(BaseModel):
42
48
  zarr_url: str
43
49
  init_args: dict[str, Any] = Field(default_factory=dict)
44
50
 
51
+ @validator("zarr_url")
52
+ def normalize_path(cls, v: str) -> str:
53
+ return normalize_url(v)
54
+
45
55
 
46
56
  class InitTaskOutput(BaseModel):
47
57
  class Config:
@@ -2,6 +2,7 @@ import os
2
2
  from datetime import datetime
3
3
  from datetime import timezone
4
4
  from typing import Any
5
+ from typing import Optional
5
6
 
6
7
 
7
8
  def valstr(attribute: str, accept_none: bool = False):
@@ -12,7 +13,7 @@ def valstr(attribute: str, accept_none: bool = False):
12
13
  If `accept_none`, the validator also accepts `None`.
13
14
  """
14
15
 
15
- def val(string: str):
16
+ def val(string: Optional[str]) -> Optional[str]:
16
17
  if string is None:
17
18
  if accept_none:
18
19
  return string
@@ -29,7 +30,7 @@ def valstr(attribute: str, accept_none: bool = False):
29
30
 
30
31
 
31
32
  def valdictkeys(attribute: str):
32
- def val(d: dict[str, Any]):
33
+ def val(d: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]:
33
34
  """
34
35
  Apply valstr to every key of the dictionary, and fail if there are
35
36
  identical keys.
@@ -55,7 +56,7 @@ def valint(attribute: str, min_val: int = 1):
55
56
  database entry) is greater or equal to min_val.
56
57
  """
57
58
 
58
- def val(integer: int):
59
+ def val(integer: Optional[int]) -> Optional[int]:
59
60
  if integer is None:
60
61
  raise ValueError(f"Integer attribute '{attribute}' cannot be None")
61
62
  if integer < min_val:
@@ -73,7 +74,7 @@ def val_absolute_path(attribute: str):
73
74
  Check that a string attribute is an absolute path
74
75
  """
75
76
 
76
- def val(string: str):
77
+ def val(string: Optional[str]) -> str:
77
78
  if string is None:
78
79
  raise ValueError(f"String attribute '{attribute}' cannot be None")
79
80
  s = string.strip()
@@ -90,7 +91,7 @@ def val_absolute_path(attribute: str):
90
91
 
91
92
 
92
93
  def val_unique_list(attribute: str):
93
- def val(must_be_unique: list):
94
+ def val(must_be_unique: Optional[list]) -> Optional[list]:
94
95
  if must_be_unique is not None:
95
96
  if len(set(must_be_unique)) != len(must_be_unique):
96
97
  raise ValueError(f"`{attribute}` list has repetitions")
@@ -100,7 +101,7 @@ def val_unique_list(attribute: str):
100
101
 
101
102
 
102
103
  def valutc(attribute: str):
103
- def val(timestamp: datetime):
104
+ def val(timestamp: Optional[datetime]) -> Optional[datetime]:
104
105
  """
105
106
  Replacing `tzinfo` with `timezone.utc` is just required by SQLite data.
106
107
  If using Postgres, this function leaves the datetime exactly as it is.
@@ -8,10 +8,11 @@ from pydantic import validator
8
8
 
9
9
  from .._validators import valstr
10
10
  from .._validators import valutc
11
- from ..v1.project import ProjectReadV1
12
11
  from .dumps import WorkflowTaskDumpV2
12
+ from .project import ProjectReadV2
13
13
  from .workflowtask import WorkflowTaskStatusTypeV2
14
14
  from fractal_server.images import Filters
15
+ from fractal_server.urls import normalize_url
15
16
 
16
17
 
17
18
  class _DatasetHistoryItemV2(BaseModel):
@@ -45,12 +46,15 @@ class DatasetCreateV2(BaseModel, extra=Extra.forbid):
45
46
 
46
47
  name: str
47
48
 
48
- read_only: bool = False
49
49
  zarr_dir: str
50
50
 
51
51
  filters: Filters = Field(default_factory=Filters)
52
52
 
53
53
  # Validators
54
+ @validator("zarr_dir")
55
+ def normalize_zarr_dir(cls, v: str) -> str:
56
+ return normalize_url(v)
57
+
54
58
  _name = validator("name", allow_reuse=True)(valstr("name"))
55
59
 
56
60
 
@@ -60,10 +64,9 @@ class DatasetReadV2(BaseModel):
60
64
  name: str
61
65
 
62
66
  project_id: int
63
- project: ProjectReadV1
67
+ project: ProjectReadV2
64
68
 
65
69
  history: list[_DatasetHistoryItemV2]
66
- read_only: bool
67
70
 
68
71
  timestamp_created: datetime
69
72
 
@@ -81,9 +84,14 @@ class DatasetUpdateV2(BaseModel):
81
84
  extra = "forbid"
82
85
 
83
86
  name: Optional[str]
84
- read_only: Optional[bool]
85
87
  zarr_dir: Optional[str]
86
88
  filters: Optional[Filters]
87
89
 
88
90
  # Validators
91
+ @validator("zarr_dir")
92
+ def normalize_zarr_dir(cls, v: Optional[str]) -> Optional[str]:
93
+ if v is not None:
94
+ return normalize_url(v)
95
+ return v
96
+
89
97
  _name = validator("name", allow_reuse=True)(valstr("name"))
@@ -22,7 +22,6 @@ class ProjectDumpV2(BaseModel, extra=Extra.forbid):
22
22
 
23
23
  id: int
24
24
  name: str
25
- read_only: bool
26
25
  timestamp_created: str
27
26
 
28
27
 
@@ -80,7 +79,6 @@ class DatasetDumpV2(BaseModel):
80
79
  id: int
81
80
  name: str
82
81
  project_id: int
83
- read_only: bool
84
82
  timestamp_created: str
85
83
 
86
84
  zarr_dir: str
@@ -12,7 +12,6 @@ from .._validators import valutc
12
12
  class ProjectCreateV2(BaseModel, extra=Extra.forbid):
13
13
 
14
14
  name: str
15
- read_only: bool = False
16
15
  # Validators
17
16
  _name = validator("name", allow_reuse=True)(valstr("name"))
18
17
 
@@ -21,7 +20,6 @@ class ProjectReadV2(BaseModel):
21
20
 
22
21
  id: int
23
22
  name: str
24
- read_only: bool
25
23
  timestamp_created: datetime
26
24
  # Validators
27
25
  _timestamp_created = validator("timestamp_created", allow_reuse=True)(
@@ -32,6 +30,5 @@ class ProjectReadV2(BaseModel):
32
30
  class ProjectUpdateV2(BaseModel):
33
31
 
34
32
  name: Optional[str]
35
- read_only: Optional[bool]
36
33
  # Validators
37
34
  _name = validator("name", allow_reuse=True)(valstr("name"))
@@ -7,7 +7,7 @@ from pydantic import validator
7
7
 
8
8
  from .._validators import valstr
9
9
  from .._validators import valutc
10
- from ..v1.project import ProjectReadV1
10
+ from .project import ProjectReadV2
11
11
  from .workflowtask import WorkflowTaskExportV2
12
12
  from .workflowtask import WorkflowTaskImportV2
13
13
  from .workflowtask import WorkflowTaskReadV2
@@ -27,7 +27,7 @@ class WorkflowReadV2(BaseModel):
27
27
  name: str
28
28
  project_id: int
29
29
  task_list: list[WorkflowTaskReadV2]
30
- project: ProjectReadV1
30
+ project: ProjectReadV2
31
31
  timestamp_created: datetime
32
32
 
33
33
  _timestamp_created = validator("timestamp_created", allow_reuse=True)(
@@ -1,3 +1,4 @@
1
1
  from .models import Filters # noqa: F401
2
2
  from .models import SingleImage # noqa: F401
3
3
  from .models import SingleImageTaskOutput # noqa: F401
4
+ from .models import SingleImageUpdate # noqa: F401
@@ -7,6 +7,7 @@ from pydantic import Field
7
7
  from pydantic import validator
8
8
 
9
9
  from fractal_server.app.schemas._validators import valdictkeys
10
+ from fractal_server.urls import normalize_url
10
11
 
11
12
 
12
13
  class SingleImageBase(BaseModel):
@@ -32,6 +33,15 @@ class SingleImageBase(BaseModel):
32
33
  )
33
34
  _types = validator("types", allow_reuse=True)(valdictkeys("types"))
34
35
 
36
+ @validator("zarr_url")
37
+ def normalize_zarr_url(cls, v: str) -> str:
38
+ return normalize_url(v)
39
+
40
+ @validator("origin")
41
+ def normalize_orig(cls, v: Optional[str]) -> Optional[str]:
42
+ if v is not None:
43
+ return normalize_url(v)
44
+
35
45
 
36
46
  class SingleImageTaskOutput(SingleImageBase):
37
47
  """
@@ -70,6 +80,35 @@ class SingleImage(SingleImageBase):
70
80
  return v
71
81
 
72
82
 
83
+ class SingleImageUpdate(BaseModel):
84
+ zarr_url: str
85
+ attributes: Optional[dict[str, Any]]
86
+ types: Optional[dict[str, bool]]
87
+
88
+ @validator("zarr_url")
89
+ def normalize_zarr_url(cls, v: str) -> str:
90
+ return normalize_url(v)
91
+
92
+ @validator("attributes")
93
+ def validate_attributes(
94
+ cls, v: dict[str, Any]
95
+ ) -> dict[str, Union[int, float, str, bool]]:
96
+ if v is not None:
97
+ # validate keys
98
+ valdictkeys("attributes")(v)
99
+ # validate values
100
+ for key, value in v.items():
101
+ if not isinstance(value, (int, float, str, bool)):
102
+ raise ValueError(
103
+ f"SingleImageUpdate.attributes[{key}] must be a scalar"
104
+ " (int, float, str or bool). "
105
+ f"Given {value} ({type(value)})"
106
+ )
107
+ return v
108
+
109
+ _types = validator("types", allow_reuse=True)(valdictkeys("types"))
110
+
111
+
73
112
  class Filters(BaseModel):
74
113
  attributes: dict[str, Any] = Field(default_factory=dict)
75
114
  types: dict[str, bool] = Field(default_factory=dict)
@@ -1,8 +1,8 @@
1
- """v2
1
+ """V2
2
2
 
3
- Revision ID: d71e732236cd
3
+ Revision ID: 80e12e1bc4fd
4
4
  Revises: 9fd26a2b0de4
5
- Create Date: 2024-04-05 11:09:17.639183
5
+ Create Date: 2024-04-12 10:13:58.085788
6
6
 
7
7
  """
8
8
  import sqlalchemy as sa
@@ -11,7 +11,7 @@ from alembic import op
11
11
 
12
12
 
13
13
  # revision identifiers, used by Alembic.
14
- revision = "d71e732236cd"
14
+ revision = "80e12e1bc4fd"
15
15
  down_revision = "9fd26a2b0de4"
16
16
  branch_labels = None
17
17
  depends_on = None
@@ -23,7 +23,6 @@ def upgrade() -> None:
23
23
  "projectv2",
24
24
  sa.Column("id", sa.Integer(), nullable=False),
25
25
  sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
26
- sa.Column("read_only", sa.Boolean(), nullable=False),
27
26
  sa.Column(
28
27
  "timestamp_created", sa.DateTime(timezone=True), nullable=False
29
28
  ),
@@ -81,7 +80,6 @@ def upgrade() -> None:
81
80
  sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
82
81
  sa.Column("project_id", sa.Integer(), nullable=False),
83
82
  sa.Column("history", sa.JSON(), server_default="[]", nullable=False),
84
- sa.Column("read_only", sa.Boolean(), nullable=False),
85
83
  sa.Column(
86
84
  "timestamp_created", sa.DateTime(timezone=True), nullable=False
87
85
  ),
@@ -0,0 +1,13 @@
1
+ from os.path import normpath
2
+
3
+
4
+ def normalize_url(url: str) -> str:
5
+ if url.startswith("/"):
6
+ return normpath(url)
7
+ elif url.startswith("s3"):
8
+ # It would be better to have a NotImplementedError
9
+ # but Pydantic Validation + FastAPI require
10
+ # ValueError, TypeError or AssertionError
11
+ raise ValueError("S3 handling not implemented yet")
12
+ else:
13
+ raise ValueError("URLs must begin with '/' or 's3'.")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "fractal-server"
3
- version = "2.0.0a5"
3
+ version = "2.0.0a8"
4
4
  description = "Server component of the Fractal analytics platform"
5
5
  authors = [
6
6
  "Jacopo Nespolo <jacopo.nespolo@exact-lab.it>",
@@ -86,7 +86,7 @@ filterwarnings = [
86
86
  ]
87
87
 
88
88
  [tool.bumpver]
89
- current_version = "2.0.0a5"
89
+ current_version = "2.0.0a8"
90
90
  version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
91
91
  commit_message = "bump version {old_version} -> {new_version}"
92
92
  commit = true
@@ -1 +0,0 @@
1
- __VERSION__ = "2.0.0a5"