fractal-server 2.18.5__py3-none-any.whl → 2.19.0__py3-none-any.whl

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 (64) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/app/db/__init__.py +1 -7
  3. fractal_server/app/models/security.py +16 -0
  4. fractal_server/app/models/v2/dataset.py +0 -4
  5. fractal_server/app/models/v2/job.py +4 -0
  6. fractal_server/app/models/v2/task.py +0 -1
  7. fractal_server/app/models/v2/task_group.py +4 -0
  8. fractal_server/app/models/v2/workflow.py +2 -0
  9. fractal_server/app/models/v2/workflowtask.py +3 -0
  10. fractal_server/app/routes/admin/v2/job.py +0 -2
  11. fractal_server/app/routes/admin/v2/sharing.py +47 -0
  12. fractal_server/app/routes/admin/v2/task.py +0 -5
  13. fractal_server/app/routes/admin/v2/task_group_lifecycle.py +6 -0
  14. fractal_server/app/routes/api/__init__.py +4 -52
  15. fractal_server/app/routes/api/alive.py +13 -0
  16. fractal_server/app/routes/api/settings.py +44 -0
  17. fractal_server/app/routes/api/v2/__init__.py +0 -2
  18. fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +1 -20
  19. fractal_server/app/routes/api/v2/dataset.py +9 -8
  20. fractal_server/app/routes/api/v2/history.py +8 -8
  21. fractal_server/app/routes/api/v2/images.py +6 -6
  22. fractal_server/app/routes/api/v2/job.py +10 -12
  23. fractal_server/app/routes/api/v2/pre_submission_checks.py +3 -3
  24. fractal_server/app/routes/api/v2/project.py +7 -9
  25. fractal_server/app/routes/api/v2/sharing.py +17 -9
  26. fractal_server/app/routes/api/v2/submit.py +5 -3
  27. fractal_server/app/routes/api/v2/task.py +7 -9
  28. fractal_server/app/routes/api/v2/task_collection.py +4 -2
  29. fractal_server/app/routes/api/v2/task_collection_custom.py +2 -2
  30. fractal_server/app/routes/api/v2/task_collection_pixi.py +4 -2
  31. fractal_server/app/routes/api/v2/task_group.py +10 -30
  32. fractal_server/app/routes/api/v2/task_group_lifecycle.py +10 -4
  33. fractal_server/app/routes/api/v2/task_version_update.py +4 -3
  34. fractal_server/app/routes/api/v2/workflow.py +10 -11
  35. fractal_server/app/routes/api/v2/workflow_import.py +14 -45
  36. fractal_server/app/routes/api/v2/workflowtask.py +7 -12
  37. fractal_server/app/routes/auth/__init__.py +18 -1
  38. fractal_server/app/routes/auth/current_user.py +8 -0
  39. fractal_server/app/routes/auth/oauth.py +3 -1
  40. fractal_server/app/routes/auth/users.py +11 -0
  41. fractal_server/app/routes/aux/_versions.py +42 -0
  42. fractal_server/app/schemas/user.py +7 -0
  43. fractal_server/app/schemas/v2/__init__.py +0 -1
  44. fractal_server/app/schemas/v2/dumps.py +0 -1
  45. fractal_server/app/schemas/v2/task.py +0 -5
  46. fractal_server/app/schemas/v2/workflow.py +2 -0
  47. fractal_server/app/schemas/v2/workflowtask.py +6 -2
  48. fractal_server/app/security/__init__.py +8 -3
  49. fractal_server/migrations/versions/18a26fcdea5d_drop_dataset_history.py +41 -0
  50. fractal_server/migrations/versions/1bf8785755f9_add_description_to_workflow_and_.py +53 -0
  51. fractal_server/migrations/versions/5fb08bf05b14_drop_taskv2_source.py +36 -0
  52. fractal_server/migrations/versions/cfd13f7954e7_add_fractal_server_version_to_jobv2_and_.py +52 -0
  53. fractal_server/migrations/versions/e53dc51fdf93_add_useroauth_is_guest.py +36 -0
  54. fractal_server/runner/executors/local/runner.py +2 -0
  55. fractal_server/runner/executors/slurm_ssh/runner.py +5 -0
  56. fractal_server/runner/executors/slurm_sudo/runner.py +5 -0
  57. fractal_server/runner/v2/runner.py +0 -1
  58. fractal_server/runner/v2/submit_workflow.py +0 -3
  59. {fractal_server-2.18.5.dist-info → fractal_server-2.19.0.dist-info}/METADATA +3 -3
  60. {fractal_server-2.18.5.dist-info → fractal_server-2.19.0.dist-info}/RECORD +63 -56
  61. {fractal_server-2.18.5.dist-info → fractal_server-2.19.0.dist-info}/WHEEL +1 -1
  62. fractal_server/app/routes/api/v2/status_legacy.py +0 -156
  63. {fractal_server-2.18.5.dist-info → fractal_server-2.19.0.dist-info}/entry_points.txt +0 -0
  64. {fractal_server-2.18.5.dist-info → fractal_server-2.19.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,156 +0,0 @@
1
- from fastapi import APIRouter
2
- from fastapi import Depends
3
-
4
- from fractal_server.app.db import AsyncSession
5
- from fractal_server.app.db import get_async_db
6
- from fractal_server.app.models import UserOAuth
7
- from fractal_server.app.models.v2 import JobV2
8
- from fractal_server.app.routes.auth import current_user_act_ver_prof
9
- from fractal_server.app.schemas.v2.sharing import ProjectPermissions
10
- from fractal_server.app.schemas.v2.status_legacy import LegacyStatusRead
11
- from fractal_server.app.schemas.v2.status_legacy import WorkflowTaskStatusType
12
- from fractal_server.logger import set_logger
13
-
14
- from ._aux_functions import _get_dataset_check_access
15
- from ._aux_functions import _get_submitted_jobs_statement
16
- from ._aux_functions import _get_workflow_check_access
17
-
18
- router = APIRouter()
19
-
20
- logger = set_logger(__name__)
21
-
22
-
23
- @router.get(
24
- "/project/{project_id}/status-legacy/",
25
- response_model=LegacyStatusRead,
26
- )
27
- async def get_workflowtask_status(
28
- project_id: int,
29
- dataset_id: int,
30
- workflow_id: int,
31
- user: UserOAuth = Depends(current_user_act_ver_prof),
32
- db: AsyncSession = Depends(get_async_db),
33
- ) -> LegacyStatusRead | None:
34
- """
35
- Extract the status of all `WorkflowTaskV2` of a given `WorkflowV2` that ran
36
- on a given `DatasetV2`.
37
-
38
- *NOTE*: the current endpoint is not guaranteed to provide consistent
39
- results if the workflow task list is modified in a non-trivial way
40
- (that is, by adding intermediate tasks, removing tasks, or changing their
41
- order). See fractal-server GitHub issues: 793, 1083.
42
- """
43
- # Get the dataset DB entry
44
- output = await _get_dataset_check_access(
45
- project_id=project_id,
46
- dataset_id=dataset_id,
47
- user_id=user.id,
48
- required_permissions=ProjectPermissions.READ,
49
- db=db,
50
- )
51
- dataset = output["dataset"]
52
-
53
- # Get the workflow DB entry
54
- workflow = await _get_workflow_check_access(
55
- project_id=project_id,
56
- workflow_id=workflow_id,
57
- user_id=user.id,
58
- required_permissions=ProjectPermissions.READ,
59
- db=db,
60
- )
61
-
62
- # Check whether there exists a submitted job associated to this
63
- # workflow/dataset pair. If it does exist, it will be used later.
64
- # If there are multiple jobs, raise an error.
65
- res = await db.execute(
66
- _get_submitted_jobs_statement()
67
- .where(JobV2.dataset_id == dataset_id)
68
- .where(JobV2.workflow_id == workflow_id)
69
- )
70
- running_job = res.scalars().one_or_none()
71
-
72
- # Initialize empty dictionary for WorkflowTaskV2 status
73
- workflow_tasks_status_dict: dict = {}
74
-
75
- # Lowest priority: read status from DB, which corresponds to jobs that are
76
- # not running
77
- history = dataset.history
78
- for history_item in history:
79
- wftask_id = history_item["workflowtask"]["id"]
80
- wftask_status = history_item["status"]
81
- workflow_tasks_status_dict[wftask_id] = wftask_status
82
-
83
- if running_job is None:
84
- # If no job is running, the chronological-last history item is also the
85
- # positional-last workflow task to be included in the response.
86
- if len(history) > 0:
87
- last_valid_wftask_id = history[-1]["workflowtask"]["id"]
88
- else:
89
- last_valid_wftask_id = None
90
- else:
91
- # If a job is running, then gather more up-to-date information
92
-
93
- # Mid priority: Set all WorkflowTask's that are part of the running job
94
- # as "submitted"
95
- start = running_job.first_task_index
96
- end = running_job.last_task_index + 1
97
-
98
- running_job_wftasks = workflow.task_list[start:end]
99
- running_job_statuses = [
100
- workflow_tasks_status_dict.get(wft.id, None)
101
- for wft in running_job_wftasks
102
- ]
103
- try:
104
- first_submitted_index = running_job_statuses.index(
105
- WorkflowTaskStatusType.SUBMITTED
106
- )
107
- except ValueError:
108
- logger.warning(
109
- f"Job {running_job.id} is submitted but its task list does not"
110
- f" contain a {WorkflowTaskStatusType.SUBMITTED} task."
111
- )
112
- first_submitted_index = 0
113
-
114
- for wftask in running_job_wftasks[first_submitted_index:]:
115
- workflow_tasks_status_dict[wftask.id] = (
116
- WorkflowTaskStatusType.SUBMITTED
117
- )
118
-
119
- # The last workflow task that is included in the submitted job is also
120
- # the positional-last workflow task to be included in the response.
121
- try:
122
- last_valid_wftask_id = workflow.task_list[end - 1].id
123
- except IndexError as e:
124
- logger.warning(
125
- f"Handled IndexError in `get_workflowtask_status` ({str(e)})."
126
- )
127
- logger.warning(
128
- "Additional information: "
129
- f"{running_job.first_task_index=}; "
130
- f"{running_job.last_task_index=}; "
131
- f"{len(workflow.task_list)=}; "
132
- f"{dataset_id=}; "
133
- f"{workflow_id=}."
134
- )
135
- last_valid_wftask_id = None
136
- logger.warning(f"Now setting {last_valid_wftask_id=}.")
137
-
138
- # Based on previously-gathered information, clean up the response body
139
- clean_workflow_tasks_status_dict = {}
140
- for wf_task in workflow.task_list:
141
- wf_task_status = workflow_tasks_status_dict.get(wf_task.id)
142
- if wf_task_status is None:
143
- # If a wftask ID was not found, ignore it and continue
144
- continue
145
- clean_workflow_tasks_status_dict[str(wf_task.id)] = wf_task_status
146
- if wf_task_status == WorkflowTaskStatusType.FAILED:
147
- # Starting from the beginning of `workflow.task_list`, stop the
148
- # first time that you hit a failed job
149
- break
150
- if wf_task.id == last_valid_wftask_id:
151
- # Starting from the beginning of `workflow.task_list`, stop the
152
- # first time that you hit `last_valid_wftask_id``
153
- break
154
-
155
- response_body = LegacyStatusRead(status=clean_workflow_tasks_status_dict)
156
- return response_body