fractal-server 2.0.0a11__py3-none-any.whl → 2.0.0a12__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/__init__.py +5 -2
- fractal_server/app/models/v1/state.py +1 -1
- fractal_server/app/models/v2/workflowtask.py +0 -39
- fractal_server/app/routes/admin/v1.py +5 -5
- fractal_server/app/routes/api/v1/_aux_functions.py +6 -6
- fractal_server/app/routes/api/v1/dataset.py +4 -4
- fractal_server/app/routes/api/v1/project.py +4 -4
- fractal_server/app/routes/api/v1/task.py +2 -2
- fractal_server/app/routes/api/v1/task_collection.py +3 -3
- fractal_server/app/routes/api/v1/workflow.py +4 -4
- fractal_server/app/routes/api/v1/workflowtask.py +1 -1
- fractal_server/app/routes/api/v2/dataset.py +10 -0
- fractal_server/app/routes/api/v2/job.py +1 -1
- fractal_server/app/routes/api/v2/project.py +5 -17
- fractal_server/app/routes/api/v2/submit.py +1 -1
- fractal_server/app/routes/api/v2/task_collection.py +2 -2
- fractal_server/app/routes/aux/_job.py +1 -1
- fractal_server/app/runner/task_files.py +1 -1
- fractal_server/app/runner/v1/__init__.py +4 -4
- fractal_server/app/runner/v1/_common.py +2 -2
- fractal_server/app/runner/v1/_local/__init__.py +3 -3
- fractal_server/app/runner/v2/runner.py +62 -25
- fractal_server/app/runner/v2/runner_functions.py +36 -10
- fractal_server/app/runner/v2/runner_functions_low_level.py +6 -13
- fractal_server/app/runner/v2/task_interface.py +4 -2
- fractal_server/app/schemas/__init__.py +0 -3
- fractal_server/app/schemas/v1/__init__.py +0 -6
- fractal_server/app/schemas/v2/__init__.py +2 -0
- fractal_server/app/schemas/v2/dataset.py +5 -0
- fractal_server/app/schemas/v2/workflowtask.py +60 -14
- fractal_server/images/tools.py +0 -1
- fractal_server/tasks/v1/background_operations.py +2 -2
- {fractal_server-2.0.0a11.dist-info → fractal_server-2.0.0a12.dist-info}/METADATA +1 -1
- {fractal_server-2.0.0a11.dist-info → fractal_server-2.0.0a12.dist-info}/RECORD +38 -38
- {fractal_server-2.0.0a11.dist-info → fractal_server-2.0.0a12.dist-info}/LICENSE +0 -0
- {fractal_server-2.0.0a11.dist-info → fractal_server-2.0.0a12.dist-info}/WHEEL +0 -0
- {fractal_server-2.0.0a11.dist-info → fractal_server-2.0.0a12.dist-info}/entry_points.txt +0 -0
fractal_server/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "2.0.
|
1
|
+
__VERSION__ = "2.0.0a12"
|
@@ -2,5 +2,8 @@
|
|
2
2
|
`models` module
|
3
3
|
"""
|
4
4
|
from .security import * # noqa: F401, F403
|
5
|
-
from .v1 import
|
6
|
-
from .v2 import
|
5
|
+
from .v1 import Project # noqa: F401
|
6
|
+
from .v2 import ProjectV2 # noqa: F401
|
7
|
+
|
8
|
+
# We include the project models to avoid issues with LinkUserProject
|
9
|
+
# (sometimes taking place in alembic autogenerate)
|
@@ -2,7 +2,6 @@ from typing import Any
|
|
2
2
|
from typing import Literal
|
3
3
|
from typing import Optional
|
4
4
|
|
5
|
-
from pydantic import validator
|
6
5
|
from sqlalchemy import Column
|
7
6
|
from sqlalchemy.types import JSON
|
8
7
|
from sqlmodel import Field
|
@@ -48,41 +47,3 @@ class WorkflowTaskV2(SQLModel, table=True):
|
|
48
47
|
task_legacy: Optional[Task] = Relationship(
|
49
48
|
sa_relationship_kwargs=dict(lazy="selectin")
|
50
49
|
)
|
51
|
-
|
52
|
-
@validator("args_non_parallel")
|
53
|
-
def validate_args_non_parallel(cls, value):
|
54
|
-
if value is None:
|
55
|
-
return
|
56
|
-
forbidden_args_keys = {
|
57
|
-
"zarr_dir",
|
58
|
-
"zarr_url",
|
59
|
-
"zarr_urls",
|
60
|
-
"init_args",
|
61
|
-
}
|
62
|
-
args_keys = set(value.keys())
|
63
|
-
intersect_keys = forbidden_args_keys.intersection(args_keys)
|
64
|
-
if intersect_keys:
|
65
|
-
raise ValueError(
|
66
|
-
"`args` contains the following forbidden keys: "
|
67
|
-
f"{intersect_keys}"
|
68
|
-
)
|
69
|
-
return value
|
70
|
-
|
71
|
-
@validator("args_parallel")
|
72
|
-
def validate_args_parallel(cls, value):
|
73
|
-
if value is None:
|
74
|
-
return
|
75
|
-
forbidden_args_keys = {
|
76
|
-
"zarr_dir",
|
77
|
-
"zarr_url",
|
78
|
-
"zarr_urls",
|
79
|
-
"init_args",
|
80
|
-
}
|
81
|
-
args_keys = set(value.keys())
|
82
|
-
intersect_keys = forbidden_args_keys.intersection(args_keys)
|
83
|
-
if intersect_keys:
|
84
|
-
raise ValueError(
|
85
|
-
"`args` contains the following forbidden keys: "
|
86
|
-
f"{intersect_keys}"
|
87
|
-
)
|
88
|
-
return value
|
@@ -20,12 +20,12 @@ from ....syringe import Inject
|
|
20
20
|
from ....utils import get_timestamp
|
21
21
|
from ...db import AsyncSession
|
22
22
|
from ...db import get_async_db
|
23
|
-
from ...models import ApplyWorkflow
|
24
|
-
from ...models import Dataset
|
25
|
-
from ...models import JobStatusTypeV1
|
26
|
-
from ...models import Project
|
27
|
-
from ...models import Workflow
|
28
23
|
from ...models.security import UserOAuth as User
|
24
|
+
from ...models.v1 import ApplyWorkflow
|
25
|
+
from ...models.v1 import Dataset
|
26
|
+
from ...models.v1 import JobStatusTypeV1
|
27
|
+
from ...models.v1 import Project
|
28
|
+
from ...models.v1 import Workflow
|
29
29
|
from ...runner.filenames import WORKFLOW_LOG_FILENAME
|
30
30
|
from ...schemas.v1 import ApplyWorkflowReadV1
|
31
31
|
from ...schemas.v1 import ApplyWorkflowUpdateV1
|
@@ -12,13 +12,13 @@ from sqlmodel import select
|
|
12
12
|
from sqlmodel.sql.expression import SelectOfScalar
|
13
13
|
|
14
14
|
from ....db import AsyncSession
|
15
|
-
from ....models import ApplyWorkflow
|
16
|
-
from ....models import Dataset
|
17
15
|
from ....models import LinkUserProject
|
18
|
-
from ....models import
|
19
|
-
from ....models import
|
20
|
-
from ....models import
|
21
|
-
from ....models import
|
16
|
+
from ....models.v1 import ApplyWorkflow
|
17
|
+
from ....models.v1 import Dataset
|
18
|
+
from ....models.v1 import Project
|
19
|
+
from ....models.v1 import Task
|
20
|
+
from ....models.v1 import Workflow
|
21
|
+
from ....models.v1 import WorkflowTask
|
22
22
|
from ....schemas.v1 import JobStatusTypeV1
|
23
23
|
from ....security import User
|
24
24
|
|
@@ -13,10 +13,10 @@ from sqlmodel import select
|
|
13
13
|
|
14
14
|
from ....db import AsyncSession
|
15
15
|
from ....db import get_async_db
|
16
|
-
from ....models import ApplyWorkflow
|
17
|
-
from ....models import Dataset
|
18
|
-
from ....models import Project
|
19
|
-
from ....models import Resource
|
16
|
+
from ....models.v1 import ApplyWorkflow
|
17
|
+
from ....models.v1 import Dataset
|
18
|
+
from ....models.v1 import Project
|
19
|
+
from ....models.v1 import Resource
|
20
20
|
from ....runner.filenames import HISTORY_FILENAME
|
21
21
|
from ....schemas.v1 import DatasetCreateV1
|
22
22
|
from ....schemas.v1 import DatasetReadV1
|
@@ -18,11 +18,11 @@ from .....logger import set_logger
|
|
18
18
|
from .....syringe import Inject
|
19
19
|
from ....db import AsyncSession
|
20
20
|
from ....db import get_async_db
|
21
|
-
from ....models import ApplyWorkflow
|
22
|
-
from ....models import Dataset
|
23
21
|
from ....models import LinkUserProject
|
24
|
-
from ....models import
|
25
|
-
from ....models import
|
22
|
+
from ....models.v1 import ApplyWorkflow
|
23
|
+
from ....models.v1 import Dataset
|
24
|
+
from ....models.v1 import Project
|
25
|
+
from ....models.v1 import Workflow
|
26
26
|
from ....runner.set_start_and_last_task_index import (
|
27
27
|
set_start_and_last_task_index,
|
28
28
|
)
|
@@ -11,8 +11,8 @@ from sqlmodel import select
|
|
11
11
|
from .....logger import set_logger
|
12
12
|
from ....db import AsyncSession
|
13
13
|
from ....db import get_async_db
|
14
|
-
from ....models import Task
|
15
|
-
from ....models import WorkflowTask
|
14
|
+
from ....models.v1 import Task
|
15
|
+
from ....models.v1 import WorkflowTask
|
16
16
|
from ....models.v2 import TaskV2
|
17
17
|
from ....schemas.v1 import TaskCreateV1
|
18
18
|
from ....schemas.v1 import TaskReadV1
|
@@ -17,9 +17,9 @@ from .....logger import set_logger
|
|
17
17
|
from .....syringe import Inject
|
18
18
|
from ....db import AsyncSession
|
19
19
|
from ....db import get_async_db
|
20
|
-
from ....models import State
|
21
|
-
from ....models import Task
|
22
|
-
from ....schemas.
|
20
|
+
from ....models.v1 import State
|
21
|
+
from ....models.v1 import Task
|
22
|
+
from ....schemas.state import StateRead
|
23
23
|
from ....schemas.v1 import TaskCollectPipV1
|
24
24
|
from ....schemas.v1 import TaskCollectStatusV1
|
25
25
|
from ....security import current_active_user
|
@@ -23,10 +23,10 @@ from .....logger import close_logger
|
|
23
23
|
from .....logger import set_logger
|
24
24
|
from ....db import AsyncSession
|
25
25
|
from ....db import get_async_db
|
26
|
-
from ....models import ApplyWorkflow
|
27
|
-
from ....models import Project
|
28
|
-
from ....models import Task
|
29
|
-
from ....models import Workflow
|
26
|
+
from ....models.v1 import ApplyWorkflow
|
27
|
+
from ....models.v1 import Project
|
28
|
+
from ....models.v1 import Task
|
29
|
+
from ....models.v1 import Workflow
|
30
30
|
from ....schemas.v1 import WorkflowCreateV1
|
31
31
|
from ....schemas.v1 import WorkflowExportV1
|
32
32
|
from ....schemas.v1 import WorkflowImportV1
|
@@ -22,7 +22,7 @@ from fastapi import status
|
|
22
22
|
|
23
23
|
from ....db import AsyncSession
|
24
24
|
from ....db import get_async_db
|
25
|
-
from ....models import Task
|
25
|
+
from ....models.v1 import Task
|
26
26
|
from ....schemas.v1 import WorkflowTaskCreateV1
|
27
27
|
from ....schemas.v1 import WorkflowTaskReadV1
|
28
28
|
from ....schemas.v1 import WorkflowTaskUpdateV1
|
@@ -270,6 +270,16 @@ async def import_dataset(
|
|
270
270
|
db=db,
|
271
271
|
)
|
272
272
|
|
273
|
+
for image in dataset.images:
|
274
|
+
if not image.zarr_url.startswith(dataset.zarr_dir):
|
275
|
+
raise HTTPException(
|
276
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
277
|
+
detail=(
|
278
|
+
f"Cannot import dataset: zarr_url {image.zarr_url} is not "
|
279
|
+
f"relative to zarr_dir={dataset.zarr_dir}."
|
280
|
+
),
|
281
|
+
)
|
282
|
+
|
273
283
|
# Create new Dataset
|
274
284
|
db_dataset = DatasetV2(
|
275
285
|
project_id=project_id,
|
@@ -12,7 +12,7 @@ from ....db import AsyncSession
|
|
12
12
|
from ....db import get_async_db
|
13
13
|
from ....models.v2 import JobV2
|
14
14
|
from ....models.v2 import ProjectV2
|
15
|
-
from ....runner.filenames import WORKFLOW_LOG_FILENAME
|
15
|
+
from ....runner.filenames import WORKFLOW_LOG_FILENAME
|
16
16
|
from ....schemas.v2 import JobReadV2
|
17
17
|
from ....schemas.v2 import JobStatusTypeV2
|
18
18
|
from ....security import current_active_user
|
@@ -5,11 +5,8 @@ from fastapi import Depends
|
|
5
5
|
from fastapi import HTTPException
|
6
6
|
from fastapi import Response
|
7
7
|
from fastapi import status
|
8
|
-
from sqlalchemy.exc import IntegrityError
|
9
8
|
from sqlmodel import select
|
10
9
|
|
11
|
-
from .....logger import close_logger
|
12
|
-
from .....logger import set_logger
|
13
10
|
from ....db import AsyncSession
|
14
11
|
from ....db import get_async_db
|
15
12
|
from ....models.v2 import DatasetV2
|
@@ -65,20 +62,11 @@ async def create_project(
|
|
65
62
|
|
66
63
|
db_project = ProjectV2(**project.dict())
|
67
64
|
db_project.user_list.append(user)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
except IntegrityError as e:
|
74
|
-
await db.rollback()
|
75
|
-
logger = set_logger("create_project")
|
76
|
-
logger.error(str(e))
|
77
|
-
close_logger(logger)
|
78
|
-
raise HTTPException(
|
79
|
-
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
80
|
-
detail=str(e),
|
81
|
-
)
|
65
|
+
|
66
|
+
db.add(db_project)
|
67
|
+
await db.commit()
|
68
|
+
await db.refresh(db_project)
|
69
|
+
await db.close()
|
82
70
|
|
83
71
|
return db_project
|
84
72
|
|
@@ -17,7 +17,7 @@ from ....db import get_async_db
|
|
17
17
|
from ....models.v2 import JobV2
|
18
18
|
from ....runner.set_start_and_last_task_index import (
|
19
19
|
set_start_and_last_task_index,
|
20
|
-
)
|
20
|
+
)
|
21
21
|
from ....runner.v2 import submit_workflow
|
22
22
|
from ....schemas.v2 import JobCreateV2
|
23
23
|
from ....schemas.v2 import JobReadV2
|
@@ -17,9 +17,9 @@ from .....logger import set_logger
|
|
17
17
|
from .....syringe import Inject
|
18
18
|
from ....db import AsyncSession
|
19
19
|
from ....db import get_async_db
|
20
|
-
from ....models import CollectionStateV2
|
20
|
+
from ....models.v2 import CollectionStateV2
|
21
21
|
from ....models.v2 import TaskV2
|
22
|
-
from ....schemas import StateRead
|
22
|
+
from ....schemas.state import StateRead
|
23
23
|
from ....schemas.v2 import TaskCollectPipV2
|
24
24
|
from ....schemas.v2 import TaskCollectStatusV2
|
25
25
|
from ....security import current_active_user
|
@@ -26,10 +26,10 @@ from ....logger import set_logger
|
|
26
26
|
from ....syringe import Inject
|
27
27
|
from ....utils import get_timestamp
|
28
28
|
from ...db import DB
|
29
|
-
from ...models import ApplyWorkflow
|
30
|
-
from ...models import Dataset
|
31
|
-
from ...models import Workflow
|
32
|
-
from ...models import WorkflowTask
|
29
|
+
from ...models.v1 import ApplyWorkflow
|
30
|
+
from ...models.v1 import Dataset
|
31
|
+
from ...models.v1 import Workflow
|
32
|
+
from ...models.v1 import WorkflowTask
|
33
33
|
from ...schemas.v1 import JobStatusTypeV1
|
34
34
|
from ..exceptions import JobExecutionError
|
35
35
|
from ..exceptions import TaskExecutionError
|
@@ -21,8 +21,8 @@ from typing import Optional
|
|
21
21
|
from ....config import get_settings
|
22
22
|
from ....logger import get_logger
|
23
23
|
from ....syringe import Inject
|
24
|
-
from ...models import Task
|
25
|
-
from ...models import WorkflowTask
|
24
|
+
from ...models.v1 import Task
|
25
|
+
from ...models.v1 import WorkflowTask
|
26
26
|
from ...schemas.v1 import WorkflowTaskStatusTypeV1
|
27
27
|
from ..exceptions import JobExecutionError
|
28
28
|
from ..exceptions import TaskExecutionError
|
@@ -23,11 +23,11 @@ from pathlib import Path
|
|
23
23
|
from typing import Any
|
24
24
|
from typing import Optional
|
25
25
|
|
26
|
-
from ....models import Workflow
|
26
|
+
from ....models.v1 import Workflow
|
27
27
|
from ...async_wrap import async_wrap
|
28
28
|
from ...set_start_and_last_task_index import set_start_and_last_task_index
|
29
|
-
from .._common import execute_tasks
|
30
|
-
from ..common import TaskParameters
|
29
|
+
from .._common import execute_tasks
|
30
|
+
from ..common import TaskParameters
|
31
31
|
from ._submit_setup import _local_submit_setup
|
32
32
|
from .executor import FractalThreadPoolExecutor
|
33
33
|
|
@@ -12,6 +12,7 @@ from ....images import SingleImage
|
|
12
12
|
from ....images.tools import filter_image_list
|
13
13
|
from ....images.tools import find_image_by_zarr_url
|
14
14
|
from ....images.tools import match_filter
|
15
|
+
from ..exceptions import JobExecutionError
|
15
16
|
from ..filenames import FILTERS_FILENAME
|
16
17
|
from ..filenames import HISTORY_FILENAME
|
17
18
|
from ..filenames import IMAGES_FILENAME
|
@@ -20,13 +21,12 @@ from .runner_functions import run_v1_task_parallel
|
|
20
21
|
from .runner_functions import run_v2_task_compound
|
21
22
|
from .runner_functions import run_v2_task_non_parallel
|
22
23
|
from .runner_functions import run_v2_task_parallel
|
24
|
+
from .task_interface import TaskOutput
|
23
25
|
from fractal_server.app.models.v2 import DatasetV2
|
24
26
|
from fractal_server.app.models.v2 import WorkflowTaskV2
|
25
27
|
from fractal_server.app.schemas.v2.dataset import _DatasetHistoryItemV2
|
26
28
|
from fractal_server.app.schemas.v2.workflowtask import WorkflowTaskStatusTypeV2
|
27
29
|
|
28
|
-
# FIXME: define RESERVED_ARGUMENTS = [", ...]
|
29
|
-
|
30
30
|
|
31
31
|
def execute_tasks_v2(
|
32
32
|
wf_task_list: list[WorkflowTaskV2],
|
@@ -52,8 +52,15 @@ def execute_tasks_v2(
|
|
52
52
|
for wftask in wf_task_list:
|
53
53
|
task = wftask.task
|
54
54
|
task_legacy = wftask.task_legacy
|
55
|
-
|
56
|
-
|
55
|
+
if wftask.is_legacy_task:
|
56
|
+
task_name = task_legacy.name
|
57
|
+
logger.debug(
|
58
|
+
f"SUBMIT {wftask.order}-th task "
|
59
|
+
f'(legacy, name="{task_name}")'
|
60
|
+
)
|
61
|
+
else:
|
62
|
+
task_name = task.name
|
63
|
+
logger.debug(f'SUBMIT {wftask.order}-th task (name="{task_name}")')
|
57
64
|
|
58
65
|
# PRE TASK EXECUTION
|
59
66
|
|
@@ -72,9 +79,11 @@ def execute_tasks_v2(
|
|
72
79
|
if not wftask.is_legacy_task:
|
73
80
|
for image in filtered_images:
|
74
81
|
if not match_filter(image, Filters(types=task.input_types)):
|
75
|
-
raise
|
76
|
-
|
77
|
-
f"
|
82
|
+
raise JobExecutionError(
|
83
|
+
"Invalid filtered image list\n"
|
84
|
+
f"Task input types: {task.input_types=}\n"
|
85
|
+
f'Image zarr_url: {image["zarr_url"]}\n'
|
86
|
+
f'Image types: {image["types"]}\n'
|
78
87
|
)
|
79
88
|
|
80
89
|
# TASK EXECUTION (V2)
|
@@ -115,7 +124,7 @@ def execute_tasks_v2(
|
|
115
124
|
submit_setup_call=submit_setup_call,
|
116
125
|
)
|
117
126
|
else:
|
118
|
-
raise ValueError(f"Invalid {task.type=}.")
|
127
|
+
raise ValueError(f"Unexpected error: Invalid {task.type=}.")
|
119
128
|
# TASK EXECUTION (V1)
|
120
129
|
else:
|
121
130
|
current_task_output = run_v1_task_parallel(
|
@@ -131,21 +140,36 @@ def execute_tasks_v2(
|
|
131
140
|
|
132
141
|
# POST TASK EXECUTION
|
133
142
|
|
143
|
+
# If `current_task_output` includes no images (to be created, edited or
|
144
|
+
# removed), then flag all the input images as modified. See
|
145
|
+
# fractal-server issue #1374.
|
146
|
+
if (
|
147
|
+
current_task_output.image_list_updates == []
|
148
|
+
and current_task_output.image_list_removals == []
|
149
|
+
):
|
150
|
+
current_task_output = TaskOutput(
|
151
|
+
**current_task_output.dict(exclude={"image_list_updates"}),
|
152
|
+
image_list_updates=[
|
153
|
+
dict(zarr_url=img["zarr_url"]) for img in filtered_images
|
154
|
+
],
|
155
|
+
)
|
156
|
+
|
134
157
|
# Update image list
|
135
158
|
current_task_output.check_zarr_urls_are_unique()
|
136
159
|
for image_obj in current_task_output.image_list_updates:
|
137
160
|
image = image_obj.dict()
|
138
161
|
# Edit existing image
|
139
|
-
|
140
|
-
|
141
|
-
]:
|
162
|
+
tmp_image_paths = [img["zarr_url"] for img in tmp_images]
|
163
|
+
if image["zarr_url"] in tmp_image_paths:
|
142
164
|
if (
|
143
165
|
image["origin"] is not None
|
144
166
|
and image["origin"] != image["zarr_url"]
|
145
167
|
):
|
146
|
-
raise
|
147
|
-
|
148
|
-
|
168
|
+
raise JobExecutionError(
|
169
|
+
"Cannot edit an image with zarr_url different from "
|
170
|
+
"origin.\n"
|
171
|
+
f"zarr_url={image['zarr_url']}\n"
|
172
|
+
f"origin={image['origin']}"
|
149
173
|
)
|
150
174
|
img_search = find_image_by_zarr_url(
|
151
175
|
images=tmp_images,
|
@@ -153,6 +177,7 @@ def execute_tasks_v2(
|
|
153
177
|
)
|
154
178
|
if img_search is None:
|
155
179
|
raise ValueError(
|
180
|
+
"Unexpected error: "
|
156
181
|
f"Image with zarr_url {image['zarr_url']} not found, "
|
157
182
|
"while updating image list."
|
158
183
|
)
|
@@ -188,14 +213,19 @@ def execute_tasks_v2(
|
|
188
213
|
else:
|
189
214
|
# Check that image['zarr_url'] is relative to zarr_dir
|
190
215
|
if not image["zarr_url"].startswith(zarr_dir):
|
191
|
-
raise
|
192
|
-
|
193
|
-
|
216
|
+
raise JobExecutionError(
|
217
|
+
"Cannot create image if zarr_dir is not a parent "
|
218
|
+
"directory of zarr_url.\n"
|
219
|
+
f"zarr_dir: {zarr_dir}\n"
|
220
|
+
f"zarr_url: {image['zarr_url']}"
|
194
221
|
)
|
195
222
|
# Check that image['zarr_url'] is not equal to zarr_dir
|
196
223
|
if image["zarr_url"] == zarr_dir:
|
197
|
-
raise
|
198
|
-
"image
|
224
|
+
raise JobExecutionError(
|
225
|
+
"Cannot create image if zarr_url is equal to "
|
226
|
+
"zarr_dir.\n"
|
227
|
+
f"zarr_dir: {zarr_dir}\n"
|
228
|
+
f"zarr_url: {image['zarr_url']}"
|
199
229
|
)
|
200
230
|
# Propagate attributes and types from `origin` (if any)
|
201
231
|
updated_attributes = {}
|
@@ -236,8 +266,8 @@ def execute_tasks_v2(
|
|
236
266
|
images=tmp_images, zarr_url=img_zarr_url
|
237
267
|
)
|
238
268
|
if img_search is None:
|
239
|
-
raise
|
240
|
-
f"Cannot remove missing image
|
269
|
+
raise JobExecutionError(
|
270
|
+
f"Cannot remove missing image (zarr_url={img_zarr_url})."
|
241
271
|
)
|
242
272
|
else:
|
243
273
|
tmp_images.pop(img_search["index"])
|
@@ -249,24 +279,31 @@ def execute_tasks_v2(
|
|
249
279
|
current_task_output.filters.attributes
|
250
280
|
)
|
251
281
|
|
252
|
-
#
|
282
|
+
# Find manifest ouptut types
|
253
283
|
if wftask.is_legacy_task:
|
254
284
|
types_from_manifest = {}
|
255
285
|
else:
|
256
286
|
types_from_manifest = task.output_types
|
287
|
+
|
288
|
+
# Find task-output types
|
257
289
|
if current_task_output.filters is not None:
|
258
290
|
types_from_task = current_task_output.filters.types
|
259
291
|
else:
|
260
292
|
types_from_task = {}
|
293
|
+
|
261
294
|
# Check that key sets are disjoint
|
262
295
|
set_types_from_manifest = set(types_from_manifest.keys())
|
263
296
|
set_types_from_task = set(types_from_task.keys())
|
264
297
|
if not set_types_from_manifest.isdisjoint(set_types_from_task):
|
265
298
|
overlap = set_types_from_manifest.intersection(set_types_from_task)
|
266
|
-
raise
|
267
|
-
"
|
268
|
-
f"
|
299
|
+
raise JobExecutionError(
|
300
|
+
"Some type filters are being set twice, "
|
301
|
+
f"for task '{task_name}'.\n"
|
302
|
+
f"Types from task output: {types_from_task}\n"
|
303
|
+
f"Types from task maniest: {types_from_manifest}\n"
|
304
|
+
f"Overlapping keys: {overlap}"
|
269
305
|
)
|
306
|
+
|
270
307
|
# Update filters.types
|
271
308
|
tmp_filters["types"].update(types_from_manifest)
|
272
309
|
tmp_filters["types"].update(types_from_task)
|
@@ -8,6 +8,9 @@ from typing import Callable
|
|
8
8
|
from typing import Literal
|
9
9
|
from typing import Optional
|
10
10
|
|
11
|
+
from pydantic import ValidationError
|
12
|
+
|
13
|
+
from ..exceptions import JobExecutionError
|
11
14
|
from .deduplicate_list import deduplicate_list
|
12
15
|
from .merge_outputs import merge_outputs
|
13
16
|
from .runner_functions_low_level import run_single_task
|
@@ -31,6 +34,34 @@ __all__ = [
|
|
31
34
|
MAX_PARALLELIZATION_LIST_SIZE = 20_000
|
32
35
|
|
33
36
|
|
37
|
+
def _cast_and_validate_TaskOutput(
|
38
|
+
task_output: dict[str, Any]
|
39
|
+
) -> Optional[TaskOutput]:
|
40
|
+
try:
|
41
|
+
validated_task_output = TaskOutput(**task_output)
|
42
|
+
return validated_task_output
|
43
|
+
except ValidationError as e:
|
44
|
+
raise JobExecutionError(
|
45
|
+
"Validation of task output failed.\n"
|
46
|
+
f"Original error: {str(e)}\n"
|
47
|
+
f"Original data: {task_output}."
|
48
|
+
)
|
49
|
+
|
50
|
+
|
51
|
+
def _cast_and_validate_InitTaskOutput(
|
52
|
+
init_task_output: dict[str, Any],
|
53
|
+
) -> Optional[InitTaskOutput]:
|
54
|
+
try:
|
55
|
+
validated_init_task_output = InitTaskOutput(**init_task_output)
|
56
|
+
return validated_init_task_output
|
57
|
+
except ValidationError as e:
|
58
|
+
raise JobExecutionError(
|
59
|
+
"Validation of init-task output failed.\n"
|
60
|
+
f"Original error: {str(e)}\n"
|
61
|
+
f"Original data: {init_task_output}."
|
62
|
+
)
|
63
|
+
|
64
|
+
|
34
65
|
def no_op_submit_setup_call(
|
35
66
|
*,
|
36
67
|
wftask: WorkflowTaskV2,
|
@@ -71,7 +102,7 @@ def _get_executor_options(
|
|
71
102
|
|
72
103
|
def _check_parallelization_list_size(my_list):
|
73
104
|
if len(my_list) > MAX_PARALLELIZATION_LIST_SIZE:
|
74
|
-
raise
|
105
|
+
raise JobExecutionError(
|
75
106
|
"Too many parallelization items.\n"
|
76
107
|
f" {len(my_list)}\n"
|
77
108
|
f" {MAX_PARALLELIZATION_LIST_SIZE=}\n"
|
@@ -126,12 +157,10 @@ def run_v2_task_non_parallel(
|
|
126
157
|
**executor_options,
|
127
158
|
)
|
128
159
|
output = future.result()
|
129
|
-
# FIXME V2: handle validation errors
|
130
160
|
if output is None:
|
131
161
|
return TaskOutput()
|
132
162
|
else:
|
133
|
-
|
134
|
-
return validated_output
|
163
|
+
return _cast_and_validate_TaskOutput(output)
|
135
164
|
|
136
165
|
|
137
166
|
def run_v2_task_parallel(
|
@@ -188,9 +217,7 @@ def run_v2_task_parallel(
|
|
188
217
|
if output is None:
|
189
218
|
outputs[ind] = TaskOutput()
|
190
219
|
else:
|
191
|
-
|
192
|
-
validated_output = TaskOutput(**output)
|
193
|
-
outputs[ind] = validated_output
|
220
|
+
outputs[ind] = _cast_and_validate_TaskOutput(output)
|
194
221
|
|
195
222
|
merged_output = merge_outputs(outputs)
|
196
223
|
return merged_output
|
@@ -245,7 +272,7 @@ def run_v2_task_compound(
|
|
245
272
|
if output is None:
|
246
273
|
init_task_output = InitTaskOutput()
|
247
274
|
else:
|
248
|
-
init_task_output =
|
275
|
+
init_task_output = _cast_and_validate_InitTaskOutput(output)
|
249
276
|
parallelization_list = init_task_output.parallelization_list
|
250
277
|
parallelization_list = deduplicate_list(parallelization_list)
|
251
278
|
|
@@ -285,8 +312,7 @@ def run_v2_task_compound(
|
|
285
312
|
if output is None:
|
286
313
|
outputs[ind] = TaskOutput()
|
287
314
|
else:
|
288
|
-
|
289
|
-
validated_output = TaskOutput(**output)
|
315
|
+
validated_output = _cast_and_validate_TaskOutput(output)
|
290
316
|
outputs[ind] = validated_output
|
291
317
|
|
292
318
|
merged_output = merge_outputs(outputs)
|
@@ -76,19 +76,12 @@ def run_single_task(
|
|
76
76
|
workflow_dir_user = workflow_dir
|
77
77
|
|
78
78
|
component = args.pop(_COMPONENT_KEY_, None)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
else:
|
86
|
-
task_files = get_task_file_paths(
|
87
|
-
workflow_dir=workflow_dir,
|
88
|
-
workflow_dir_user=workflow_dir_user,
|
89
|
-
task_order=wftask.order,
|
90
|
-
component=component,
|
91
|
-
)
|
79
|
+
task_files = get_task_file_paths(
|
80
|
+
workflow_dir=workflow_dir,
|
81
|
+
workflow_dir_user=workflow_dir_user,
|
82
|
+
task_order=wftask.order,
|
83
|
+
component=component,
|
84
|
+
)
|
92
85
|
|
93
86
|
# Write arguments to args.json file
|
94
87
|
with task_files.args.open("w") as f:
|
@@ -29,8 +29,10 @@ class TaskOutput(BaseModel):
|
|
29
29
|
if zarr_urls.count(zarr_url) > 1
|
30
30
|
]
|
31
31
|
msg = (
|
32
|
-
"TaskOutput
|
33
|
-
"
|
32
|
+
"TaskOutput "
|
33
|
+
f"({len(self.image_list_updates)} image_list_updates and "
|
34
|
+
f"{len(self.image_list_removals)} image_list_removals) "
|
35
|
+
"has non-unique zarr_urls:"
|
34
36
|
)
|
35
37
|
for duplicate in duplicates:
|
36
38
|
msg = f"{msg}\n{duplicate}"
|
@@ -1,12 +1,6 @@
|
|
1
1
|
"""
|
2
2
|
Schemas for API request/response bodies
|
3
3
|
"""
|
4
|
-
from ..state import _StateBase # noqa: F401
|
5
|
-
from ..state import StateRead # noqa: F401
|
6
|
-
from ..user import UserCreate # noqa: F401
|
7
|
-
from ..user import UserRead # noqa: F401
|
8
|
-
from ..user import UserUpdate # noqa: F401
|
9
|
-
from ..user import UserUpdateStrict # noqa: F401
|
10
4
|
from .applyworkflow import ApplyWorkflowCreateV1 # noqa: F401
|
11
5
|
from .applyworkflow import ApplyWorkflowReadV1 # noqa: F401
|
12
6
|
from .applyworkflow import ApplyWorkflowUpdateV1 # noqa: F401
|
@@ -1,4 +1,6 @@
|
|
1
1
|
from .dataset import DatasetCreateV2 # noqa F401
|
2
|
+
from .dataset import DatasetExportV2 # noqa F401
|
3
|
+
from .dataset import DatasetImportV2 # noqa F401
|
2
4
|
from .dataset import DatasetReadV2 # noqa F401
|
3
5
|
from .dataset import DatasetUpdateV2 # noqa F401
|
4
6
|
from .dumps import DatasetDumpV2 # noqa F401
|
@@ -103,6 +103,11 @@ class DatasetImportV2(BaseModel):
|
|
103
103
|
images: list[SingleImage] = Field(default_factory=[])
|
104
104
|
filters: Filters = Field(default_factory=Filters)
|
105
105
|
|
106
|
+
# Validators
|
107
|
+
@validator("zarr_dir")
|
108
|
+
def normalize_zarr_dir(cls, v: str) -> str:
|
109
|
+
return normalize_url(v)
|
110
|
+
|
106
111
|
|
107
112
|
class DatasetExportV2(BaseModel):
|
108
113
|
"""
|
@@ -12,12 +12,14 @@ from .._validators import valdictkeys
|
|
12
12
|
from .._validators import valint
|
13
13
|
from ..v1.task import TaskExportV1
|
14
14
|
from ..v1.task import TaskImportV1
|
15
|
-
from ..v1.task import TaskReadV1
|
16
15
|
from .task import TaskExportV2
|
17
16
|
from .task import TaskImportV2
|
17
|
+
from .task import TaskLegacyReadV2
|
18
18
|
from .task import TaskReadV2
|
19
19
|
from fractal_server.images import Filters
|
20
20
|
|
21
|
+
RESERVED_ARGUMENTS = {"zarr_dir", "zarr_url", "zarr_urls", "init_args"}
|
22
|
+
|
21
23
|
|
22
24
|
class WorkflowTaskStatusTypeV2(str, Enum):
|
23
25
|
"""
|
@@ -56,14 +58,36 @@ class WorkflowTaskCreateV2(BaseModel, extra=Extra.forbid):
|
|
56
58
|
_meta_parallel = validator("meta_parallel", allow_reuse=True)(
|
57
59
|
valdictkeys("meta_parallel")
|
58
60
|
)
|
59
|
-
_args_non_parallel = validator("args_non_parallel", allow_reuse=True)(
|
60
|
-
valdictkeys("args_non_parallel")
|
61
|
-
)
|
62
|
-
_args_parallel = validator("args_parallel", allow_reuse=True)(
|
63
|
-
valdictkeys("args_parallel")
|
64
|
-
)
|
65
61
|
_order = validator("order", allow_reuse=True)(valint("order", min_val=0))
|
66
62
|
|
63
|
+
@validator("args_non_parallel")
|
64
|
+
def validate_args_non_parallel(cls, value):
|
65
|
+
if value is None:
|
66
|
+
return
|
67
|
+
valdictkeys("args_non_parallel")(value)
|
68
|
+
args_keys = set(value.keys())
|
69
|
+
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
70
|
+
if intersect_keys:
|
71
|
+
raise ValueError(
|
72
|
+
"`args` contains the following forbidden keys: "
|
73
|
+
f"{intersect_keys}"
|
74
|
+
)
|
75
|
+
return value
|
76
|
+
|
77
|
+
@validator("args_parallel")
|
78
|
+
def validate_args_parallel(cls, value):
|
79
|
+
if value is None:
|
80
|
+
return
|
81
|
+
valdictkeys("args_parallel")(value)
|
82
|
+
args_keys = set(value.keys())
|
83
|
+
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
84
|
+
if intersect_keys:
|
85
|
+
raise ValueError(
|
86
|
+
"`args` contains the following forbidden keys: "
|
87
|
+
f"{intersect_keys}"
|
88
|
+
)
|
89
|
+
return value
|
90
|
+
|
67
91
|
@root_validator
|
68
92
|
def validate_legacy_task(cls, values):
|
69
93
|
if values["is_legacy_task"] and (
|
@@ -96,7 +120,7 @@ class WorkflowTaskReadV2(BaseModel):
|
|
96
120
|
task_id: Optional[int]
|
97
121
|
task: Optional[TaskReadV2]
|
98
122
|
task_legacy_id: Optional[int]
|
99
|
-
task_legacy: Optional[
|
123
|
+
task_legacy: Optional[TaskLegacyReadV2]
|
100
124
|
|
101
125
|
|
102
126
|
class WorkflowTaskUpdateV2(BaseModel):
|
@@ -114,12 +138,34 @@ class WorkflowTaskUpdateV2(BaseModel):
|
|
114
138
|
_meta_parallel = validator("meta_parallel", allow_reuse=True)(
|
115
139
|
valdictkeys("meta_parallel")
|
116
140
|
)
|
117
|
-
|
118
|
-
|
119
|
-
)
|
120
|
-
|
121
|
-
|
122
|
-
|
141
|
+
|
142
|
+
@validator("args_non_parallel")
|
143
|
+
def validate_args_non_parallel(cls, value):
|
144
|
+
if value is None:
|
145
|
+
return
|
146
|
+
valdictkeys("args_non_parallel")(value)
|
147
|
+
args_keys = set(value.keys())
|
148
|
+
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
149
|
+
if intersect_keys:
|
150
|
+
raise ValueError(
|
151
|
+
"`args` contains the following forbidden keys: "
|
152
|
+
f"{intersect_keys}"
|
153
|
+
)
|
154
|
+
return value
|
155
|
+
|
156
|
+
@validator("args_parallel")
|
157
|
+
def validate_args_parallel(cls, value):
|
158
|
+
if value is None:
|
159
|
+
return
|
160
|
+
valdictkeys("args_parallel")(value)
|
161
|
+
args_keys = set(value.keys())
|
162
|
+
intersect_keys = RESERVED_ARGUMENTS.intersection(args_keys)
|
163
|
+
if intersect_keys:
|
164
|
+
raise ValueError(
|
165
|
+
"`args` contains the following forbidden keys: "
|
166
|
+
f"{intersect_keys}"
|
167
|
+
)
|
168
|
+
return value
|
123
169
|
|
124
170
|
|
125
171
|
class WorkflowTaskImportV2(BaseModel):
|
fractal_server/images/tools.py
CHANGED
@@ -15,8 +15,8 @@ from ..utils import slugify_task_name
|
|
15
15
|
from ._TaskCollectPip import _TaskCollectPip
|
16
16
|
from fractal_server.app.db import DBSyncSession
|
17
17
|
from fractal_server.app.db import get_sync_db
|
18
|
-
from fractal_server.app.models import State
|
19
|
-
from fractal_server.app.models import Task
|
18
|
+
from fractal_server.app.models.v1 import State
|
19
|
+
from fractal_server.app.models.v1 import Task
|
20
20
|
from fractal_server.app.schemas.v1 import TaskCollectStatusV1
|
21
21
|
from fractal_server.app.schemas.v1 import TaskCreateV1
|
22
22
|
from fractal_server.app.schemas.v1 import TaskReadV1
|
@@ -1,16 +1,16 @@
|
|
1
|
-
fractal_server/__init__.py,sha256=
|
1
|
+
fractal_server/__init__.py,sha256=n09kNau5UUJa9hzn0KtsMdH-0FpJzIry0v93FUKYRLg,25
|
2
2
|
fractal_server/__main__.py,sha256=CocbzZooX1UtGqPi55GcHGNxnrJXFg5tUU5b3wyFCyo,4958
|
3
3
|
fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
|
4
4
|
fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
fractal_server/app/db/__init__.py,sha256=WZEVfdJAX7ZyBM1ngfEGeqWWcjK_NygtCbawpmbwGpU,4042
|
6
|
-
fractal_server/app/models/__init__.py,sha256=
|
6
|
+
fractal_server/app/models/__init__.py,sha256=FRRDJkx7LgPaUqSp8IV7qevu_VE2dt0-fQtQruHFaVo,267
|
7
7
|
fractal_server/app/models/linkuserproject.py,sha256=eQaourbGRshvlMVlKzLYJKHEjfsW1CbWws9yW4eHXhA,567
|
8
8
|
fractal_server/app/models/security.py,sha256=UG9wCVA5GRSyHrYEFhH8lIF1hXykxsr9LSi8_dFToMY,3378
|
9
9
|
fractal_server/app/models/v1/__init__.py,sha256=qUlUGnWFaIm3aBXfUuLdhcW9f_s1VzAEuypr31zvHGo,458
|
10
10
|
fractal_server/app/models/v1/dataset.py,sha256=99GDgt7njx8yYQApkImqp_7bHA5HH3ElvbR6Oyj9kVI,2017
|
11
11
|
fractal_server/app/models/v1/job.py,sha256=QLGXcWdVRHaUHQNDapYYlLpEfw4K7QyD8TmcwhrWw2o,3304
|
12
12
|
fractal_server/app/models/v1/project.py,sha256=sDmAFLOBK5o4dLrwsIN681JcT5J1rzoUNTV9QVqwnA8,859
|
13
|
-
fractal_server/app/models/v1/state.py,sha256=
|
13
|
+
fractal_server/app/models/v1/state.py,sha256=ew7xw3iPzBwUnPlzmsOEMiPbPEMsJn_TyZ5cK93jBRQ,1095
|
14
14
|
fractal_server/app/models/v1/task.py,sha256=3xZqNeFYUqslh8ddMSXF2nO4nIiOD8T5Ij37wY20kss,2782
|
15
15
|
fractal_server/app/models/v1/workflow.py,sha256=dnY5eMaOe3oZv8arn00RNX9qVkBtTLG-vYdWXcQuyo4,3950
|
16
16
|
fractal_server/app/models/v2/__init__.py,sha256=uLzdInqATSwi0bS_V4vKB-TqFrOFaXuxCAbU73c0f24,473
|
@@ -20,37 +20,37 @@ fractal_server/app/models/v2/job.py,sha256=ypJmN-qspkKBGhBG7Mt-HypSQqcQ2EmB4Bzzb
|
|
20
20
|
fractal_server/app/models/v2/project.py,sha256=CqDEKzdVxmFDMee6DnVOyX7WGmdn-dQSLSekzw_OLUc,817
|
21
21
|
fractal_server/app/models/v2/task.py,sha256=9ZPhug3VWyeqgT8wQ9_8ZXQ2crSiiicRipxrxTslOso,3257
|
22
22
|
fractal_server/app/models/v2/workflow.py,sha256=YBgFGCziUgU0aJ5EM3Svu9W2c46AewZO9VBlFCHiSps,1069
|
23
|
-
fractal_server/app/models/v2/workflowtask.py,sha256=
|
23
|
+
fractal_server/app/models/v2/workflowtask.py,sha256=3jEkObsSnlI05Pur_dSsXYdJxRqPL60Z7tK5-EJLOks,1532
|
24
24
|
fractal_server/app/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
25
|
fractal_server/app/routes/admin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
|
-
fractal_server/app/routes/admin/v1.py,sha256=
|
26
|
+
fractal_server/app/routes/admin/v1.py,sha256=uMupmRkicaoWazX8qSX5fgh00O3MbuSfim8QayP6NkE,13996
|
27
27
|
fractal_server/app/routes/admin/v2.py,sha256=T8-bGAL25on-ntZx_Msz9j5jq6NGhkjVl1jp3eRJUbw,9830
|
28
28
|
fractal_server/app/routes/api/__init__.py,sha256=EVyZrEq3I_1643QGTPCC5lgCp4xH_auYbrFfogTm4pc,315
|
29
29
|
fractal_server/app/routes/api/v1/__init__.py,sha256=Y2HQdG197J0a7DyQEE2jn53IfxD0EHGhzK1I2JZuEck,958
|
30
|
-
fractal_server/app/routes/api/v1/_aux_functions.py,sha256=
|
31
|
-
fractal_server/app/routes/api/v1/dataset.py,sha256=
|
30
|
+
fractal_server/app/routes/api/v1/_aux_functions.py,sha256=KoSefKiBXximu0df4fJ3l9bKsGaLO8rb3z6xhD8PWj4,11973
|
31
|
+
fractal_server/app/routes/api/v1/dataset.py,sha256=HRE-8vPmVkeXf7WFYkI19mDtbY-iJZeJ7PmMiV0LMgY,16923
|
32
32
|
fractal_server/app/routes/api/v1/job.py,sha256=NwXyhvvzdPDor0ts8Im__9-I0P1H943s4NXIRgaz7PM,5436
|
33
|
-
fractal_server/app/routes/api/v1/project.py,sha256=
|
34
|
-
fractal_server/app/routes/api/v1/task.py,sha256=
|
35
|
-
fractal_server/app/routes/api/v1/task_collection.py,sha256=
|
36
|
-
fractal_server/app/routes/api/v1/workflow.py,sha256=
|
37
|
-
fractal_server/app/routes/api/v1/workflowtask.py,sha256=
|
33
|
+
fractal_server/app/routes/api/v1/project.py,sha256=4wlxcc-bR45bns6Yy0WyjA9Qv9eiMscATLZKjVhSd1k,15777
|
34
|
+
fractal_server/app/routes/api/v1/task.py,sha256=udbKnenzc-Q10elYCVB9JmOPWATraa9tZi0AaByvWo0,6129
|
35
|
+
fractal_server/app/routes/api/v1/task_collection.py,sha256=mFaYyCWtCPRqvs3j6zx_zaiDXn31Uzoa7UHZS-Lu_L0,8882
|
36
|
+
fractal_server/app/routes/api/v1/workflow.py,sha256=7r9IoIevg_rvYCrerMOsIsUabSOQatxdPCfLdkP0dRs,10942
|
37
|
+
fractal_server/app/routes/api/v1/workflowtask.py,sha256=qcHQlzlSFf_k8gtId-mA3tnyzgSR7i1m7pvR4R86blE,5582
|
38
38
|
fractal_server/app/routes/api/v2/__init__.py,sha256=UNgODxoEXfQpQDjvsnMvHaUWbZOrcHhEXNisLcU-0tE,1487
|
39
39
|
fractal_server/app/routes/api/v2/_aux_functions.py,sha256=IL1JKVqRcGfqiVbptDzpMKqi9QTYDYCCcsqIG0x0Nl8,14301
|
40
|
-
fractal_server/app/routes/api/v2/dataset.py,sha256=
|
40
|
+
fractal_server/app/routes/api/v2/dataset.py,sha256=_HjKNP9XsMGoqyubGdF2ZyeW7vXC3VdK_0_TaUxgIF0,8248
|
41
41
|
fractal_server/app/routes/api/v2/images.py,sha256=4r_HblPWyuKSZSJZfn8mbDaLv1ncwZU0gWdKneZcNG4,7894
|
42
|
-
fractal_server/app/routes/api/v2/job.py,sha256=
|
43
|
-
fractal_server/app/routes/api/v2/project.py,sha256=
|
42
|
+
fractal_server/app/routes/api/v2/job.py,sha256=BtaxErBDbLwjY2zgGD1I6eRpsffoMonifcS1CMEXmLU,5325
|
43
|
+
fractal_server/app/routes/api/v2/project.py,sha256=qyvizYZ4aUFgF3tGdfp4z8AwWgfo19N_KbFEljfUaC8,5594
|
44
44
|
fractal_server/app/routes/api/v2/status.py,sha256=3bqQejJ3TnIMan5wK6jr9sv4ypsQr9WWU8xqlvTgDCE,5739
|
45
|
-
fractal_server/app/routes/api/v2/submit.py,sha256=
|
45
|
+
fractal_server/app/routes/api/v2/submit.py,sha256=lbPTZKemoRjypcpExi-Yz9fIiPdv9OIjFeUu9yuILA4,6889
|
46
46
|
fractal_server/app/routes/api/v2/task.py,sha256=gJ0LruSk-Q1iMw8ZOX8C0wrZ4S4DGlQTr_5SdJJud0Q,7130
|
47
|
-
fractal_server/app/routes/api/v2/task_collection.py,sha256=
|
47
|
+
fractal_server/app/routes/api/v2/task_collection.py,sha256=wHkPkQKnvXEzidywuJqLe8QB_xjlHUqzPgsitXydNkU,8961
|
48
48
|
fractal_server/app/routes/api/v2/task_legacy.py,sha256=P_VJv9v0yzFUBuS-DQHhMVSOe20ecGJJcFBqiiFciOM,1628
|
49
49
|
fractal_server/app/routes/api/v2/workflow.py,sha256=sw-1phO_rrmDAcWX9Zqb9M8SfrWF78-02AuLB1-D1PU,11845
|
50
50
|
fractal_server/app/routes/api/v2/workflowtask.py,sha256=l4eTD5IIun5cOdYzsxh3ajmnOISaSccYA_mVf15Cjtw,8802
|
51
51
|
fractal_server/app/routes/auth.py,sha256=Xv80iqdyfY3lyicYs2Y8B6zEDEnyUu_H6_6psYtv3R4,4885
|
52
52
|
fractal_server/app/routes/aux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
|
-
fractal_server/app/routes/aux/_job.py,sha256=
|
53
|
+
fractal_server/app/routes/aux/_job.py,sha256=7OP3B_FqYJUQ8hVn-7G8oYEEaZrM4hxLF9FoSyjudTo,1251
|
54
54
|
fractal_server/app/routes/aux/_runner.py,sha256=psW6fsoo_VrAHrD5UQPbqFYikCp0m16VRymC-U1yUTk,675
|
55
55
|
fractal_server/app/runner/.gitignore,sha256=ytzN_oyHWXrGU7iFAtoHSTUbM6Rn6kG0Zkddg0xZk6s,16
|
56
56
|
fractal_server/app/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -68,10 +68,10 @@ fractal_server/app/runner/executors/slurm/executor.py,sha256=O9h6ZPAKM95BUJrZkHC
|
|
68
68
|
fractal_server/app/runner/executors/slurm/remote.py,sha256=wLziIsGdSMiO-jIXM8x77JRK82g_2hx0iBKTiMghuIo,5852
|
69
69
|
fractal_server/app/runner/filenames.py,sha256=9lwu3yB4C67yiijYw8XIKaLFn3mJUt6_TCyVFM_aZUQ,206
|
70
70
|
fractal_server/app/runner/set_start_and_last_task_index.py,sha256=-q4zVybAj8ek2XlbENKlfOAJ39hT_zoJoZkqzDqiAMY,1254
|
71
|
-
fractal_server/app/runner/task_files.py,sha256=
|
72
|
-
fractal_server/app/runner/v1/__init__.py,sha256=
|
73
|
-
fractal_server/app/runner/v1/_common.py,sha256=
|
74
|
-
fractal_server/app/runner/v1/_local/__init__.py,sha256=
|
71
|
+
fractal_server/app/runner/task_files.py,sha256=b5aRDi35QemBQnHT_AU6L_IPJJU_k_f5sJn-JXzkzy0,3180
|
72
|
+
fractal_server/app/runner/v1/__init__.py,sha256=Uqf9smd4G9JCunXOsJ0U_DJyhYvl8TwItY3TbDLBLMc,13620
|
73
|
+
fractal_server/app/runner/v1/_common.py,sha256=2-NScI-7qCIw14Od90so1onw-psIt8x1kx6EXq489Vk,21246
|
74
|
+
fractal_server/app/runner/v1/_local/__init__.py,sha256=ZcWftuGRLmN8-S6QZXm6FhNehsxwmwZRhuRv-a7zA6s,6839
|
75
75
|
fractal_server/app/runner/v1/_local/_local_config.py,sha256=hM7SPxR07luXPcXdrWXRpEB2uOyjSSRUdqW3QBKJn9c,3147
|
76
76
|
fractal_server/app/runner/v1/_local/_submit_setup.py,sha256=kvNPT7ey2mEamORzPMMVThbFHtzZcSr-0A9tYw9uVDA,1493
|
77
77
|
fractal_server/app/runner/v1/_local/executor.py,sha256=QrJlD77G6q4WohoJQO7XXbvi2RlCUsNvMnPDEZIoAqA,3620
|
@@ -91,16 +91,16 @@ fractal_server/app/runner/v2/_slurm/get_slurm_config.py,sha256=I_lOS75iGYyJ74-gN
|
|
91
91
|
fractal_server/app/runner/v2/deduplicate_list.py,sha256=-imwO7OB7ATADEnqVbTElUwoY0YIJCTf_SbWJNN9OZg,639
|
92
92
|
fractal_server/app/runner/v2/handle_failed_job.py,sha256=M1r3dnrbUMo_AI2qjaVuGhieMAyLh5gcvB10YOBpjvI,5415
|
93
93
|
fractal_server/app/runner/v2/merge_outputs.py,sha256=IHuHqbKmk97K35BFvTrKVBs60z3e_--OzXTnsvmA02c,1281
|
94
|
-
fractal_server/app/runner/v2/runner.py,sha256=
|
95
|
-
fractal_server/app/runner/v2/runner_functions.py,sha256=
|
96
|
-
fractal_server/app/runner/v2/runner_functions_low_level.py,sha256=
|
97
|
-
fractal_server/app/runner/v2/task_interface.py,sha256=
|
94
|
+
fractal_server/app/runner/v2/runner.py,sha256=pZDRYXibPs6lYz8hg-F7KbibR_cl0sjCa5s9yaFE_-s,14160
|
95
|
+
fractal_server/app/runner/v2/runner_functions.py,sha256=jwLfIL1gdmL-KqSKb-5CDG-g7rQYZdywn24bJ92R2qI,11067
|
96
|
+
fractal_server/app/runner/v2/runner_functions_low_level.py,sha256=nPxmoSTIAQRwEf8iwfCdwTq4Eo3eDAHcgGn3GejPgqk,3710
|
97
|
+
fractal_server/app/runner/v2/task_interface.py,sha256=myS-kT0DsJ8xIJZBVEzgD8g54VbiwL6i7Im3e1zcVHQ,1866
|
98
98
|
fractal_server/app/runner/v2/v1_compat.py,sha256=t0ficzAHUFaaeI56nqTb4YEKxfARF7L9Y6ijtJCwjP8,912
|
99
|
-
fractal_server/app/schemas/__init__.py,sha256=
|
99
|
+
fractal_server/app/schemas/__init__.py,sha256=jiIf54owztXupv3PO6Ilh0qcrkh2RUzKq4bcEFqEfc4,40
|
100
100
|
fractal_server/app/schemas/_validators.py,sha256=1dTOYr1IZykrxuQSV2-zuEMZbKe_nGwrfS7iUrsh-sE,3461
|
101
101
|
fractal_server/app/schemas/state.py,sha256=t4XM04aqxeluh8MfvD7LfEc-8-dOmUVluZHhLsfxxkc,692
|
102
102
|
fractal_server/app/schemas/user.py,sha256=rE8WgBz-ceVUs0Sz2ZwcjUrSTZTnS0ys5SBtD2XD9r8,3113
|
103
|
-
fractal_server/app/schemas/v1/__init__.py,sha256=
|
103
|
+
fractal_server/app/schemas/v1/__init__.py,sha256=terWiFLKJ0QU-y3PG3hXNYdpxGTffZTlwrwJ8LfQ3FM,1809
|
104
104
|
fractal_server/app/schemas/v1/applyworkflow.py,sha256=uuIh7fHlHEL4yLqL-dePI6-nfCsqgBYATmht7w_KITw,4302
|
105
105
|
fractal_server/app/schemas/v1/dataset.py,sha256=n71lNUO3JLy2K3IM9BZM2Fk1EnKQOTU7pm2s2rJ1FGY,3444
|
106
106
|
fractal_server/app/schemas/v1/dumps.py,sha256=67VXnyLh_0Ufo7rPM2jZ9P9rk0CnYcVAkilx_cLX6sg,1274
|
@@ -109,8 +109,8 @@ fractal_server/app/schemas/v1/project.py,sha256=TO2TjI4m9FO-A9IB9lUCld7E4Ld0k4Ma
|
|
109
109
|
fractal_server/app/schemas/v1/task.py,sha256=7BxOZ_qoRQ8n3YbQpDvB7VMcxB5fSYQmR5RLIWhuJ5U,3704
|
110
110
|
fractal_server/app/schemas/v1/task_collection.py,sha256=uvq9bcMaGD_qHsh7YtcpoSAkVAbw12eY4DocIO3MKOg,3057
|
111
111
|
fractal_server/app/schemas/v1/workflow.py,sha256=tuOs5E5Q_ozA8if7YPZ07cQjzqB_QMkBS4u92qo4Ro0,4618
|
112
|
-
fractal_server/app/schemas/v2/__init__.py,sha256=
|
113
|
-
fractal_server/app/schemas/v2/dataset.py,sha256=
|
112
|
+
fractal_server/app/schemas/v2/__init__.py,sha256=IssDWR6q_mgNkaAxfhSnEZZLZRZIqOsr9SM7RvN1IsY,1852
|
113
|
+
fractal_server/app/schemas/v2/dataset.py,sha256=dLT52tV4dSf2HrFNak4vdQEn8PT_04IUrGnd2z-AXIU,2599
|
114
114
|
fractal_server/app/schemas/v2/dumps.py,sha256=IpIT_2KxJd7qTgW2NllDknGeP7vBAJDfyz1I5p3TytU,2023
|
115
115
|
fractal_server/app/schemas/v2/job.py,sha256=zfF9K3v4jWUJ7M482ta2CkqUJ4tVT4XfVt60p9IRhP0,3250
|
116
116
|
fractal_server/app/schemas/v2/manifest.py,sha256=N37IWohcfO3_y2l8rVM0h_1nZq7m4Izxk9iL1vtwBJw,6243
|
@@ -119,13 +119,13 @@ fractal_server/app/schemas/v2/status.py,sha256=SQaUpQkjFq5c5k5J4rOjNhuQaDOEg8lks
|
|
119
119
|
fractal_server/app/schemas/v2/task.py,sha256=7IfxiZkaVqlARy7WYE_H8m7j_IEcuQaZORUrs6b5YuY,4672
|
120
120
|
fractal_server/app/schemas/v2/task_collection.py,sha256=sY29NQfJrbjiidmVkVjSIH-20wIsmh7G1QOdr05KoDQ,3171
|
121
121
|
fractal_server/app/schemas/v2/workflow.py,sha256=Zzx3e-qgkH8le0FUmAx9UrV5PWd7bj14PPXUh_zgZXM,1827
|
122
|
-
fractal_server/app/schemas/v2/workflowtask.py,sha256=
|
122
|
+
fractal_server/app/schemas/v2/workflowtask.py,sha256=atVuVN4aXsVEOmSd-vyg-8_8OnPmqx-gT75rXcn_AlQ,6552
|
123
123
|
fractal_server/app/security/__init__.py,sha256=wxosoHc3mJYPCdPMyWnRD8w_2OgnKYp2aDkdmwrZh5k,11203
|
124
124
|
fractal_server/config.py,sha256=CA8ASObADaME5chDiBXawAJZ3MvjTRpCKP0jvdYtSh8,15080
|
125
125
|
fractal_server/data_migrations/README.md,sha256=_3AEFvDg9YkybDqCLlFPdDmGJvr6Tw7HRI14aZ3LOIw,398
|
126
126
|
fractal_server/images/__init__.py,sha256=xO6jTLE4EZKO6cTDdJsBmK9cdeh9hFTaSbSuWgQg7y4,196
|
127
127
|
fractal_server/images/models.py,sha256=9ipU5h4N6ogBChoB-2vHoqtL0TXOHCv6kRR-fER3mkM,4167
|
128
|
-
fractal_server/images/tools.py,sha256=
|
128
|
+
fractal_server/images/tools.py,sha256=gxeniYy4Z-cp_ToK2LHPJUTVVUUrdpogYdcBUvBuLiY,2209
|
129
129
|
fractal_server/logger.py,sha256=95duXY8eSxf1HWg0CVn8SUGNzgJw9ZR0FlapDDF6WAY,3924
|
130
130
|
fractal_server/main.py,sha256=7CpwPfCsHxBAo5fWuXPCsYOFCpbBI0F7Z0jsgCQdou8,3001
|
131
131
|
fractal_server/migrations/README,sha256=4rQvyDfqodGhpJw74VYijRmgFP49ji5chyEemWGHsuw,59
|
@@ -154,7 +154,7 @@ fractal_server/tasks/endpoint_operations.py,sha256=D1WSJd8dIfIumKezon1NYX5a0QNPq
|
|
154
154
|
fractal_server/tasks/utils.py,sha256=R1_SKfXTwveT7CJJOrvkwi0vNpr9MBIiNh7qv8EK3Wc,3278
|
155
155
|
fractal_server/tasks/v1/_TaskCollectPip.py,sha256=16Gn8lVYHBuwNLBHdcdx0X8s9QXXsbfPwSzcCcM6fRg,3775
|
156
156
|
fractal_server/tasks/v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
157
|
-
fractal_server/tasks/v1/background_operations.py,sha256=
|
157
|
+
fractal_server/tasks/v1/background_operations.py,sha256=I-D4SaG56UMkoH7dNy5CzbEsAjySCPc7gQc-U14phKk,11731
|
158
158
|
fractal_server/tasks/v1/get_collection_data.py,sha256=bi9tuApLgoKZNMIG1kR4GoKI9S6Y040gFfNQapw4ikM,502
|
159
159
|
fractal_server/tasks/v2/_TaskCollectPip.py,sha256=QeCqXDgOnMjk3diVlC5bgGEywyQjYFm5637Rke49vJY,3775
|
160
160
|
fractal_server/tasks/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -162,8 +162,8 @@ fractal_server/tasks/v2/background_operations.py,sha256=fUukEA-zFjUDhxgI3oO_Bvy7
|
|
162
162
|
fractal_server/tasks/v2/get_collection_data.py,sha256=Qhf2T_aaqAfqu9_KpUSlXsS7EJoZQbEPEreHHa2jco8,502
|
163
163
|
fractal_server/urls.py,sha256=5o_qq7PzKKbwq12NHSQZDmDitn5RAOeQ4xufu-2v9Zk,448
|
164
164
|
fractal_server/utils.py,sha256=b7WwFdcFZ8unyT65mloFToYuEDXpQoHRcmRNqrhd_dQ,2115
|
165
|
-
fractal_server-2.0.
|
166
|
-
fractal_server-2.0.
|
167
|
-
fractal_server-2.0.
|
168
|
-
fractal_server-2.0.
|
169
|
-
fractal_server-2.0.
|
165
|
+
fractal_server-2.0.0a12.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
|
166
|
+
fractal_server-2.0.0a12.dist-info/METADATA,sha256=vBB1xO15zGGC1KMJRwj7xmVLHS0pF0BLTjVUusilAns,4201
|
167
|
+
fractal_server-2.0.0a12.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
168
|
+
fractal_server-2.0.0a12.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
|
169
|
+
fractal_server-2.0.0a12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|