fractal-server 2.17.2__py3-none-any.whl → 2.18.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.
- fractal_server/__init__.py +1 -1
- fractal_server/__main__.py +2 -1
- fractal_server/app/models/linkuserproject.py +40 -0
- fractal_server/app/models/security.py +7 -5
- fractal_server/app/models/v2/job.py +13 -2
- fractal_server/app/models/v2/resource.py +13 -0
- fractal_server/app/routes/admin/v2/__init__.py +11 -11
- fractal_server/app/routes/admin/v2/accounting.py +2 -2
- fractal_server/app/routes/admin/v2/job.py +34 -23
- fractal_server/app/routes/admin/v2/sharing.py +103 -0
- fractal_server/app/routes/admin/v2/task.py +9 -8
- fractal_server/app/routes/admin/v2/task_group.py +94 -16
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +20 -20
- fractal_server/app/routes/api/__init__.py +0 -9
- fractal_server/app/routes/api/v2/__init__.py +47 -47
- fractal_server/app/routes/api/v2/_aux_functions.py +65 -64
- fractal_server/app/routes/api/v2/_aux_functions_history.py +8 -3
- fractal_server/app/routes/api/v2/_aux_functions_sharing.py +97 -0
- fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +4 -4
- fractal_server/app/routes/api/v2/_aux_functions_tasks.py +2 -2
- fractal_server/app/routes/api/v2/dataset.py +89 -77
- fractal_server/app/routes/api/v2/history.py +28 -16
- fractal_server/app/routes/api/v2/images.py +22 -8
- fractal_server/app/routes/api/v2/job.py +40 -24
- fractal_server/app/routes/api/v2/pre_submission_checks.py +13 -6
- fractal_server/app/routes/api/v2/project.py +48 -25
- fractal_server/app/routes/api/v2/sharing.py +311 -0
- fractal_server/app/routes/api/v2/status_legacy.py +22 -33
- fractal_server/app/routes/api/v2/submit.py +76 -71
- fractal_server/app/routes/api/v2/task.py +15 -17
- fractal_server/app/routes/api/v2/task_collection.py +18 -18
- fractal_server/app/routes/api/v2/task_collection_custom.py +11 -13
- fractal_server/app/routes/api/v2/task_collection_pixi.py +9 -9
- fractal_server/app/routes/api/v2/task_group.py +18 -18
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +26 -26
- fractal_server/app/routes/api/v2/task_version_update.py +12 -9
- fractal_server/app/routes/api/v2/workflow.py +41 -29
- fractal_server/app/routes/api/v2/workflow_import.py +25 -23
- fractal_server/app/routes/api/v2/workflowtask.py +25 -17
- fractal_server/app/routes/auth/_aux_auth.py +100 -0
- fractal_server/app/routes/auth/current_user.py +0 -63
- fractal_server/app/routes/auth/group.py +1 -30
- fractal_server/app/routes/auth/router.py +2 -0
- fractal_server/app/routes/auth/users.py +9 -0
- fractal_server/app/routes/auth/viewer_paths.py +43 -0
- fractal_server/app/schemas/user.py +29 -12
- fractal_server/app/schemas/user_group.py +0 -15
- fractal_server/app/schemas/v2/__init__.py +55 -48
- fractal_server/app/schemas/v2/dataset.py +35 -13
- fractal_server/app/schemas/v2/dumps.py +9 -9
- fractal_server/app/schemas/v2/job.py +11 -11
- fractal_server/app/schemas/v2/project.py +3 -3
- fractal_server/app/schemas/v2/resource.py +13 -4
- fractal_server/app/schemas/v2/sharing.py +99 -0
- fractal_server/app/schemas/v2/status_legacy.py +3 -3
- fractal_server/app/schemas/v2/task.py +6 -6
- fractal_server/app/schemas/v2/task_collection.py +4 -4
- fractal_server/app/schemas/v2/task_group.py +16 -16
- fractal_server/app/schemas/v2/workflow.py +16 -16
- fractal_server/app/schemas/v2/workflowtask.py +14 -14
- fractal_server/app/security/__init__.py +1 -1
- fractal_server/app/shutdown.py +6 -6
- fractal_server/config/__init__.py +0 -6
- fractal_server/config/_data.py +0 -79
- fractal_server/config/_main.py +6 -1
- fractal_server/data_migrations/2_18_0.py +30 -0
- fractal_server/images/models.py +1 -2
- fractal_server/main.py +72 -11
- fractal_server/migrations/versions/7910eed4cf97_user_project_dirs_and_usergroup_viewer_.py +60 -0
- fractal_server/migrations/versions/88270f589c9b_add_prevent_new_submissions.py +39 -0
- fractal_server/migrations/versions/bc0e8b3327a7_project_sharing.py +72 -0
- fractal_server/migrations/versions/f0702066b007_one_submitted_job_per_dataset.py +40 -0
- fractal_server/runner/config/_slurm.py +2 -0
- fractal_server/runner/executors/slurm_common/_batching.py +4 -10
- fractal_server/runner/executors/slurm_common/slurm_config.py +1 -0
- fractal_server/runner/executors/slurm_ssh/runner.py +1 -1
- fractal_server/runner/executors/slurm_sudo/runner.py +1 -1
- fractal_server/runner/v2/_local.py +4 -3
- fractal_server/runner/v2/_slurm_ssh.py +4 -3
- fractal_server/runner/v2/_slurm_sudo.py +4 -3
- fractal_server/runner/v2/runner.py +36 -17
- fractal_server/runner/v2/runner_functions.py +11 -14
- fractal_server/runner/v2/submit_workflow.py +22 -9
- fractal_server/tasks/v2/local/_utils.py +2 -2
- fractal_server/tasks/v2/local/collect.py +5 -6
- fractal_server/tasks/v2/local/collect_pixi.py +5 -6
- fractal_server/tasks/v2/local/deactivate.py +7 -7
- fractal_server/tasks/v2/local/deactivate_pixi.py +3 -3
- fractal_server/tasks/v2/local/delete.py +5 -5
- fractal_server/tasks/v2/local/reactivate.py +5 -5
- fractal_server/tasks/v2/local/reactivate_pixi.py +5 -5
- fractal_server/tasks/v2/ssh/collect.py +5 -5
- fractal_server/tasks/v2/ssh/collect_pixi.py +5 -5
- fractal_server/tasks/v2/ssh/deactivate.py +7 -7
- fractal_server/tasks/v2/ssh/deactivate_pixi.py +2 -2
- fractal_server/tasks/v2/ssh/delete.py +5 -5
- fractal_server/tasks/v2/ssh/reactivate.py +5 -5
- fractal_server/tasks/v2/ssh/reactivate_pixi.py +5 -5
- fractal_server/tasks/v2/utils_background.py +7 -7
- fractal_server/tasks/v2/utils_database.py +5 -5
- fractal_server/types/__init__.py +22 -0
- fractal_server/types/validators/__init__.py +3 -0
- fractal_server/types/validators/_common_validators.py +32 -0
- {fractal_server-2.17.2.dist-info → fractal_server-2.18.0.dist-info}/METADATA +3 -2
- {fractal_server-2.17.2.dist-info → fractal_server-2.18.0.dist-info}/RECORD +108 -98
- {fractal_server-2.17.2.dist-info → fractal_server-2.18.0.dist-info}/WHEEL +0 -0
- {fractal_server-2.17.2.dist-info → fractal_server-2.18.0.dist-info}/entry_points.txt +0 -0
- {fractal_server-2.17.2.dist-info → fractal_server-2.18.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -8,12 +8,18 @@ from pydantic import EmailStr
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
|
|
10
10
|
from fractal_server.string_tools import validate_cmd
|
|
11
|
-
from fractal_server.types import
|
|
11
|
+
from fractal_server.types import ListUniqueAbsolutePathStr
|
|
12
12
|
from fractal_server.types import ListUniqueNonEmptyString
|
|
13
13
|
from fractal_server.types import ListUniqueNonNegativeInt
|
|
14
14
|
from fractal_server.types import NonEmptyStr
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def _validate_cmd_list(value: list[str]) -> list[str]:
|
|
18
|
+
for v in value:
|
|
19
|
+
validate_cmd(v)
|
|
20
|
+
return value
|
|
21
|
+
|
|
22
|
+
|
|
17
23
|
class OAuthAccountRead(BaseModel):
|
|
18
24
|
"""
|
|
19
25
|
Schema for storing essential `OAuthAccount` information within
|
|
@@ -38,20 +44,17 @@ class UserRead(schemas.BaseUser[int]):
|
|
|
38
44
|
group_ids_names:
|
|
39
45
|
oauth_accounts:
|
|
40
46
|
profile_id:
|
|
47
|
+
project_dirs:
|
|
48
|
+
slurm_accounts:
|
|
41
49
|
"""
|
|
42
50
|
|
|
43
51
|
group_ids_names: list[tuple[int, str]] | None = None
|
|
44
52
|
oauth_accounts: list[OAuthAccountRead]
|
|
45
53
|
profile_id: int | None = None
|
|
46
|
-
|
|
54
|
+
project_dirs: list[str]
|
|
47
55
|
slurm_accounts: list[str]
|
|
48
56
|
|
|
49
57
|
|
|
50
|
-
def _validate_cmd(value: str) -> str:
|
|
51
|
-
validate_cmd(value)
|
|
52
|
-
return value
|
|
53
|
-
|
|
54
|
-
|
|
55
58
|
class UserUpdate(schemas.BaseUserUpdate):
|
|
56
59
|
"""
|
|
57
60
|
Schema for `User` update.
|
|
@@ -63,7 +66,7 @@ class UserUpdate(schemas.BaseUserUpdate):
|
|
|
63
66
|
is_superuser:
|
|
64
67
|
is_verified:
|
|
65
68
|
profile_id:
|
|
66
|
-
|
|
69
|
+
project_dirs:
|
|
67
70
|
slurm_accounts:
|
|
68
71
|
"""
|
|
69
72
|
|
|
@@ -74,9 +77,9 @@ class UserUpdate(schemas.BaseUserUpdate):
|
|
|
74
77
|
is_superuser: bool = None
|
|
75
78
|
is_verified: bool = None
|
|
76
79
|
profile_id: int | None = None
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
)
|
|
80
|
+
project_dirs: Annotated[
|
|
81
|
+
ListUniqueAbsolutePathStr, AfterValidator(_validate_cmd_list)
|
|
82
|
+
] = Field(default=None, min_length=1)
|
|
80
83
|
slurm_accounts: ListUniqueNonEmptyString = None
|
|
81
84
|
|
|
82
85
|
|
|
@@ -98,10 +101,14 @@ class UserCreate(schemas.BaseUserCreate):
|
|
|
98
101
|
|
|
99
102
|
Attributes:
|
|
100
103
|
profile_id:
|
|
104
|
+
project_dirs:
|
|
105
|
+
slurm_accounts:
|
|
101
106
|
"""
|
|
102
107
|
|
|
103
108
|
profile_id: int | None = None
|
|
104
|
-
|
|
109
|
+
project_dirs: Annotated[
|
|
110
|
+
ListUniqueAbsolutePathStr, AfterValidator(_validate_cmd_list)
|
|
111
|
+
] = Field(min_length=1)
|
|
105
112
|
slurm_accounts: list[str] = Field(default_factory=list)
|
|
106
113
|
|
|
107
114
|
|
|
@@ -109,6 +116,8 @@ class UserUpdateGroups(BaseModel):
|
|
|
109
116
|
"""
|
|
110
117
|
Schema for `POST /auth/users/{user_id}/set-groups/`
|
|
111
118
|
|
|
119
|
+
Attributes:
|
|
120
|
+
group_ids:
|
|
112
121
|
"""
|
|
113
122
|
|
|
114
123
|
model_config = ConfigDict(extra="forbid")
|
|
@@ -117,6 +126,14 @@ class UserUpdateGroups(BaseModel):
|
|
|
117
126
|
|
|
118
127
|
|
|
119
128
|
class UserProfileInfo(BaseModel):
|
|
129
|
+
"""
|
|
130
|
+
Attributes:
|
|
131
|
+
has_profile:
|
|
132
|
+
resource_name:
|
|
133
|
+
profile_name:
|
|
134
|
+
username:
|
|
135
|
+
"""
|
|
136
|
+
|
|
120
137
|
has_profile: bool
|
|
121
138
|
resource_name: str | None = None
|
|
122
139
|
profile_name: str | None = None
|
|
@@ -2,16 +2,13 @@ from datetime import datetime
|
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel
|
|
4
4
|
from pydantic import ConfigDict
|
|
5
|
-
from pydantic import Field
|
|
6
5
|
from pydantic import field_serializer
|
|
7
6
|
from pydantic.types import AwareDatetime
|
|
8
7
|
|
|
9
|
-
from fractal_server.types import ListUniqueAbsolutePathStr
|
|
10
8
|
from fractal_server.types import NonEmptyStr
|
|
11
9
|
|
|
12
10
|
__all__ = (
|
|
13
11
|
"UserGroupRead",
|
|
14
|
-
"UserGroupUpdate",
|
|
15
12
|
"UserGroupCreate",
|
|
16
13
|
)
|
|
17
14
|
|
|
@@ -34,7 +31,6 @@ class UserGroupRead(BaseModel):
|
|
|
34
31
|
name: str
|
|
35
32
|
timestamp_created: AwareDatetime
|
|
36
33
|
user_ids: list[int] | None = None
|
|
37
|
-
viewer_paths: list[str]
|
|
38
34
|
|
|
39
35
|
@field_serializer("timestamp_created")
|
|
40
36
|
def serialize_datetime(v: datetime) -> str:
|
|
@@ -52,14 +48,3 @@ class UserGroupCreate(BaseModel):
|
|
|
52
48
|
model_config = ConfigDict(extra="forbid")
|
|
53
49
|
|
|
54
50
|
name: NonEmptyStr
|
|
55
|
-
viewer_paths: ListUniqueAbsolutePathStr = Field(default_factory=list)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class UserGroupUpdate(BaseModel):
|
|
59
|
-
"""
|
|
60
|
-
Schema for `UserGroup` update
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
model_config = ConfigDict(extra="forbid")
|
|
64
|
-
|
|
65
|
-
viewer_paths: ListUniqueAbsolutePathStr = None
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
from .accounting import AccountingRecordRead # noqa F401
|
|
2
|
-
from .dataset import
|
|
3
|
-
from .dataset import
|
|
4
|
-
from .dataset import
|
|
5
|
-
from .dataset import
|
|
6
|
-
from .dataset import
|
|
7
|
-
from .dumps import
|
|
8
|
-
from .dumps import
|
|
9
|
-
from .dumps import
|
|
10
|
-
from .dumps import
|
|
11
|
-
from .dumps import
|
|
12
|
-
from .dumps import
|
|
2
|
+
from .dataset import DatasetCreate # noqa F401
|
|
3
|
+
from .dataset import DatasetExport # noqa F401
|
|
4
|
+
from .dataset import DatasetImport # noqa F401
|
|
5
|
+
from .dataset import DatasetRead # noqa F401
|
|
6
|
+
from .dataset import DatasetUpdate # noqa F401
|
|
7
|
+
from .dumps import DatasetDump # noqa F401
|
|
8
|
+
from .dumps import ProjectDump # noqa F401
|
|
9
|
+
from .dumps import TaskDump # noqa F401
|
|
10
|
+
from .dumps import TaskGroupDump # noqa F401
|
|
11
|
+
from .dumps import WorkflowDump # noqa F401
|
|
12
|
+
from .dumps import WorkflowTaskDump # noqa F401
|
|
13
13
|
from .history import HistoryRunRead # noqa F401
|
|
14
14
|
from .history import HistoryRunReadAggregated # noqa F401
|
|
15
15
|
from .history import HistoryUnitRead # noqa F401
|
|
16
16
|
from .history import HistoryUnitStatus # noqa F401
|
|
17
17
|
from .history import HistoryUnitStatusWithUnset # noqa F401
|
|
18
18
|
from .history import ImageLogsRequest # noqa F401
|
|
19
|
-
from .job import
|
|
20
|
-
from .job import
|
|
21
|
-
from .job import
|
|
22
|
-
from .job import
|
|
19
|
+
from .job import JobCreate # noqa F401
|
|
20
|
+
from .job import JobRead # noqa F401
|
|
21
|
+
from .job import JobStatusType # noqa F401
|
|
22
|
+
from .job import JobUpdate # noqa F401
|
|
23
23
|
from .manifest import ManifestV2 # noqa F401
|
|
24
24
|
from .manifest import TaskManifestV2 # noqa F401
|
|
25
25
|
from .profile import ProfileCreate # noqa F401
|
|
@@ -27,45 +27,52 @@ from .profile import ProfileRead # noqa F401
|
|
|
27
27
|
from .profile import ValidProfileLocal # noqa F401
|
|
28
28
|
from .profile import ValidProfileSlurmSSH # noqa F401
|
|
29
29
|
from .profile import ValidProfileSlurmSudo # noqa F401
|
|
30
|
-
from .project import
|
|
31
|
-
from .project import
|
|
32
|
-
from .project import
|
|
30
|
+
from .project import ProjectCreate # noqa F401
|
|
31
|
+
from .project import ProjectRead # noqa F401
|
|
32
|
+
from .project import ProjectUpdate # noqa F401
|
|
33
|
+
from .sharing import ProjectPermissions # noqa F401
|
|
34
|
+
from .sharing import ProjectGuestCreate # noqa F401
|
|
35
|
+
from .sharing import ProjectAccessRead # noqa F401
|
|
36
|
+
from .sharing import ProjectInvitationRead # noqa F401
|
|
37
|
+
from .sharing import ProjectGuestRead # noqa F401
|
|
38
|
+
from .sharing import ProjectGuestUpdate # noqa F401
|
|
39
|
+
from .sharing import LinkUserProjectRead # noqa F401
|
|
33
40
|
from .resource import ResourceCreate # noqa F401
|
|
34
41
|
from .resource import ResourceRead # noqa F401
|
|
35
42
|
from .resource import ResourceType # noqa F401
|
|
36
43
|
from .resource import ValidResourceLocal # noqa F401
|
|
37
44
|
from .resource import ValidResourceSlurmSSH # noqa F401
|
|
38
45
|
from .resource import ValidResourceSlurmSudo # noqa F401
|
|
39
|
-
from .status_legacy import
|
|
40
|
-
from .task import
|
|
41
|
-
from .task import
|
|
42
|
-
from .task import
|
|
43
|
-
from .task import
|
|
44
|
-
from .task import
|
|
46
|
+
from .status_legacy import WorkflowTaskStatusType # noqa F401
|
|
47
|
+
from .task import TaskCreate # noqa F401
|
|
48
|
+
from .task import TaskExport # noqa F401
|
|
49
|
+
from .task import TaskImport # noqa F401
|
|
50
|
+
from .task import TaskImportLegacy # noqa F401
|
|
51
|
+
from .task import TaskRead # noqa F401
|
|
45
52
|
from .task import TaskType # noqa F401
|
|
46
|
-
from .task import
|
|
53
|
+
from .task import TaskUpdate # noqa F401
|
|
47
54
|
from .task_collection import FractalUploadedFile # noqa F401
|
|
48
|
-
from .task_collection import
|
|
49
|
-
from .task_collection import
|
|
50
|
-
from .task_group import
|
|
51
|
-
from .task_group import
|
|
52
|
-
from .task_group import
|
|
53
|
-
from .task_group import
|
|
54
|
-
from .task_group import
|
|
55
|
+
from .task_collection import TaskCollectCustom # noqa F401
|
|
56
|
+
from .task_collection import TaskCollectPip # noqa F401
|
|
57
|
+
from .task_group import TaskGroupActivityAction # noqa F401
|
|
58
|
+
from .task_group import TaskGroupActivityStatus # noqa F401
|
|
59
|
+
from .task_group import TaskGroupActivityRead # noqa F401
|
|
60
|
+
from .task_group import TaskGroupCreate # noqa F401
|
|
61
|
+
from .task_group import TaskGroupCreateStrict # noqa F401
|
|
55
62
|
from .task_group import TaskGroupReadSuperuser # noqa F401
|
|
56
|
-
from .task_group import
|
|
57
|
-
from .task_group import
|
|
58
|
-
from .task_group import
|
|
59
|
-
from .workflow import
|
|
60
|
-
from .workflow import
|
|
61
|
-
from .workflow import
|
|
62
|
-
from .workflow import
|
|
63
|
-
from .workflow import
|
|
64
|
-
from .workflow import
|
|
65
|
-
from .workflowtask import
|
|
66
|
-
from .workflowtask import
|
|
67
|
-
from .workflowtask import
|
|
68
|
-
from .workflowtask import
|
|
69
|
-
from .workflowtask import
|
|
70
|
-
from .workflowtask import
|
|
71
|
-
from .workflowtask import
|
|
63
|
+
from .task_group import TaskGroupRead # noqa F401
|
|
64
|
+
from .task_group import TaskGroupUpdate # noqa F401
|
|
65
|
+
from .task_group import TaskGroupOriginEnum # noqa F401
|
|
66
|
+
from .workflow import WorkflowCreate # noqa F401
|
|
67
|
+
from .workflow import WorkflowExport # noqa F401
|
|
68
|
+
from .workflow import WorkflowImport # noqa F401
|
|
69
|
+
from .workflow import WorkflowRead # noqa F401
|
|
70
|
+
from .workflow import WorkflowReadWithWarnings # noqa F401
|
|
71
|
+
from .workflow import WorkflowUpdate # noqa F401
|
|
72
|
+
from .workflowtask import WorkflowTaskCreate # noqa F401
|
|
73
|
+
from .workflowtask import WorkflowTaskExport # noqa F401
|
|
74
|
+
from .workflowtask import WorkflowTaskImport # noqa F401
|
|
75
|
+
from .workflowtask import WorkflowTaskRead # noqa F401
|
|
76
|
+
from .workflowtask import WorkflowTaskReadWithWarning # noqa F401
|
|
77
|
+
from .workflowtask import WorkflowTaskReplace # noqa F401
|
|
78
|
+
from .workflowtask import WorkflowTaskUpdate # noqa F401
|
|
@@ -1,35 +1,49 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
from pydantic import BaseModel
|
|
4
5
|
from pydantic import ConfigDict
|
|
5
6
|
from pydantic import Field
|
|
6
7
|
from pydantic import field_serializer
|
|
8
|
+
from pydantic import model_validator
|
|
7
9
|
from pydantic.types import AwareDatetime
|
|
8
10
|
|
|
9
|
-
from fractal_server.app.schemas.v2.project import
|
|
11
|
+
from fractal_server.app.schemas.v2.project import ProjectRead
|
|
10
12
|
from fractal_server.images import SingleImage
|
|
13
|
+
from fractal_server.types import AbsolutePathStr
|
|
11
14
|
from fractal_server.types import NonEmptyStr
|
|
15
|
+
from fractal_server.types import RelativePathStr
|
|
12
16
|
from fractal_server.types import ZarrDirStr
|
|
13
17
|
|
|
14
18
|
|
|
15
|
-
class
|
|
19
|
+
class DatasetCreate(BaseModel):
|
|
16
20
|
"""
|
|
17
|
-
|
|
21
|
+
DatasetCreate
|
|
18
22
|
|
|
19
23
|
Attributes:
|
|
20
24
|
name:
|
|
21
|
-
|
|
25
|
+
project_dir:
|
|
26
|
+
zarr_subfolder:
|
|
22
27
|
"""
|
|
23
28
|
|
|
24
29
|
model_config = ConfigDict(extra="forbid")
|
|
25
30
|
|
|
26
31
|
name: NonEmptyStr
|
|
27
|
-
|
|
32
|
+
project_dir: AbsolutePathStr | None = None
|
|
33
|
+
zarr_subfolder: RelativePathStr | None = None
|
|
34
|
+
|
|
35
|
+
@model_validator(mode="after")
|
|
36
|
+
def validate_zarr_dir(self):
|
|
37
|
+
if (self.project_dir is None) and (self.zarr_subfolder is not None):
|
|
38
|
+
raise ValueError(
|
|
39
|
+
"Cannot provide `zarr_subfolder` without `project_dir`"
|
|
40
|
+
)
|
|
41
|
+
return self
|
|
28
42
|
|
|
29
43
|
|
|
30
|
-
class
|
|
44
|
+
class DatasetRead(BaseModel):
|
|
31
45
|
"""
|
|
32
|
-
|
|
46
|
+
DatasetRead
|
|
33
47
|
|
|
34
48
|
Attributes:
|
|
35
49
|
id:
|
|
@@ -44,7 +58,7 @@ class DatasetReadV2(BaseModel):
|
|
|
44
58
|
name: str
|
|
45
59
|
|
|
46
60
|
project_id: int
|
|
47
|
-
project:
|
|
61
|
+
project: ProjectRead
|
|
48
62
|
|
|
49
63
|
timestamp_created: AwareDatetime
|
|
50
64
|
|
|
@@ -55,9 +69,9 @@ class DatasetReadV2(BaseModel):
|
|
|
55
69
|
return v.isoformat()
|
|
56
70
|
|
|
57
71
|
|
|
58
|
-
class
|
|
72
|
+
class DatasetUpdate(BaseModel):
|
|
59
73
|
"""
|
|
60
|
-
|
|
74
|
+
DatasetUpdate
|
|
61
75
|
|
|
62
76
|
Attributes:
|
|
63
77
|
name:
|
|
@@ -67,10 +81,9 @@ class DatasetUpdateV2(BaseModel):
|
|
|
67
81
|
model_config = ConfigDict(extra="forbid")
|
|
68
82
|
|
|
69
83
|
name: NonEmptyStr = None
|
|
70
|
-
zarr_dir: ZarrDirStr | None = None
|
|
71
84
|
|
|
72
85
|
|
|
73
|
-
class
|
|
86
|
+
class DatasetImport(BaseModel):
|
|
74
87
|
"""
|
|
75
88
|
Class for `Dataset` import.
|
|
76
89
|
|
|
@@ -88,8 +101,17 @@ class DatasetImportV2(BaseModel):
|
|
|
88
101
|
zarr_dir: ZarrDirStr
|
|
89
102
|
images: list[SingleImage] = Field(default_factory=list)
|
|
90
103
|
|
|
104
|
+
@model_validator(mode="after")
|
|
105
|
+
def validate_image_zarr_url(self):
|
|
106
|
+
for image in self.images:
|
|
107
|
+
if not Path(image.zarr_url).is_relative_to(self.zarr_dir):
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"{image.zarr_url=} is not relative to {self.zarr_dir=}."
|
|
110
|
+
)
|
|
111
|
+
return self
|
|
112
|
+
|
|
91
113
|
|
|
92
|
-
class
|
|
114
|
+
class DatasetExport(BaseModel):
|
|
93
115
|
"""
|
|
94
116
|
Class for `Dataset` export.
|
|
95
117
|
|
|
@@ -13,17 +13,17 @@ from pydantic import ConfigDict
|
|
|
13
13
|
from pydantic import Field
|
|
14
14
|
|
|
15
15
|
from .task import TaskType
|
|
16
|
-
from .task_group import
|
|
16
|
+
from .task_group import TaskGroupOriginEnum
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class
|
|
19
|
+
class ProjectDump(BaseModel):
|
|
20
20
|
model_config = ConfigDict(extra="forbid")
|
|
21
21
|
id: int
|
|
22
22
|
name: str
|
|
23
23
|
timestamp_created: str
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
class
|
|
26
|
+
class TaskDump(BaseModel):
|
|
27
27
|
id: int
|
|
28
28
|
name: str
|
|
29
29
|
type: TaskType
|
|
@@ -37,7 +37,7 @@ class TaskDumpV2(BaseModel):
|
|
|
37
37
|
output_types: dict[str, bool]
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
class
|
|
40
|
+
class WorkflowTaskDump(BaseModel):
|
|
41
41
|
"""
|
|
42
42
|
We do not include 'model_config = ConfigDict(extra="forbid")'
|
|
43
43
|
because legacy data may include 'input_filters' field and we want to avoid
|
|
@@ -51,10 +51,10 @@ class WorkflowTaskDumpV2(BaseModel):
|
|
|
51
51
|
type_filters: dict[str, bool]
|
|
52
52
|
|
|
53
53
|
task_id: int | None = None
|
|
54
|
-
task:
|
|
54
|
+
task: TaskDump | None = None
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
class
|
|
57
|
+
class WorkflowDump(BaseModel):
|
|
58
58
|
model_config = ConfigDict(extra="forbid")
|
|
59
59
|
id: int
|
|
60
60
|
name: str
|
|
@@ -62,7 +62,7 @@ class WorkflowDumpV2(BaseModel):
|
|
|
62
62
|
timestamp_created: str
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
class
|
|
65
|
+
class DatasetDump(BaseModel):
|
|
66
66
|
"""
|
|
67
67
|
We do not include 'model_config = ConfigDict(extra="forbid")' because
|
|
68
68
|
legacy data may include 'type_filters' or 'attribute_filters' and we
|
|
@@ -76,9 +76,9 @@ class DatasetDumpV2(BaseModel):
|
|
|
76
76
|
zarr_dir: str
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
class
|
|
79
|
+
class TaskGroupDump(BaseModel):
|
|
80
80
|
id: int
|
|
81
|
-
origin:
|
|
81
|
+
origin: TaskGroupOriginEnum
|
|
82
82
|
pkg_name: str
|
|
83
83
|
version: str | None = None
|
|
84
84
|
python_version: str | None = None
|
|
@@ -10,15 +10,15 @@ from pydantic.types import AwareDatetime
|
|
|
10
10
|
from pydantic.types import NonNegativeInt
|
|
11
11
|
from pydantic.types import StrictStr
|
|
12
12
|
|
|
13
|
-
from fractal_server.app.schemas.v2.dumps import
|
|
14
|
-
from fractal_server.app.schemas.v2.dumps import
|
|
15
|
-
from fractal_server.app.schemas.v2.dumps import
|
|
13
|
+
from fractal_server.app.schemas.v2.dumps import DatasetDump
|
|
14
|
+
from fractal_server.app.schemas.v2.dumps import ProjectDump
|
|
15
|
+
from fractal_server.app.schemas.v2.dumps import WorkflowDump
|
|
16
16
|
from fractal_server.types import AttributeFilters
|
|
17
17
|
from fractal_server.types import NonEmptyStr
|
|
18
18
|
from fractal_server.types import TypeFilters
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class
|
|
21
|
+
class JobStatusType(StrEnum):
|
|
22
22
|
"""
|
|
23
23
|
Define the available job statuses
|
|
24
24
|
|
|
@@ -39,7 +39,7 @@ class JobStatusTypeV2(StrEnum):
|
|
|
39
39
|
FAILED = "failed"
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
class
|
|
42
|
+
class JobCreate(BaseModel):
|
|
43
43
|
model_config = ConfigDict(extra="forbid")
|
|
44
44
|
|
|
45
45
|
first_task_index: NonNegativeInt | None = None
|
|
@@ -65,16 +65,16 @@ class JobCreateV2(BaseModel):
|
|
|
65
65
|
return values
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
class
|
|
68
|
+
class JobRead(BaseModel):
|
|
69
69
|
id: int
|
|
70
70
|
project_id: int | None = None
|
|
71
|
-
project_dump:
|
|
71
|
+
project_dump: ProjectDump
|
|
72
72
|
user_email: str
|
|
73
73
|
slurm_account: str | None = None
|
|
74
74
|
workflow_id: int | None = None
|
|
75
|
-
workflow_dump:
|
|
75
|
+
workflow_dump: WorkflowDump
|
|
76
76
|
dataset_id: int | None = None
|
|
77
|
-
dataset_dump:
|
|
77
|
+
dataset_dump: DatasetDump
|
|
78
78
|
start_timestamp: AwareDatetime
|
|
79
79
|
end_timestamp: AwareDatetime | None = None
|
|
80
80
|
status: str
|
|
@@ -100,7 +100,7 @@ class JobReadV2(BaseModel):
|
|
|
100
100
|
return v.isoformat()
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
class
|
|
103
|
+
class JobUpdate(BaseModel):
|
|
104
104
|
model_config = ConfigDict(extra="forbid")
|
|
105
105
|
|
|
106
|
-
status:
|
|
106
|
+
status: JobStatusType
|
|
@@ -8,13 +8,13 @@ from pydantic.types import AwareDatetime
|
|
|
8
8
|
from fractal_server.types import NonEmptyStr
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class
|
|
11
|
+
class ProjectCreate(BaseModel):
|
|
12
12
|
model_config = ConfigDict(extra="forbid")
|
|
13
13
|
|
|
14
14
|
name: NonEmptyStr
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class
|
|
17
|
+
class ProjectRead(BaseModel):
|
|
18
18
|
id: int
|
|
19
19
|
name: str
|
|
20
20
|
timestamp_created: AwareDatetime
|
|
@@ -24,7 +24,7 @@ class ProjectReadV2(BaseModel):
|
|
|
24
24
|
return v.isoformat()
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
class
|
|
27
|
+
class ProjectUpdate(BaseModel):
|
|
28
28
|
model_config = ConfigDict(extra="forbid")
|
|
29
29
|
|
|
30
30
|
name: NonEmptyStr = None
|
|
@@ -77,6 +77,8 @@ class ValidResourceBase(BaseModel):
|
|
|
77
77
|
jobs_runner_config: dict[NonEmptyStr, Any]
|
|
78
78
|
jobs_poll_interval: int = 5
|
|
79
79
|
|
|
80
|
+
prevent_new_submissions: bool = False
|
|
81
|
+
|
|
80
82
|
@model_validator(mode="after")
|
|
81
83
|
def _pixi_slurm_config(self) -> Self:
|
|
82
84
|
if (
|
|
@@ -95,6 +97,9 @@ class ValidResourceLocal(ValidResourceBase):
|
|
|
95
97
|
Attributes:
|
|
96
98
|
name: Resource name.
|
|
97
99
|
type: Resource type.
|
|
100
|
+
prevent_new_submissions:
|
|
101
|
+
When set to true: Prevent new job submissions and stop execution of
|
|
102
|
+
ongoing jobs as soon as the current task is complete.
|
|
98
103
|
tasks_python_config:
|
|
99
104
|
Configuration of Python interpreters used for task collection.
|
|
100
105
|
tasks_pixi_config:
|
|
@@ -105,7 +110,6 @@ class ValidResourceLocal(ValidResourceBase):
|
|
|
105
110
|
Local base folder for job folders.
|
|
106
111
|
jobs_runner_config:
|
|
107
112
|
Runner configuration.
|
|
108
|
-
|
|
109
113
|
"""
|
|
110
114
|
|
|
111
115
|
type: Literal[ResourceType.LOCAL]
|
|
@@ -121,6 +125,9 @@ class ValidResourceSlurmSudo(ValidResourceBase):
|
|
|
121
125
|
Attributes:
|
|
122
126
|
name: Resource name.
|
|
123
127
|
type: Resource type.
|
|
128
|
+
prevent_new_submissions:
|
|
129
|
+
When set to true: Prevent new job submissions and stop execution of
|
|
130
|
+
ongoing jobs as soon as the current task is complete.
|
|
124
131
|
tasks_python_config:
|
|
125
132
|
Configuration of Python interpreters used for task collection.
|
|
126
133
|
tasks_pixi_config:
|
|
@@ -150,6 +157,9 @@ class ValidResourceSlurmSSH(ValidResourceBase):
|
|
|
150
157
|
Attributes:
|
|
151
158
|
name: Resource name
|
|
152
159
|
type: Resource type.
|
|
160
|
+
prevent_new_submissions:
|
|
161
|
+
When set to true: Prevent new job submissions and stop execution of
|
|
162
|
+
ongoing jobs as soon as the current task is complete.
|
|
153
163
|
tasks_python_config:
|
|
154
164
|
Configuration of Python interpreters used for task collection.
|
|
155
165
|
tasks_pixi_config:
|
|
@@ -198,10 +208,9 @@ class ResourceRead(BaseModel):
|
|
|
198
208
|
"""
|
|
199
209
|
|
|
200
210
|
id: int
|
|
201
|
-
|
|
202
|
-
type: str
|
|
203
|
-
|
|
204
211
|
name: str
|
|
212
|
+
type: str
|
|
213
|
+
prevent_new_submissions: bool
|
|
205
214
|
timestamp_created: AwareDatetime
|
|
206
215
|
|
|
207
216
|
host: str | None
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ProjectPermissions(StrEnum):
|
|
7
|
+
"""
|
|
8
|
+
Available permissions for accessing Project
|
|
9
|
+
Attributes:
|
|
10
|
+
READ:
|
|
11
|
+
WRITE:
|
|
12
|
+
EXECUTE:
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
READ = "r"
|
|
16
|
+
WRITE = "rw"
|
|
17
|
+
EXECUTE = "rwx"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ProjectGuestCreate(BaseModel):
|
|
21
|
+
"""
|
|
22
|
+
Request body for project-sharing invitation.
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
permissions:
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
permissions: ProjectPermissions
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ProjectGuestRead(BaseModel):
|
|
32
|
+
"""
|
|
33
|
+
Information about a guest.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
email: Guest email.
|
|
37
|
+
is_verified: Project/guest verification status.
|
|
38
|
+
permissions: Guest permissions for project.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
email: str
|
|
42
|
+
is_verified: bool
|
|
43
|
+
permissions: str
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ProjectGuestUpdate(BaseModel):
|
|
47
|
+
"""
|
|
48
|
+
Request body for updating permissions of an existing guest.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
permissions: New permissions for guest.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
permissions: ProjectPermissions
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ProjectAccessRead(BaseModel):
|
|
58
|
+
"""
|
|
59
|
+
Project-access information for current user.
|
|
60
|
+
|
|
61
|
+
Attributes:
|
|
62
|
+
is_owner: Whether current user is owner.
|
|
63
|
+
permissions: Current user permissions.
|
|
64
|
+
owner_email: Email of project owner
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
is_owner: bool
|
|
68
|
+
permissions: str
|
|
69
|
+
owner_email: str
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ProjectInvitationRead(BaseModel):
|
|
73
|
+
"""
|
|
74
|
+
Info about a pending invitation.
|
|
75
|
+
|
|
76
|
+
Attributes:
|
|
77
|
+
project_id:
|
|
78
|
+
project_name:
|
|
79
|
+
owner_email:
|
|
80
|
+
guest_permissions:
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
project_id: int
|
|
84
|
+
project_name: str
|
|
85
|
+
owner_email: str
|
|
86
|
+
guest_permissions: str
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class LinkUserProjectRead(BaseModel):
|
|
90
|
+
# User info
|
|
91
|
+
user_id: int
|
|
92
|
+
user_email: str
|
|
93
|
+
# Project info
|
|
94
|
+
project_id: int
|
|
95
|
+
project_name: str
|
|
96
|
+
# Permissions
|
|
97
|
+
is_verified: bool
|
|
98
|
+
is_owner: bool
|
|
99
|
+
permissions: str
|