fractal-server 2.12.1__py3-none-any.whl → 2.13.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/app/models/security.py +9 -12
- fractal_server/app/models/v2/dataset.py +2 -2
- fractal_server/app/models/v2/job.py +11 -9
- fractal_server/app/models/v2/task.py +2 -3
- fractal_server/app/models/v2/task_group.py +6 -2
- fractal_server/app/models/v2/workflowtask.py +15 -8
- fractal_server/app/routes/admin/v2/task.py +1 -1
- fractal_server/app/routes/admin/v2/task_group.py +1 -1
- fractal_server/app/routes/api/v2/dataset.py +4 -4
- fractal_server/app/routes/api/v2/images.py +11 -11
- fractal_server/app/routes/api/v2/project.py +2 -2
- fractal_server/app/routes/api/v2/status.py +1 -1
- fractal_server/app/routes/api/v2/submit.py +8 -6
- fractal_server/app/routes/api/v2/task.py +4 -2
- fractal_server/app/routes/api/v2/task_collection.py +3 -2
- fractal_server/app/routes/api/v2/task_group.py +2 -2
- fractal_server/app/routes/api/v2/workflow.py +3 -3
- fractal_server/app/routes/api/v2/workflow_import.py +3 -3
- fractal_server/app/routes/api/v2/workflowtask.py +3 -1
- fractal_server/app/routes/auth/_aux_auth.py +4 -1
- fractal_server/app/routes/auth/current_user.py +3 -5
- fractal_server/app/routes/auth/group.py +1 -1
- fractal_server/app/routes/auth/users.py +2 -4
- fractal_server/app/routes/aux/_runner.py +1 -1
- fractal_server/app/routes/aux/validate_user_settings.py +1 -2
- fractal_server/app/runner/executors/_job_states.py +13 -0
- fractal_server/app/runner/executors/slurm/_slurm_config.py +26 -18
- fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -3
- fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +31 -22
- fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +2 -5
- fractal_server/app/runner/executors/slurm/ssh/executor.py +21 -27
- fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -3
- fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +1 -2
- fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +37 -47
- fractal_server/app/runner/executors/slurm/sudo/executor.py +25 -24
- fractal_server/app/runner/v2/__init__.py +0 -9
- fractal_server/app/runner/v2/_local/_local_config.py +5 -4
- fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +4 -4
- fractal_server/app/runner/v2/_slurm_sudo/__init__.py +2 -2
- fractal_server/app/runner/v2/deduplicate_list.py +1 -1
- fractal_server/app/runner/v2/runner.py +9 -4
- fractal_server/app/runner/v2/task_interface.py +15 -7
- fractal_server/app/schemas/_filter_validators.py +6 -3
- fractal_server/app/schemas/_validators.py +7 -5
- fractal_server/app/schemas/user.py +23 -18
- fractal_server/app/schemas/user_group.py +25 -11
- fractal_server/app/schemas/user_settings.py +31 -24
- fractal_server/app/schemas/v2/dataset.py +48 -35
- fractal_server/app/schemas/v2/dumps.py +16 -14
- fractal_server/app/schemas/v2/job.py +49 -29
- fractal_server/app/schemas/v2/manifest.py +32 -28
- fractal_server/app/schemas/v2/project.py +18 -8
- fractal_server/app/schemas/v2/task.py +86 -75
- fractal_server/app/schemas/v2/task_collection.py +41 -30
- fractal_server/app/schemas/v2/task_group.py +39 -20
- fractal_server/app/schemas/v2/workflow.py +24 -12
- fractal_server/app/schemas/v2/workflowtask.py +63 -61
- fractal_server/app/security/__init__.py +1 -1
- fractal_server/config.py +32 -25
- fractal_server/images/models.py +18 -12
- fractal_server/main.py +1 -1
- fractal_server/tasks/v2/utils_background.py +1 -1
- fractal_server/tasks/v2/utils_database.py +1 -1
- {fractal_server-2.12.1.dist-info → fractal_server-2.13.0.dist-info}/METADATA +9 -10
- {fractal_server-2.12.1.dist-info → fractal_server-2.13.0.dist-info}/RECORD +69 -72
- fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -121
- fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -108
- fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -42
- fractal_server/app/runner/v2/_local_experimental/executor.py +0 -157
- {fractal_server-2.12.1.dist-info → fractal_server-2.13.0.dist-info}/LICENSE +0 -0
- {fractal_server-2.12.1.dist-info → fractal_server-2.13.0.dist-info}/WHEEL +0 -0
- {fractal_server-2.12.1.dist-info → fractal_server-2.13.0.dist-info}/entry_points.txt +0 -0
@@ -3,9 +3,9 @@ from typing import Literal
|
|
3
3
|
from typing import Optional
|
4
4
|
|
5
5
|
from pydantic import BaseModel
|
6
|
-
from pydantic import
|
7
|
-
from pydantic import
|
8
|
-
from pydantic import
|
6
|
+
from pydantic import ConfigDict
|
7
|
+
from pydantic import field_validator
|
8
|
+
from pydantic import model_validator
|
9
9
|
|
10
10
|
from .._validators import valstr
|
11
11
|
from fractal_server.app.schemas.v2 import ManifestV2
|
@@ -21,7 +21,7 @@ class WheelFile(BaseModel):
|
|
21
21
|
contents: bytes
|
22
22
|
|
23
23
|
|
24
|
-
class TaskCollectPipV2(BaseModel
|
24
|
+
class TaskCollectPipV2(BaseModel):
|
25
25
|
"""
|
26
26
|
TaskCollectPipV2 class
|
27
27
|
|
@@ -45,35 +45,40 @@ class TaskCollectPipV2(BaseModel, extra=Extra.forbid):
|
|
45
45
|
|
46
46
|
"""
|
47
47
|
|
48
|
+
model_config = ConfigDict(extra="forbid")
|
48
49
|
package: Optional[str] = None
|
49
50
|
package_version: Optional[str] = None
|
50
51
|
package_extras: Optional[str] = None
|
51
52
|
python_version: Optional[Literal["3.9", "3.10", "3.11", "3.12"]] = None
|
52
53
|
pinned_package_versions: Optional[dict[str, str]] = None
|
53
54
|
|
54
|
-
@
|
55
|
+
@field_validator("package")
|
56
|
+
@classmethod
|
55
57
|
def package_validator(cls, value: Optional[str]) -> Optional[str]:
|
56
58
|
if value is None:
|
57
59
|
return value
|
58
|
-
value = valstr("package")(value)
|
60
|
+
value = valstr("package")(cls, value)
|
59
61
|
validate_cmd(value, attribute_name="package")
|
60
62
|
return value
|
61
63
|
|
62
|
-
@
|
64
|
+
@field_validator("package_version")
|
65
|
+
@classmethod
|
63
66
|
def package_version_validator(cls, value: Optional[str]) -> Optional[str]:
|
64
67
|
if value is None:
|
65
68
|
return value
|
66
|
-
value = valstr("package_version")(value)
|
69
|
+
value = valstr("package_version")(cls, value)
|
67
70
|
validate_cmd(value, attribute_name="package_version")
|
68
71
|
return value
|
69
72
|
|
70
|
-
@
|
73
|
+
@field_validator("pinned_package_versions")
|
74
|
+
@classmethod
|
71
75
|
def pinned_package_versions_validator(cls, value):
|
72
76
|
if value is None:
|
73
77
|
return value
|
74
78
|
old_keys = list(value.keys())
|
75
79
|
new_keys = [
|
76
|
-
valstr(f"pinned_package_versions[{key}]")(key)
|
80
|
+
valstr(f"pinned_package_versions[{key}]")(cls, key)
|
81
|
+
for key in old_keys
|
77
82
|
]
|
78
83
|
if len(new_keys) != len(set(new_keys)):
|
79
84
|
raise ValueError(
|
@@ -87,16 +92,17 @@ class TaskCollectPipV2(BaseModel, extra=Extra.forbid):
|
|
87
92
|
validate_cmd(version)
|
88
93
|
return value
|
89
94
|
|
90
|
-
@
|
95
|
+
@field_validator("package_extras")
|
96
|
+
@classmethod
|
91
97
|
def package_extras_validator(cls, value: Optional[str]) -> Optional[str]:
|
92
98
|
if value is None:
|
93
99
|
return value
|
94
|
-
value = valstr("package_extras")(value)
|
100
|
+
value = valstr("package_extras")(cls, value)
|
95
101
|
validate_cmd(value, attribute_name="package_extras")
|
96
102
|
return value
|
97
103
|
|
98
104
|
|
99
|
-
class TaskCollectCustomV2(BaseModel
|
105
|
+
class TaskCollectCustomV2(BaseModel):
|
100
106
|
"""
|
101
107
|
Attributes:
|
102
108
|
manifest: Manifest of a Fractal task package (this is typically the
|
@@ -114,29 +120,31 @@ class TaskCollectCustomV2(BaseModel, extra=Extra.forbid):
|
|
114
120
|
version: Optional version of tasks to be collected.
|
115
121
|
"""
|
116
122
|
|
123
|
+
model_config = ConfigDict(extra="forbid")
|
117
124
|
manifest: ManifestV2
|
118
125
|
python_interpreter: str
|
119
126
|
label: str
|
120
|
-
package_root: Optional[str]
|
121
|
-
package_name: Optional[str]
|
122
|
-
version: Optional[str]
|
127
|
+
package_root: Optional[str] = None
|
128
|
+
package_name: Optional[str] = None
|
129
|
+
version: Optional[str] = None
|
123
130
|
|
124
131
|
# Valstr
|
125
|
-
_python_interpreter =
|
126
|
-
valstr("python_interpreter")
|
132
|
+
_python_interpreter = field_validator("python_interpreter")(
|
133
|
+
classmethod(valstr("python_interpreter"))
|
127
134
|
)
|
128
|
-
_label =
|
129
|
-
_package_root =
|
130
|
-
valstr("package_root", accept_none=True)
|
135
|
+
_label = field_validator("label")(classmethod(valstr("label")))
|
136
|
+
_package_root = field_validator("package_root")(
|
137
|
+
classmethod(valstr("package_root", accept_none=True))
|
131
138
|
)
|
132
|
-
_package_name =
|
133
|
-
valstr("package_name", accept_none=True)
|
139
|
+
_package_name = field_validator("package_name")(
|
140
|
+
classmethod(valstr("package_name", accept_none=True))
|
134
141
|
)
|
135
|
-
_version =
|
136
|
-
valstr("version", accept_none=True)
|
142
|
+
_version = field_validator("version")(
|
143
|
+
classmethod(valstr("version", accept_none=True))
|
137
144
|
)
|
138
145
|
|
139
|
-
@
|
146
|
+
@model_validator(mode="before")
|
147
|
+
@classmethod
|
140
148
|
def one_of_package_root_or_name(cls, values):
|
141
149
|
package_root = values.get("package_root")
|
142
150
|
package_name = values.get("package_name")
|
@@ -149,18 +157,20 @@ class TaskCollectCustomV2(BaseModel, extra=Extra.forbid):
|
|
149
157
|
)
|
150
158
|
return values
|
151
159
|
|
152
|
-
@
|
160
|
+
@field_validator("package_name")
|
161
|
+
@classmethod
|
153
162
|
def package_name_validator(cls, value: str):
|
154
163
|
"""
|
155
164
|
Remove all whitespace characters, then check for invalid code.
|
156
165
|
"""
|
157
166
|
if value is not None:
|
158
167
|
validate_cmd(value)
|
159
|
-
value = valstr("package_name")(value)
|
168
|
+
value = valstr("package_name")(cls, value)
|
160
169
|
value = value.replace(" ", "")
|
161
170
|
return value
|
162
171
|
|
163
|
-
@
|
172
|
+
@field_validator("package_root")
|
173
|
+
@classmethod
|
164
174
|
def package_root_validator(cls, value):
|
165
175
|
if (value is not None) and (not Path(value).is_absolute()):
|
166
176
|
raise ValueError(
|
@@ -168,7 +178,8 @@ class TaskCollectCustomV2(BaseModel, extra=Extra.forbid):
|
|
168
178
|
)
|
169
179
|
return value
|
170
180
|
|
171
|
-
@
|
181
|
+
@field_validator("python_interpreter")
|
182
|
+
@classmethod
|
172
183
|
def python_interpreter_validator(cls, value):
|
173
184
|
if not Path(value).is_absolute():
|
174
185
|
raise ValueError(
|
@@ -3,9 +3,11 @@ from enum import Enum
|
|
3
3
|
from typing import Optional
|
4
4
|
|
5
5
|
from pydantic import BaseModel
|
6
|
-
from pydantic import
|
6
|
+
from pydantic import ConfigDict
|
7
7
|
from pydantic import Field
|
8
|
-
from pydantic import
|
8
|
+
from pydantic import field_serializer
|
9
|
+
from pydantic import field_validator
|
10
|
+
from pydantic.types import AwareDatetime
|
9
11
|
|
10
12
|
from .._validators import val_absolute_path
|
11
13
|
from .._validators import valdict_keys
|
@@ -32,7 +34,8 @@ class TaskGroupActivityActionV2(str, Enum):
|
|
32
34
|
REACTIVATE = "reactivate"
|
33
35
|
|
34
36
|
|
35
|
-
class TaskGroupCreateV2(BaseModel
|
37
|
+
class TaskGroupCreateV2(BaseModel):
|
38
|
+
model_config = ConfigDict(extra="forbid")
|
36
39
|
user_id: int
|
37
40
|
user_group_id: Optional[int] = None
|
38
41
|
active: bool = True
|
@@ -48,21 +51,21 @@ class TaskGroupCreateV2(BaseModel, extra=Extra.forbid):
|
|
48
51
|
pinned_package_versions: dict[str, str] = Field(default_factory=dict)
|
49
52
|
|
50
53
|
# Validators
|
51
|
-
_path =
|
52
|
-
_venv_path =
|
53
|
-
val_absolute_path("venv_path")
|
54
|
+
_path = field_validator("path")(classmethod(val_absolute_path("path")))
|
55
|
+
_venv_path = field_validator("venv_path")(
|
56
|
+
classmethod(val_absolute_path("venv_path"))
|
54
57
|
)
|
55
|
-
_wheel_path =
|
56
|
-
val_absolute_path("wheel_path")
|
58
|
+
_wheel_path = field_validator("wheel_path")(
|
59
|
+
classmethod(val_absolute_path("wheel_path"))
|
57
60
|
)
|
58
|
-
_pinned_package_versions =
|
59
|
-
"pinned_package_versions"
|
60
|
-
)(valdict_keys("pinned_package_versions"))
|
61
|
-
_pip_extras = validator("pip_extras", allow_reuse=True)(
|
62
|
-
valstr("pip_extras")
|
61
|
+
_pinned_package_versions = field_validator("pinned_package_versions")(
|
62
|
+
valdict_keys("pinned_package_versions")
|
63
63
|
)
|
64
|
-
|
65
|
-
valstr("
|
64
|
+
_pip_extras = field_validator("pip_extras")(
|
65
|
+
classmethod(valstr("pip_extras"))
|
66
|
+
)
|
67
|
+
_python_version = field_validator("python_version")(
|
68
|
+
classmethod(valstr("python_version"))
|
66
69
|
)
|
67
70
|
|
68
71
|
|
@@ -99,11 +102,16 @@ class TaskGroupReadV2(BaseModel):
|
|
99
102
|
venv_file_number: Optional[int] = None
|
100
103
|
|
101
104
|
active: bool
|
102
|
-
timestamp_created:
|
103
|
-
timestamp_last_used:
|
105
|
+
timestamp_created: AwareDatetime
|
106
|
+
timestamp_last_used: AwareDatetime
|
107
|
+
|
108
|
+
@field_serializer("timestamp_created", "timestamp_last_used")
|
109
|
+
def serialize_datetime(v: datetime) -> str:
|
110
|
+
return v.isoformat()
|
104
111
|
|
105
112
|
|
106
|
-
class TaskGroupUpdateV2(BaseModel
|
113
|
+
class TaskGroupUpdateV2(BaseModel):
|
114
|
+
model_config = ConfigDict(extra="forbid")
|
107
115
|
user_group_id: Optional[int] = None
|
108
116
|
|
109
117
|
|
@@ -111,10 +119,21 @@ class TaskGroupActivityV2Read(BaseModel):
|
|
111
119
|
id: int
|
112
120
|
user_id: int
|
113
121
|
taskgroupv2_id: Optional[int] = None
|
114
|
-
timestamp_started:
|
115
|
-
timestamp_ended: Optional[
|
122
|
+
timestamp_started: AwareDatetime
|
123
|
+
timestamp_ended: Optional[AwareDatetime] = None
|
116
124
|
pkg_name: str
|
117
125
|
version: str
|
118
126
|
status: TaskGroupActivityStatusV2
|
119
127
|
action: TaskGroupActivityActionV2
|
120
128
|
log: Optional[str] = None
|
129
|
+
|
130
|
+
@field_serializer("timestamp_started")
|
131
|
+
def serialize_datetime_start(v: datetime) -> str:
|
132
|
+
return v.isoformat()
|
133
|
+
|
134
|
+
@field_serializer("timestamp_ended")
|
135
|
+
def serialize_datetime_end(v: Optional[datetime]) -> Optional[str]:
|
136
|
+
if v is None:
|
137
|
+
return None
|
138
|
+
else:
|
139
|
+
return v.isoformat()
|
@@ -2,8 +2,10 @@ from datetime import datetime
|
|
2
2
|
from typing import Optional
|
3
3
|
|
4
4
|
from pydantic import BaseModel
|
5
|
-
from pydantic import
|
6
|
-
from pydantic import
|
5
|
+
from pydantic import ConfigDict
|
6
|
+
from pydantic import field_serializer
|
7
|
+
from pydantic import field_validator
|
8
|
+
from pydantic.types import AwareDatetime
|
7
9
|
|
8
10
|
from .._validators import valstr
|
9
11
|
from .project import ProjectReadV2
|
@@ -13,12 +15,14 @@ from .workflowtask import WorkflowTaskReadV2
|
|
13
15
|
from .workflowtask import WorkflowTaskReadV2WithWarning
|
14
16
|
|
15
17
|
|
16
|
-
class WorkflowCreateV2(BaseModel
|
18
|
+
class WorkflowCreateV2(BaseModel):
|
19
|
+
|
20
|
+
model_config = ConfigDict(extra="forbid")
|
17
21
|
|
18
22
|
name: str
|
19
23
|
|
20
24
|
# Validators
|
21
|
-
_name =
|
25
|
+
_name = field_validator("name")(classmethod(valstr("name")))
|
22
26
|
|
23
27
|
|
24
28
|
class WorkflowReadV2(BaseModel):
|
@@ -28,22 +32,29 @@ class WorkflowReadV2(BaseModel):
|
|
28
32
|
project_id: int
|
29
33
|
task_list: list[WorkflowTaskReadV2]
|
30
34
|
project: ProjectReadV2
|
31
|
-
timestamp_created:
|
35
|
+
timestamp_created: AwareDatetime
|
36
|
+
|
37
|
+
@field_serializer("timestamp_created")
|
38
|
+
def serialize_datetime(v: datetime) -> str:
|
39
|
+
return v.isoformat()
|
32
40
|
|
33
41
|
|
34
42
|
class WorkflowReadV2WithWarnings(WorkflowReadV2):
|
35
43
|
task_list: list[WorkflowTaskReadV2WithWarning]
|
36
44
|
|
37
45
|
|
38
|
-
class WorkflowUpdateV2(BaseModel
|
46
|
+
class WorkflowUpdateV2(BaseModel):
|
47
|
+
|
48
|
+
model_config = ConfigDict(extra="forbid")
|
39
49
|
|
40
|
-
name: Optional[str]
|
41
|
-
reordered_workflowtask_ids: Optional[list[int]]
|
50
|
+
name: Optional[str] = None
|
51
|
+
reordered_workflowtask_ids: Optional[list[int]] = None
|
42
52
|
|
43
53
|
# Validators
|
44
|
-
_name =
|
54
|
+
_name = field_validator("name")(classmethod(valstr("name")))
|
45
55
|
|
46
|
-
@
|
56
|
+
@field_validator("reordered_workflowtask_ids")
|
57
|
+
@classmethod
|
47
58
|
def check_positive_and_unique(cls, value):
|
48
59
|
if any(i < 0 for i in value):
|
49
60
|
raise ValueError("Negative `id` in `reordered_workflowtask_ids`")
|
@@ -52,7 +63,7 @@ class WorkflowUpdateV2(BaseModel, extra=Extra.forbid):
|
|
52
63
|
return value
|
53
64
|
|
54
65
|
|
55
|
-
class WorkflowImportV2(BaseModel
|
66
|
+
class WorkflowImportV2(BaseModel):
|
56
67
|
"""
|
57
68
|
Class for `Workflow` import.
|
58
69
|
|
@@ -60,11 +71,12 @@ class WorkflowImportV2(BaseModel, extra=Extra.forbid):
|
|
60
71
|
task_list:
|
61
72
|
"""
|
62
73
|
|
74
|
+
model_config = ConfigDict(extra="forbid")
|
63
75
|
name: str
|
64
76
|
task_list: list[WorkflowTaskImportV2]
|
65
77
|
|
66
78
|
# Validators
|
67
|
-
_name =
|
79
|
+
_name = field_validator("name")(classmethod(valstr("name")))
|
68
80
|
|
69
81
|
|
70
82
|
class WorkflowExportV2(BaseModel):
|
@@ -4,10 +4,10 @@ from typing import Optional
|
|
4
4
|
from typing import Union
|
5
5
|
|
6
6
|
from pydantic import BaseModel
|
7
|
-
from pydantic import
|
7
|
+
from pydantic import ConfigDict
|
8
8
|
from pydantic import Field
|
9
|
-
from pydantic import
|
10
|
-
from pydantic import
|
9
|
+
from pydantic import field_validator
|
10
|
+
from pydantic import model_validator
|
11
11
|
|
12
12
|
from .._filter_validators import validate_type_filters
|
13
13
|
from .._validators import root_validate_dict_keys
|
@@ -39,34 +39,35 @@ class WorkflowTaskStatusTypeV2(str, Enum):
|
|
39
39
|
FAILED = "failed"
|
40
40
|
|
41
41
|
|
42
|
-
class WorkflowTaskCreateV2(BaseModel
|
42
|
+
class WorkflowTaskCreateV2(BaseModel):
|
43
|
+
model_config = ConfigDict(extra="forbid")
|
43
44
|
|
44
|
-
meta_non_parallel: Optional[dict[str, Any]]
|
45
|
-
meta_parallel: Optional[dict[str, Any]]
|
46
|
-
args_non_parallel: Optional[dict[str, Any]]
|
47
|
-
args_parallel: Optional[dict[str, Any]]
|
45
|
+
meta_non_parallel: Optional[dict[str, Any]] = None
|
46
|
+
meta_parallel: Optional[dict[str, Any]] = None
|
47
|
+
args_non_parallel: Optional[dict[str, Any]] = None
|
48
|
+
args_parallel: Optional[dict[str, Any]] = None
|
48
49
|
type_filters: dict[str, bool] = Field(default_factory=dict)
|
49
50
|
|
50
51
|
# Validators
|
51
|
-
_dict_keys =
|
52
|
-
root_validate_dict_keys
|
52
|
+
_dict_keys = model_validator(mode="before")(
|
53
|
+
classmethod(root_validate_dict_keys)
|
53
54
|
)
|
54
|
-
_type_filters =
|
55
|
-
validate_type_filters
|
55
|
+
_type_filters = field_validator("type_filters")(
|
56
|
+
classmethod(validate_type_filters)
|
56
57
|
)
|
57
|
-
|
58
|
-
|
59
|
-
valdict_keys("meta_non_parallel")
|
58
|
+
_meta_non_parallel = field_validator("meta_non_parallel")(
|
59
|
+
classmethod(valdict_keys("meta_non_parallel"))
|
60
60
|
)
|
61
|
-
_meta_parallel =
|
62
|
-
valdict_keys("meta_parallel")
|
61
|
+
_meta_parallel = field_validator("meta_parallel")(
|
62
|
+
classmethod(valdict_keys("meta_parallel"))
|
63
63
|
)
|
64
64
|
|
65
|
-
@
|
65
|
+
@field_validator("args_non_parallel")
|
66
|
+
@classmethod
|
66
67
|
def validate_args_non_parallel(cls, value):
|
67
68
|
if value is None:
|
68
69
|
return
|
69
|
-
valdict_keys("args_non_parallel")(value)
|
70
|
+
valdict_keys("args_non_parallel")(cls, value)
|
70
71
|
args_keys = set(value.keys())
|
71
72
|
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
72
73
|
if intersect_keys:
|
@@ -76,11 +77,12 @@ class WorkflowTaskCreateV2(BaseModel, extra=Extra.forbid):
|
|
76
77
|
)
|
77
78
|
return value
|
78
79
|
|
79
|
-
@
|
80
|
+
@field_validator("args_parallel")
|
81
|
+
@classmethod
|
80
82
|
def validate_args_parallel(cls, value):
|
81
83
|
if value is None:
|
82
84
|
return
|
83
|
-
valdict_keys("args_parallel")(value)
|
85
|
+
valdict_keys("args_parallel")(cls, value)
|
84
86
|
args_keys = set(value.keys())
|
85
87
|
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
86
88
|
if intersect_keys:
|
@@ -99,16 +101,15 @@ class WorkflowTaskReplaceV2(BaseModel):
|
|
99
101
|
|
100
102
|
|
101
103
|
class WorkflowTaskReadV2(BaseModel):
|
102
|
-
|
103
104
|
id: int
|
104
105
|
|
105
106
|
workflow_id: int
|
106
|
-
order: Optional[int]
|
107
|
-
meta_non_parallel: Optional[dict[str, Any]]
|
108
|
-
meta_parallel: Optional[dict[str, Any]]
|
107
|
+
order: Optional[int] = None
|
108
|
+
meta_non_parallel: Optional[dict[str, Any]] = None
|
109
|
+
meta_parallel: Optional[dict[str, Any]] = None
|
109
110
|
|
110
|
-
args_non_parallel: Optional[dict[str, Any]]
|
111
|
-
args_parallel: Optional[dict[str, Any]]
|
111
|
+
args_non_parallel: Optional[dict[str, Any]] = None
|
112
|
+
args_parallel: Optional[dict[str, Any]] = None
|
112
113
|
|
113
114
|
type_filters: dict[str, bool]
|
114
115
|
|
@@ -121,34 +122,35 @@ class WorkflowTaskReadV2WithWarning(WorkflowTaskReadV2):
|
|
121
122
|
warning: Optional[str] = None
|
122
123
|
|
123
124
|
|
124
|
-
class WorkflowTaskUpdateV2(BaseModel
|
125
|
+
class WorkflowTaskUpdateV2(BaseModel):
|
126
|
+
model_config = ConfigDict(extra="forbid")
|
125
127
|
|
126
|
-
meta_non_parallel: Optional[dict[str, Any]]
|
127
|
-
meta_parallel: Optional[dict[str, Any]]
|
128
|
-
args_non_parallel: Optional[dict[str, Any]]
|
129
|
-
args_parallel: Optional[dict[str, Any]]
|
130
|
-
type_filters: Optional[dict[str, bool]]
|
128
|
+
meta_non_parallel: Optional[dict[str, Any]] = None
|
129
|
+
meta_parallel: Optional[dict[str, Any]] = None
|
130
|
+
args_non_parallel: Optional[dict[str, Any]] = None
|
131
|
+
args_parallel: Optional[dict[str, Any]] = None
|
132
|
+
type_filters: Optional[dict[str, bool]] = None
|
131
133
|
|
132
134
|
# Validators
|
133
|
-
_dict_keys =
|
134
|
-
root_validate_dict_keys
|
135
|
+
_dict_keys = model_validator(mode="before")(
|
136
|
+
classmethod(root_validate_dict_keys)
|
135
137
|
)
|
136
|
-
_type_filters =
|
137
|
-
validate_type_filters
|
138
|
+
_type_filters = field_validator("type_filters")(
|
139
|
+
classmethod(validate_type_filters)
|
138
140
|
)
|
139
|
-
|
140
|
-
|
141
|
-
valdict_keys("meta_non_parallel")
|
141
|
+
_meta_non_parallel = field_validator("meta_non_parallel")(
|
142
|
+
classmethod(valdict_keys("meta_non_parallel"))
|
142
143
|
)
|
143
|
-
_meta_parallel =
|
144
|
-
valdict_keys("meta_parallel")
|
144
|
+
_meta_parallel = field_validator("meta_parallel")(
|
145
|
+
classmethod(valdict_keys("meta_parallel"))
|
145
146
|
)
|
146
147
|
|
147
|
-
@
|
148
|
+
@field_validator("args_non_parallel")
|
149
|
+
@classmethod
|
148
150
|
def validate_args_non_parallel(cls, value):
|
149
151
|
if value is None:
|
150
152
|
return
|
151
|
-
valdict_keys("args_non_parallel")(value)
|
153
|
+
valdict_keys("args_non_parallel")(cls, value)
|
152
154
|
args_keys = set(value.keys())
|
153
155
|
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
154
156
|
if intersect_keys:
|
@@ -158,11 +160,12 @@ class WorkflowTaskUpdateV2(BaseModel, extra=Extra.forbid):
|
|
158
160
|
)
|
159
161
|
return value
|
160
162
|
|
161
|
-
@
|
163
|
+
@field_validator("args_parallel")
|
164
|
+
@classmethod
|
162
165
|
def validate_args_parallel(cls, value):
|
163
166
|
if value is None:
|
164
167
|
return
|
165
|
-
valdict_keys("args_parallel")(value)
|
168
|
+
valdict_keys("args_parallel")(cls, value)
|
166
169
|
args_keys = set(value.keys())
|
167
170
|
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
168
171
|
if intersect_keys:
|
@@ -173,7 +176,8 @@ class WorkflowTaskUpdateV2(BaseModel, extra=Extra.forbid):
|
|
173
176
|
return value
|
174
177
|
|
175
178
|
|
176
|
-
class WorkflowTaskImportV2(BaseModel
|
179
|
+
class WorkflowTaskImportV2(BaseModel):
|
180
|
+
model_config = ConfigDict(extra="forbid")
|
177
181
|
|
178
182
|
meta_non_parallel: Optional[dict[str, Any]] = None
|
179
183
|
meta_parallel: Optional[dict[str, Any]] = None
|
@@ -185,7 +189,8 @@ class WorkflowTaskImportV2(BaseModel, extra=Extra.forbid):
|
|
185
189
|
task: Union[TaskImportV2, TaskImportV2Legacy]
|
186
190
|
|
187
191
|
# Validators
|
188
|
-
@
|
192
|
+
@model_validator(mode="before")
|
193
|
+
@classmethod
|
189
194
|
def update_legacy_filters(cls, values: dict):
|
190
195
|
"""
|
191
196
|
Transform legacy filters (created with fractal-server<2.11.0)
|
@@ -197,7 +202,6 @@ class WorkflowTaskImportV2(BaseModel, extra=Extra.forbid):
|
|
197
202
|
"Cannot set filters both through the legacy field "
|
198
203
|
"('filters') and the new one ('type_filters')."
|
199
204
|
)
|
200
|
-
|
201
205
|
else:
|
202
206
|
# As of 2.11.0, WorkflowTask do not have attribute filters
|
203
207
|
# any more.
|
@@ -213,26 +217,24 @@ class WorkflowTaskImportV2(BaseModel, extra=Extra.forbid):
|
|
213
217
|
|
214
218
|
return values
|
215
219
|
|
216
|
-
_type_filters =
|
217
|
-
validate_type_filters
|
220
|
+
_type_filters = field_validator("type_filters")(
|
221
|
+
classmethod(validate_type_filters)
|
218
222
|
)
|
219
|
-
|
220
|
-
|
221
|
-
valdict_keys("meta_non_parallel")
|
223
|
+
_meta_non_parallel = field_validator("meta_non_parallel")(
|
224
|
+
classmethod(valdict_keys("meta_non_parallel"))
|
222
225
|
)
|
223
|
-
_meta_parallel =
|
224
|
-
valdict_keys("meta_parallel")
|
226
|
+
_meta_parallel = field_validator("meta_parallel")(
|
227
|
+
classmethod(valdict_keys("meta_parallel"))
|
225
228
|
)
|
226
|
-
_args_non_parallel =
|
227
|
-
valdict_keys("args_non_parallel")
|
229
|
+
_args_non_parallel = field_validator("args_non_parallel")(
|
230
|
+
classmethod(valdict_keys("args_non_parallel"))
|
228
231
|
)
|
229
|
-
_args_parallel =
|
230
|
-
valdict_keys("args_parallel")
|
232
|
+
_args_parallel = field_validator("args_parallel")(
|
233
|
+
classmethod(valdict_keys("args_parallel"))
|
231
234
|
)
|
232
235
|
|
233
236
|
|
234
237
|
class WorkflowTaskExportV2(BaseModel):
|
235
|
-
|
236
238
|
meta_non_parallel: Optional[dict[str, Any]] = None
|
237
239
|
meta_parallel: Optional[dict[str, Any]] = None
|
238
240
|
args_non_parallel: Optional[dict[str, Any]] = None
|
@@ -83,7 +83,7 @@ class SQLModelUserDatabaseAsync(Generic[UP, ID], BaseUserDatabase[UP, ID]):
|
|
83
83
|
|
84
84
|
session: AsyncSession
|
85
85
|
user_model: Type[UP]
|
86
|
-
oauth_account_model: Optional[Type[OAuthAccount]]
|
86
|
+
oauth_account_model: Optional[Type[OAuthAccount]] = None
|
87
87
|
|
88
88
|
def __init__(
|
89
89
|
self,
|