fractal-server 2.14.5__py3-none-any.whl → 2.14.6__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/db/__init__.py +2 -2
- fractal_server/app/models/security.py +8 -8
- fractal_server/app/models/user_settings.py +8 -10
- fractal_server/app/models/v2/accounting.py +2 -3
- fractal_server/app/models/v2/dataset.py +1 -2
- fractal_server/app/models/v2/history.py +3 -4
- fractal_server/app/models/v2/job.py +10 -11
- fractal_server/app/models/v2/project.py +1 -2
- fractal_server/app/models/v2/task.py +13 -14
- fractal_server/app/models/v2/task_group.py +15 -16
- fractal_server/app/models/v2/workflow.py +1 -2
- fractal_server/app/models/v2/workflowtask.py +6 -7
- fractal_server/app/routes/admin/v2/accounting.py +3 -4
- fractal_server/app/routes/admin/v2/job.py +13 -14
- fractal_server/app/routes/admin/v2/project.py +2 -4
- fractal_server/app/routes/admin/v2/task.py +11 -13
- fractal_server/app/routes/admin/v2/task_group.py +15 -17
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +5 -8
- fractal_server/app/routes/api/v2/__init__.py +2 -0
- fractal_server/app/routes/api/v2/_aux_functions.py +7 -9
- fractal_server/app/routes/api/v2/_aux_functions_history.py +1 -1
- fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +1 -3
- fractal_server/app/routes/api/v2/_aux_functions_tasks.py +5 -6
- fractal_server/app/routes/api/v2/dataset.py +6 -8
- fractal_server/app/routes/api/v2/history.py +5 -8
- fractal_server/app/routes/api/v2/images.py +2 -3
- fractal_server/app/routes/api/v2/job.py +5 -6
- fractal_server/app/routes/api/v2/pre_submission_checks.py +1 -3
- fractal_server/app/routes/api/v2/project.py +2 -4
- fractal_server/app/routes/api/v2/status_legacy.py +2 -4
- fractal_server/app/routes/api/v2/submit.py +3 -4
- fractal_server/app/routes/api/v2/task.py +6 -7
- fractal_server/app/routes/api/v2/task_collection.py +11 -13
- fractal_server/app/routes/api/v2/task_collection_custom.py +4 -4
- fractal_server/app/routes/api/v2/task_group.py +6 -8
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +6 -9
- fractal_server/app/routes/api/v2/task_version_update.py +270 -0
- fractal_server/app/routes/api/v2/workflow.py +5 -6
- fractal_server/app/routes/api/v2/workflow_import.py +3 -5
- fractal_server/app/routes/api/v2/workflowtask.py +2 -114
- fractal_server/app/routes/auth/current_user.py +2 -2
- fractal_server/app/routes/pagination.py +2 -3
- fractal_server/app/runner/exceptions.py +15 -16
- fractal_server/app/runner/executors/base_runner.py +3 -3
- fractal_server/app/runner/executors/call_command_wrapper.py +1 -1
- fractal_server/app/runner/executors/local/get_local_config.py +2 -3
- fractal_server/app/runner/executors/local/runner.py +1 -1
- fractal_server/app/runner/executors/slurm_common/_batching.py +2 -3
- fractal_server/app/runner/executors/slurm_common/_slurm_config.py +27 -29
- fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +11 -14
- fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +2 -3
- fractal_server/app/runner/executors/slurm_common/remote.py +2 -2
- fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +2 -3
- fractal_server/app/runner/executors/slurm_ssh/run_subprocess.py +2 -3
- fractal_server/app/runner/executors/slurm_ssh/runner.py +3 -4
- fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +1 -2
- fractal_server/app/runner/executors/slurm_sudo/runner.py +6 -7
- fractal_server/app/runner/set_start_and_last_task_index.py +2 -5
- fractal_server/app/runner/shutdown.py +5 -11
- fractal_server/app/runner/task_files.py +3 -5
- fractal_server/app/runner/v2/_local.py +3 -4
- fractal_server/app/runner/v2/_slurm_ssh.py +4 -5
- fractal_server/app/runner/v2/_slurm_sudo.py +7 -8
- fractal_server/app/runner/v2/runner.py +4 -5
- fractal_server/app/runner/v2/runner_functions.py +4 -5
- fractal_server/app/runner/v2/submit_workflow.py +7 -10
- fractal_server/app/runner/v2/task_interface.py +2 -3
- fractal_server/app/runner/versions.py +1 -2
- fractal_server/app/schemas/user.py +2 -4
- fractal_server/app/schemas/user_group.py +1 -2
- fractal_server/app/schemas/user_settings.py +19 -21
- fractal_server/app/schemas/v2/dataset.py +2 -3
- fractal_server/app/schemas/v2/dumps.py +13 -15
- fractal_server/app/schemas/v2/history.py +6 -7
- fractal_server/app/schemas/v2/job.py +17 -18
- fractal_server/app/schemas/v2/manifest.py +12 -13
- fractal_server/app/schemas/v2/status_legacy.py +2 -2
- fractal_server/app/schemas/v2/task.py +29 -30
- fractal_server/app/schemas/v2/task_collection.py +8 -9
- fractal_server/app/schemas/v2/task_group.py +22 -23
- fractal_server/app/schemas/v2/workflow.py +1 -2
- fractal_server/app/schemas/v2/workflowtask.py +27 -29
- fractal_server/app/security/__init__.py +10 -12
- fractal_server/config.py +32 -33
- fractal_server/images/models.py +2 -4
- fractal_server/images/tools.py +4 -7
- fractal_server/logger.py +3 -5
- fractal_server/ssh/_fabric.py +37 -12
- fractal_server/string_tools.py +2 -2
- fractal_server/syringe.py +1 -1
- fractal_server/tasks/v2/local/collect.py +2 -3
- fractal_server/tasks/v2/local/deactivate.py +1 -1
- fractal_server/tasks/v2/local/reactivate.py +1 -1
- fractal_server/tasks/v2/ssh/collect.py +256 -245
- fractal_server/tasks/v2/ssh/deactivate.py +210 -187
- fractal_server/tasks/v2/ssh/reactivate.py +154 -146
- fractal_server/tasks/v2/utils_background.py +2 -3
- fractal_server/types/__init__.py +1 -2
- fractal_server/types/validators/_filter_validators.py +1 -2
- fractal_server/utils.py +4 -5
- fractal_server/zip_tools.py +1 -1
- {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/METADATA +2 -3
- {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/RECORD +107 -107
- fractal_server/app/history/__init__.py +0 -0
- {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/LICENSE +0 -0
- {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/WHEEL +0 -0
- {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/entry_points.txt +0 -0
fractal_server/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "2.14.
|
1
|
+
__VERSION__ = "2.14.6"
|
@@ -2,8 +2,8 @@
|
|
2
2
|
`db` module, loosely adapted from
|
3
3
|
https://testdriven.io/blog/fastapi-sqlmodel/#async-sqlmodel
|
4
4
|
"""
|
5
|
-
from
|
6
|
-
from
|
5
|
+
from collections.abc import AsyncGenerator
|
6
|
+
from collections.abc import Generator
|
7
7
|
|
8
8
|
from sqlalchemy import create_engine
|
9
9
|
from sqlalchemy.ext.asyncio import AsyncSession
|
@@ -46,13 +46,13 @@ class OAuthAccount(SQLModel, table=True):
|
|
46
46
|
|
47
47
|
__tablename__ = "oauthaccount"
|
48
48
|
|
49
|
-
id:
|
49
|
+
id: int | None = Field(default=None, primary_key=True)
|
50
50
|
user_id: int = Field(foreign_key="user_oauth.id", nullable=False)
|
51
51
|
user: Optional["UserOAuth"] = Relationship(back_populates="oauth_accounts")
|
52
52
|
oauth_name: str = Field(index=True, nullable=False)
|
53
53
|
access_token: str = Field(nullable=False)
|
54
|
-
expires_at:
|
55
|
-
refresh_token:
|
54
|
+
expires_at: int | None = Field(nullable=True, default=None)
|
55
|
+
refresh_token: str | None = Field(nullable=True, default=None)
|
56
56
|
account_id: str = Field(index=True, nullable=False)
|
57
57
|
account_email: str = Field(nullable=False)
|
58
58
|
model_config = ConfigDict(from_attributes=True)
|
@@ -81,7 +81,7 @@ class UserOAuth(SQLModel, table=True):
|
|
81
81
|
|
82
82
|
__tablename__ = "user_oauth"
|
83
83
|
|
84
|
-
id:
|
84
|
+
id: int | None = Field(default=None, primary_key=True)
|
85
85
|
|
86
86
|
email: EmailStr = Field(
|
87
87
|
sa_column_kwargs={"unique": True, "index": True}, nullable=False
|
@@ -91,17 +91,17 @@ class UserOAuth(SQLModel, table=True):
|
|
91
91
|
is_superuser: bool = Field(default=False, nullable=False)
|
92
92
|
is_verified: bool = Field(default=False, nullable=False)
|
93
93
|
|
94
|
-
username:
|
94
|
+
username: str | None = None
|
95
95
|
|
96
96
|
oauth_accounts: list["OAuthAccount"] = Relationship(
|
97
97
|
back_populates="user",
|
98
98
|
sa_relationship_kwargs={"lazy": "joined", "cascade": "all, delete"},
|
99
99
|
)
|
100
100
|
|
101
|
-
user_settings_id:
|
101
|
+
user_settings_id: int | None = Field(
|
102
102
|
foreign_key="user_settings.id", default=None
|
103
103
|
)
|
104
|
-
settings:
|
104
|
+
settings: UserSettings | None = Relationship(
|
105
105
|
sa_relationship_kwargs=dict(lazy="selectin", cascade="all, delete")
|
106
106
|
)
|
107
107
|
model_config = ConfigDict(from_attributes=True)
|
@@ -117,7 +117,7 @@ class UserGroup(SQLModel, table=True):
|
|
117
117
|
timestamp_created: Time of creation
|
118
118
|
"""
|
119
119
|
|
120
|
-
id:
|
120
|
+
id: int | None = Field(default=None, primary_key=True)
|
121
121
|
name: str = Field(unique=True)
|
122
122
|
timestamp_created: datetime = Field(
|
123
123
|
default_factory=get_timestamp,
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from sqlalchemy import Column
|
4
2
|
from sqlalchemy.types import JSON
|
5
3
|
from sqlmodel import Field
|
@@ -25,14 +23,14 @@ class UserSettings(SQLModel, table=True):
|
|
25
23
|
|
26
24
|
__tablename__ = "user_settings"
|
27
25
|
|
28
|
-
id:
|
26
|
+
id: int | None = Field(default=None, primary_key=True)
|
29
27
|
slurm_accounts: list[str] = Field(
|
30
28
|
sa_column=Column(JSON, server_default="[]", nullable=False)
|
31
29
|
)
|
32
|
-
ssh_host:
|
33
|
-
ssh_username:
|
34
|
-
ssh_private_key_path:
|
35
|
-
ssh_tasks_dir:
|
36
|
-
ssh_jobs_dir:
|
37
|
-
slurm_user:
|
38
|
-
project_dir:
|
30
|
+
ssh_host: str | None = None
|
31
|
+
ssh_username: str | None = None
|
32
|
+
ssh_private_key_path: str | None = None
|
33
|
+
ssh_tasks_dir: str | None = None
|
34
|
+
ssh_jobs_dir: str | None = None
|
35
|
+
slurm_user: str | None = None
|
36
|
+
project_dir: str | None = None
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from sqlalchemy import Column
|
5
4
|
from sqlalchemy import Integer
|
@@ -12,7 +11,7 @@ from ....utils import get_timestamp
|
|
12
11
|
|
13
12
|
|
14
13
|
class AccountingRecord(SQLModel, table=True):
|
15
|
-
id:
|
14
|
+
id: int | None = Field(default=None, primary_key=True)
|
16
15
|
user_id: int = Field(foreign_key="user_oauth.id", nullable=False)
|
17
16
|
timestamp: datetime = Field(
|
18
17
|
default_factory=get_timestamp,
|
@@ -23,7 +22,7 @@ class AccountingRecord(SQLModel, table=True):
|
|
23
22
|
|
24
23
|
|
25
24
|
class AccountingRecordSlurm(SQLModel, table=True):
|
26
|
-
id:
|
25
|
+
id: int | None = Field(default=None, primary_key=True)
|
27
26
|
user_id: int = Field(foreign_key="user_oauth.id", nullable=False)
|
28
27
|
timestamp: datetime = Field(
|
29
28
|
default_factory=get_timestamp,
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from typing import Any
|
3
|
-
from typing import Optional
|
4
3
|
|
5
4
|
from pydantic import ConfigDict
|
6
5
|
from sqlalchemy import Column
|
@@ -16,7 +15,7 @@ from ....utils import get_timestamp
|
|
16
15
|
class DatasetV2(SQLModel, table=True):
|
17
16
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
18
17
|
|
19
|
-
id:
|
18
|
+
id: int | None = Field(default=None, primary_key=True)
|
20
19
|
name: str
|
21
20
|
|
22
21
|
project_id: int = Field(foreign_key="projectv2.id", ondelete="CASCADE")
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from typing import Any
|
3
|
-
from typing import Optional
|
4
3
|
|
5
4
|
from pydantic import ConfigDict
|
6
5
|
from sqlalchemy import Column
|
@@ -17,12 +16,12 @@ from ....utils import get_timestamp
|
|
17
16
|
class HistoryRun(SQLModel, table=True):
|
18
17
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
19
18
|
|
20
|
-
id:
|
19
|
+
id: int | None = Field(default=None, primary_key=True)
|
21
20
|
dataset_id: int = Field(
|
22
21
|
foreign_key="datasetv2.id",
|
23
22
|
ondelete="CASCADE",
|
24
23
|
)
|
25
|
-
workflowtask_id:
|
24
|
+
workflowtask_id: int | None = Field(
|
26
25
|
foreign_key="workflowtaskv2.id",
|
27
26
|
default=None,
|
28
27
|
ondelete="SET NULL",
|
@@ -45,7 +44,7 @@ class HistoryRun(SQLModel, table=True):
|
|
45
44
|
|
46
45
|
|
47
46
|
class HistoryUnit(SQLModel, table=True):
|
48
|
-
id:
|
47
|
+
id: int | None = Field(default=None, primary_key=True)
|
49
48
|
history_run_id: int = Field(
|
50
49
|
foreign_key="historyrun.id",
|
51
50
|
ondelete="CASCADE",
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from typing import Any
|
3
|
-
from typing import Optional
|
4
3
|
|
5
4
|
from pydantic import ConfigDict
|
6
5
|
from sqlalchemy import Column
|
@@ -17,19 +16,19 @@ from fractal_server.types import AttributeFilters
|
|
17
16
|
class JobV2(SQLModel, table=True):
|
18
17
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
19
18
|
|
20
|
-
id:
|
21
|
-
project_id:
|
19
|
+
id: int | None = Field(default=None, primary_key=True)
|
20
|
+
project_id: int | None = Field(
|
22
21
|
foreign_key="projectv2.id", default=None, ondelete="SET NULL"
|
23
22
|
)
|
24
|
-
workflow_id:
|
23
|
+
workflow_id: int | None = Field(
|
25
24
|
foreign_key="workflowv2.id", default=None, ondelete="SET NULL"
|
26
25
|
)
|
27
|
-
dataset_id:
|
26
|
+
dataset_id: int | None = Field(
|
28
27
|
foreign_key="datasetv2.id", default=None, ondelete="SET NULL"
|
29
28
|
)
|
30
29
|
|
31
30
|
user_email: str = Field(nullable=False)
|
32
|
-
slurm_account:
|
31
|
+
slurm_account: str | None = None
|
33
32
|
|
34
33
|
dataset_dump: dict[str, Any] = Field(
|
35
34
|
sa_column=Column(JSON, nullable=False)
|
@@ -41,9 +40,9 @@ class JobV2(SQLModel, table=True):
|
|
41
40
|
sa_column=Column(JSON, nullable=False)
|
42
41
|
)
|
43
42
|
|
44
|
-
worker_init:
|
45
|
-
working_dir:
|
46
|
-
working_dir_user:
|
43
|
+
worker_init: str | None = None
|
44
|
+
working_dir: str | None = None
|
45
|
+
working_dir_user: str | None = None
|
47
46
|
first_task_index: int
|
48
47
|
last_task_index: int
|
49
48
|
|
@@ -51,11 +50,11 @@ class JobV2(SQLModel, table=True):
|
|
51
50
|
default_factory=get_timestamp,
|
52
51
|
sa_column=Column(DateTime(timezone=True), nullable=False),
|
53
52
|
)
|
54
|
-
end_timestamp:
|
53
|
+
end_timestamp: datetime | None = Field(
|
55
54
|
default=None, sa_column=Column(DateTime(timezone=True))
|
56
55
|
)
|
57
56
|
status: str = JobStatusTypeV2.SUBMITTED
|
58
|
-
log:
|
57
|
+
log: str | None = None
|
59
58
|
|
60
59
|
attribute_filters: AttributeFilters = Field(
|
61
60
|
sa_column=Column(JSON, nullable=False, server_default="{}")
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from sqlalchemy import Column
|
5
4
|
from sqlalchemy.types import DateTime
|
@@ -14,7 +13,7 @@ from fractal_server.utils import get_timestamp
|
|
14
13
|
|
15
14
|
class ProjectV2(SQLModel, table=True):
|
16
15
|
|
17
|
-
id:
|
16
|
+
id: int | None = Field(default=None, primary_key=True)
|
18
17
|
name: str
|
19
18
|
timestamp_created: datetime = Field(
|
20
19
|
default_factory=get_timestamp,
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from typing import Any
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from sqlalchemy import Column
|
5
4
|
from sqlalchemy.types import JSON
|
@@ -8,13 +7,13 @@ from sqlmodel import SQLModel
|
|
8
7
|
|
9
8
|
|
10
9
|
class TaskV2(SQLModel, table=True):
|
11
|
-
id:
|
10
|
+
id: int | None = Field(default=None, primary_key=True)
|
12
11
|
name: str
|
13
12
|
|
14
13
|
type: str
|
15
|
-
command_non_parallel:
|
16
|
-
command_parallel:
|
17
|
-
source:
|
14
|
+
command_non_parallel: str | None = None
|
15
|
+
command_parallel: str | None = None
|
16
|
+
source: str | None = None
|
18
17
|
|
19
18
|
meta_non_parallel: dict[str, Any] = Field(
|
20
19
|
sa_column=Column(JSON, server_default="{}", default={}, nullable=False)
|
@@ -23,25 +22,25 @@ class TaskV2(SQLModel, table=True):
|
|
23
22
|
sa_column=Column(JSON, server_default="{}", default={}, nullable=False)
|
24
23
|
)
|
25
24
|
|
26
|
-
version:
|
27
|
-
args_schema_non_parallel:
|
25
|
+
version: str | None = None
|
26
|
+
args_schema_non_parallel: dict[str, Any] | None = Field(
|
28
27
|
sa_column=Column(JSON), default=None
|
29
28
|
)
|
30
|
-
args_schema_parallel:
|
29
|
+
args_schema_parallel: dict[str, Any] | None = Field(
|
31
30
|
sa_column=Column(JSON), default=None
|
32
31
|
)
|
33
|
-
args_schema_version:
|
34
|
-
docs_info:
|
35
|
-
docs_link:
|
32
|
+
args_schema_version: str | None = None
|
33
|
+
docs_info: str | None = None
|
34
|
+
docs_link: str | None = None
|
36
35
|
|
37
36
|
input_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
|
38
37
|
output_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
|
39
38
|
|
40
39
|
taskgroupv2_id: int = Field(foreign_key="taskgroupv2.id")
|
41
40
|
|
42
|
-
category:
|
43
|
-
modality:
|
44
|
-
authors:
|
41
|
+
category: str | None = None
|
42
|
+
modality: str | None = None
|
43
|
+
authors: str | None = None
|
45
44
|
tags: list[str] = Field(
|
46
45
|
sa_column=Column(JSON, server_default="[]", nullable=False)
|
47
46
|
)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from datetime import timezone
|
3
|
-
from typing import Optional
|
4
3
|
|
5
4
|
from sqlalchemy import Column
|
6
5
|
from sqlalchemy.types import DateTime
|
@@ -14,7 +13,7 @@ from fractal_server.utils import get_timestamp
|
|
14
13
|
|
15
14
|
|
16
15
|
class TaskGroupV2(SQLModel, table=True):
|
17
|
-
id:
|
16
|
+
id: int | None = Field(default=None, primary_key=True)
|
18
17
|
task_list: list[TaskV2] = Relationship(
|
19
18
|
sa_relationship_kwargs=dict(
|
20
19
|
lazy="selectin", cascade="all, delete-orphan"
|
@@ -22,17 +21,17 @@ class TaskGroupV2(SQLModel, table=True):
|
|
22
21
|
)
|
23
22
|
|
24
23
|
user_id: int = Field(foreign_key="user_oauth.id")
|
25
|
-
user_group_id:
|
24
|
+
user_group_id: int | None = Field(
|
26
25
|
foreign_key="usergroup.id", default=None, ondelete="SET NULL"
|
27
26
|
)
|
28
27
|
|
29
28
|
origin: str
|
30
29
|
pkg_name: str
|
31
|
-
version:
|
32
|
-
python_version:
|
33
|
-
path:
|
34
|
-
wheel_path:
|
35
|
-
pip_extras:
|
30
|
+
version: str | None = None
|
31
|
+
python_version: str | None = None
|
32
|
+
path: str | None = None
|
33
|
+
wheel_path: str | None = None
|
34
|
+
pip_extras: str | None = None
|
36
35
|
pinned_package_versions: dict[str, str] = Field(
|
37
36
|
sa_column=Column(
|
38
37
|
JSON,
|
@@ -41,10 +40,10 @@ class TaskGroupV2(SQLModel, table=True):
|
|
41
40
|
nullable=True,
|
42
41
|
),
|
43
42
|
)
|
44
|
-
pip_freeze:
|
45
|
-
venv_path:
|
46
|
-
venv_size_in_kB:
|
47
|
-
venv_file_number:
|
43
|
+
pip_freeze: str | None = None
|
44
|
+
venv_path: str | None = None
|
45
|
+
venv_size_in_kB: int | None = None
|
46
|
+
venv_file_number: int | None = None
|
48
47
|
|
49
48
|
active: bool = True
|
50
49
|
timestamp_created: datetime = Field(
|
@@ -97,9 +96,9 @@ class TaskGroupV2(SQLModel, table=True):
|
|
97
96
|
|
98
97
|
class TaskGroupActivityV2(SQLModel, table=True):
|
99
98
|
|
100
|
-
id:
|
99
|
+
id: int | None = Field(default=None, primary_key=True)
|
101
100
|
user_id: int = Field(foreign_key="user_oauth.id")
|
102
|
-
taskgroupv2_id:
|
101
|
+
taskgroupv2_id: int | None = Field(
|
103
102
|
default=None, foreign_key="taskgroupv2.id", ondelete="SET NULL"
|
104
103
|
)
|
105
104
|
timestamp_started: datetime = Field(
|
@@ -110,8 +109,8 @@ class TaskGroupActivityV2(SQLModel, table=True):
|
|
110
109
|
version: str
|
111
110
|
status: str
|
112
111
|
action: str
|
113
|
-
log:
|
114
|
-
timestamp_ended:
|
112
|
+
log: str | None = None
|
113
|
+
timestamp_ended: datetime | None = Field(
|
115
114
|
default=None,
|
116
115
|
sa_column=Column(DateTime(timezone=True)),
|
117
116
|
)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from sqlalchemy import Column
|
5
4
|
from sqlalchemy.ext.orderinglist import ordering_list
|
@@ -14,7 +13,7 @@ from .workflowtask import WorkflowTaskV2
|
|
14
13
|
|
15
14
|
class WorkflowV2(SQLModel, table=True):
|
16
15
|
|
17
|
-
id:
|
16
|
+
id: int | None = Field(default=None, primary_key=True)
|
18
17
|
name: str
|
19
18
|
project_id: int = Field(foreign_key="projectv2.id", ondelete="CASCADE")
|
20
19
|
project: "ProjectV2" = Relationship( # noqa: F821
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from typing import Any
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from pydantic import ConfigDict
|
5
4
|
from sqlalchemy import Column
|
@@ -14,20 +13,20 @@ from .task import TaskV2
|
|
14
13
|
class WorkflowTaskV2(SQLModel, table=True):
|
15
14
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
16
15
|
|
17
|
-
id:
|
16
|
+
id: int | None = Field(default=None, primary_key=True)
|
18
17
|
|
19
18
|
workflow_id: int = Field(foreign_key="workflowv2.id", ondelete="CASCADE")
|
20
|
-
order:
|
21
|
-
meta_parallel:
|
19
|
+
order: int | None = None
|
20
|
+
meta_parallel: dict[str, Any] | None = Field(
|
22
21
|
sa_column=Column(JSON), default=None
|
23
22
|
)
|
24
|
-
meta_non_parallel:
|
23
|
+
meta_non_parallel: dict[str, Any] | None = Field(
|
25
24
|
sa_column=Column(JSON), default=None
|
26
25
|
)
|
27
|
-
args_parallel:
|
26
|
+
args_parallel: dict[str, Any] | None = Field(
|
28
27
|
sa_column=Column(JSON), default=None
|
29
28
|
)
|
30
|
-
args_non_parallel:
|
29
|
+
args_non_parallel: dict[str, Any] | None = Field(
|
31
30
|
sa_column=Column(JSON), default=None
|
32
31
|
)
|
33
32
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from itertools import chain
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from fastapi import APIRouter
|
5
4
|
from fastapi import Depends
|
@@ -22,9 +21,9 @@ from fractal_server.app.schemas.v2 import AccountingRecordRead
|
|
22
21
|
|
23
22
|
|
24
23
|
class AccountingQuery(BaseModel):
|
25
|
-
user_id:
|
26
|
-
timestamp_min:
|
27
|
-
timestamp_max:
|
24
|
+
user_id: int | None = None
|
25
|
+
timestamp_min: AwareDatetime | None = None
|
26
|
+
timestamp_max: AwareDatetime | None = None
|
28
27
|
|
29
28
|
|
30
29
|
router = APIRouter()
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from pathlib import Path
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from fastapi import APIRouter
|
5
4
|
from fastapi import Depends
|
@@ -30,16 +29,16 @@ router = APIRouter()
|
|
30
29
|
|
31
30
|
@router.get("/", response_model=list[JobReadV2])
|
32
31
|
async def view_job(
|
33
|
-
id:
|
34
|
-
user_id:
|
35
|
-
project_id:
|
36
|
-
dataset_id:
|
37
|
-
workflow_id:
|
38
|
-
status:
|
39
|
-
start_timestamp_min:
|
40
|
-
start_timestamp_max:
|
41
|
-
end_timestamp_min:
|
42
|
-
end_timestamp_max:
|
32
|
+
id: int | None = None,
|
33
|
+
user_id: int | None = None,
|
34
|
+
project_id: int | None = None,
|
35
|
+
dataset_id: int | None = None,
|
36
|
+
workflow_id: int | None = None,
|
37
|
+
status: JobStatusTypeV2 | None = None,
|
38
|
+
start_timestamp_min: AwareDatetime | None = None,
|
39
|
+
start_timestamp_max: AwareDatetime | None = None,
|
40
|
+
end_timestamp_min: AwareDatetime | None = None,
|
41
|
+
end_timestamp_max: AwareDatetime | None = None,
|
43
42
|
log: bool = True,
|
44
43
|
user: UserOAuth = Depends(current_active_superuser),
|
45
44
|
db: AsyncSession = Depends(get_async_db),
|
@@ -123,7 +122,7 @@ async def view_single_job(
|
|
123
122
|
|
124
123
|
if show_tmp_logs and (job.status == JobStatusTypeV2.SUBMITTED):
|
125
124
|
try:
|
126
|
-
with open(f"{job.working_dir}/{WORKFLOW_LOG_FILENAME}"
|
125
|
+
with open(f"{job.working_dir}/{WORKFLOW_LOG_FILENAME}") as f:
|
127
126
|
job.log = f.read()
|
128
127
|
except FileNotFoundError:
|
129
128
|
pass
|
@@ -137,7 +136,7 @@ async def update_job(
|
|
137
136
|
job_id: int,
|
138
137
|
user: UserOAuth = Depends(current_active_superuser),
|
139
138
|
db: AsyncSession = Depends(get_async_db),
|
140
|
-
) ->
|
139
|
+
) -> JobReadV2 | None:
|
141
140
|
"""
|
142
141
|
Change the status of an existing job.
|
143
142
|
|
@@ -154,7 +153,7 @@ async def update_job(
|
|
154
153
|
if job_update.status != JobStatusTypeV2.FAILED:
|
155
154
|
raise HTTPException(
|
156
155
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
157
|
-
detail=f"Cannot set job status to {job_update.status
|
156
|
+
detail=f"Cannot set job status to {job_update.status}",
|
158
157
|
)
|
159
158
|
|
160
159
|
setattr(job, "status", job_update.status)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from fastapi import APIRouter
|
4
2
|
from fastapi import Depends
|
5
3
|
from sqlmodel import select
|
@@ -16,8 +14,8 @@ router = APIRouter()
|
|
16
14
|
|
17
15
|
@router.get("/", response_model=list[ProjectReadV2])
|
18
16
|
async def view_project(
|
19
|
-
id:
|
20
|
-
user_id:
|
17
|
+
id: int | None = None,
|
18
|
+
user_id: int | None = None,
|
21
19
|
user: UserOAuth = Depends(current_active_superuser),
|
22
20
|
db: AsyncSession = Depends(get_async_db),
|
23
21
|
) -> list[ProjectReadV2]:
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from fastapi import APIRouter
|
4
2
|
from fastapi import Depends
|
5
3
|
from fastapi import HTTPException
|
@@ -27,10 +25,10 @@ class TaskV2Minimal(BaseModel):
|
|
27
25
|
name: str
|
28
26
|
type: str
|
29
27
|
taskgroupv2_id: int
|
30
|
-
command_non_parallel:
|
31
|
-
command_parallel:
|
32
|
-
source:
|
33
|
-
version:
|
28
|
+
command_non_parallel: str | None = None
|
29
|
+
command_parallel: str | None = None
|
30
|
+
source: str | None = None
|
31
|
+
version: str | None = None
|
34
32
|
|
35
33
|
|
36
34
|
class ProjectUser(BaseModel):
|
@@ -56,14 +54,14 @@ class TaskV2Info(BaseModel):
|
|
56
54
|
|
57
55
|
@router.get("/", response_model=list[TaskV2Info])
|
58
56
|
async def query_tasks(
|
59
|
-
id:
|
60
|
-
source:
|
61
|
-
version:
|
62
|
-
name:
|
57
|
+
id: int | None = None,
|
58
|
+
source: str | None = None,
|
59
|
+
version: str | None = None,
|
60
|
+
name: str | None = None,
|
63
61
|
max_number_of_results: int = 25,
|
64
|
-
category:
|
65
|
-
modality:
|
66
|
-
author:
|
62
|
+
category: str | None = None,
|
63
|
+
modality: str | None = None,
|
64
|
+
author: str | None = None,
|
67
65
|
user: UserOAuth = Depends(current_active_superuser),
|
68
66
|
db: AsyncSession = Depends(get_async_db),
|
69
67
|
) -> list[TaskV2Info]:
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from fastapi import APIRouter
|
4
2
|
from fastapi import Depends
|
5
3
|
from fastapi import HTTPException
|
@@ -35,13 +33,13 @@ logger = set_logger(__name__)
|
|
35
33
|
|
36
34
|
@router.get("/activity/", response_model=list[TaskGroupActivityV2Read])
|
37
35
|
async def get_task_group_activity_list(
|
38
|
-
task_group_activity_id:
|
39
|
-
user_id:
|
40
|
-
taskgroupv2_id:
|
41
|
-
pkg_name:
|
42
|
-
status:
|
43
|
-
action:
|
44
|
-
timestamp_started_min:
|
36
|
+
task_group_activity_id: int | None = None,
|
37
|
+
user_id: int | None = None,
|
38
|
+
taskgroupv2_id: int | None = None,
|
39
|
+
pkg_name: str | None = None,
|
40
|
+
status: TaskGroupActivityStatusV2 | None = None,
|
41
|
+
action: TaskGroupActivityActionV2 | None = None,
|
42
|
+
timestamp_started_min: AwareDatetime | None = None,
|
45
43
|
superuser: UserOAuth = Depends(current_active_superuser),
|
46
44
|
db: AsyncSession = Depends(get_async_db),
|
47
45
|
) -> list[TaskGroupActivityV2Read]:
|
@@ -87,14 +85,14 @@ async def query_task_group(
|
|
87
85
|
|
88
86
|
@router.get("/", response_model=list[TaskGroupReadV2])
|
89
87
|
async def query_task_group_list(
|
90
|
-
user_id:
|
91
|
-
user_group_id:
|
92
|
-
private:
|
93
|
-
active:
|
94
|
-
pkg_name:
|
95
|
-
origin:
|
96
|
-
timestamp_last_used_min:
|
97
|
-
timestamp_last_used_max:
|
88
|
+
user_id: int | None = None,
|
89
|
+
user_group_id: int | None = None,
|
90
|
+
private: bool | None = None,
|
91
|
+
active: bool | None = None,
|
92
|
+
pkg_name: str | None = None,
|
93
|
+
origin: TaskGroupV2OriginEnum | None = None,
|
94
|
+
timestamp_last_used_min: AwareDatetime | None = None,
|
95
|
+
timestamp_last_used_max: AwareDatetime | None = None,
|
98
96
|
user: UserOAuth = Depends(current_active_superuser),
|
99
97
|
db: AsyncSession = Depends(get_async_db),
|
100
98
|
) -> list[TaskGroupReadV2]:
|