fractal-server 2.17.1a1__py3-none-any.whl → 2.18.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fractal_server/__init__.py +1 -1
- fractal_server/__main__.py +21 -19
- fractal_server/app/db/__init__.py +3 -3
- fractal_server/app/models/__init__.py +1 -0
- fractal_server/app/models/linkuserproject.py +43 -1
- fractal_server/app/models/security.py +28 -8
- fractal_server/app/models/v2/__init__.py +3 -1
- fractal_server/app/models/v2/accounting.py +9 -1
- fractal_server/app/models/v2/dataset.py +5 -1
- fractal_server/app/models/v2/history.py +15 -1
- fractal_server/app/models/v2/job.py +17 -2
- fractal_server/app/models/v2/profile.py +29 -0
- fractal_server/app/models/v2/project.py +4 -10
- fractal_server/app/models/v2/resource.py +17 -0
- fractal_server/app/models/v2/task_group.py +4 -3
- fractal_server/app/models/v2/workflow.py +2 -1
- fractal_server/app/routes/admin/v2/__init__.py +12 -13
- fractal_server/app/routes/admin/v2/accounting.py +3 -3
- fractal_server/app/routes/admin/v2/job.py +35 -24
- fractal_server/app/routes/admin/v2/profile.py +3 -2
- fractal_server/app/routes/admin/v2/resource.py +5 -5
- fractal_server/app/routes/admin/v2/sharing.py +103 -0
- fractal_server/app/routes/admin/v2/task.py +37 -26
- fractal_server/app/routes/admin/v2/task_group.py +94 -17
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +21 -22
- fractal_server/app/routes/api/__init__.py +1 -9
- fractal_server/app/routes/api/v2/__init__.py +49 -50
- fractal_server/app/routes/api/v2/_aux_functions.py +132 -124
- fractal_server/app/routes/api/v2/_aux_functions_history.py +51 -23
- fractal_server/app/routes/api/v2/_aux_functions_sharing.py +97 -0
- fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +6 -8
- fractal_server/app/routes/api/v2/_aux_functions_tasks.py +7 -9
- fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +1 -2
- fractal_server/app/routes/api/v2/dataset.py +95 -102
- fractal_server/app/routes/api/v2/history.py +59 -33
- fractal_server/app/routes/api/v2/images.py +24 -9
- fractal_server/app/routes/api/v2/job.py +52 -33
- fractal_server/app/routes/api/v2/pre_submission_checks.py +16 -8
- fractal_server/app/routes/api/v2/project.py +65 -37
- fractal_server/app/routes/api/v2/sharing.py +311 -0
- fractal_server/app/routes/api/v2/status_legacy.py +31 -41
- fractal_server/app/routes/api/v2/submit.py +82 -78
- fractal_server/app/routes/api/v2/task.py +19 -20
- fractal_server/app/routes/api/v2/task_collection.py +41 -43
- fractal_server/app/routes/api/v2/task_collection_custom.py +19 -20
- fractal_server/app/routes/api/v2/task_collection_pixi.py +10 -11
- fractal_server/app/routes/api/v2/task_group.py +25 -24
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +32 -32
- fractal_server/app/routes/api/v2/task_version_update.py +23 -19
- fractal_server/app/routes/api/v2/workflow.py +50 -55
- fractal_server/app/routes/api/v2/workflow_import.py +37 -37
- fractal_server/app/routes/api/v2/workflowtask.py +32 -26
- fractal_server/app/routes/auth/__init__.py +1 -3
- fractal_server/app/routes/auth/_aux_auth.py +101 -2
- fractal_server/app/routes/auth/current_user.py +2 -66
- fractal_server/app/routes/auth/group.py +8 -35
- fractal_server/app/routes/auth/login.py +1 -0
- fractal_server/app/routes/auth/oauth.py +4 -3
- fractal_server/app/routes/auth/register.py +4 -2
- fractal_server/app/routes/auth/router.py +2 -0
- fractal_server/app/routes/auth/users.py +19 -10
- fractal_server/app/routes/auth/viewer_paths.py +43 -0
- fractal_server/app/routes/aux/_job.py +1 -1
- fractal_server/app/routes/aux/_runner.py +2 -2
- fractal_server/app/routes/pagination.py +1 -1
- fractal_server/app/schemas/user.py +29 -12
- fractal_server/app/schemas/user_group.py +0 -15
- fractal_server/app/schemas/v2/__init__.py +55 -48
- fractal_server/app/schemas/v2/accounting.py +11 -0
- fractal_server/app/schemas/v2/dataset.py +57 -11
- fractal_server/app/schemas/v2/dumps.py +10 -9
- fractal_server/app/schemas/v2/job.py +11 -11
- fractal_server/app/schemas/v2/manifest.py +4 -3
- fractal_server/app/schemas/v2/profile.py +53 -2
- fractal_server/app/schemas/v2/project.py +3 -3
- fractal_server/app/schemas/v2/resource.py +121 -16
- fractal_server/app/schemas/v2/sharing.py +99 -0
- fractal_server/app/schemas/v2/status_legacy.py +3 -3
- fractal_server/app/schemas/v2/task.py +6 -7
- fractal_server/app/schemas/v2/task_collection.py +5 -5
- fractal_server/app/schemas/v2/task_group.py +16 -16
- fractal_server/app/schemas/v2/workflow.py +16 -16
- fractal_server/app/schemas/v2/workflowtask.py +16 -15
- fractal_server/app/security/__init__.py +5 -8
- fractal_server/app/security/signup_email.py +4 -5
- fractal_server/app/shutdown.py +6 -6
- fractal_server/config/__init__.py +0 -6
- fractal_server/config/_data.py +0 -68
- fractal_server/config/_database.py +19 -20
- fractal_server/config/_email.py +30 -38
- fractal_server/config/_main.py +38 -52
- fractal_server/config/_oauth.py +17 -21
- fractal_server/data_migrations/2_18_0.py +30 -0
- fractal_server/exceptions.py +4 -0
- fractal_server/images/models.py +4 -5
- fractal_server/images/status_tools.py +4 -2
- fractal_server/logger.py +1 -1
- fractal_server/main.py +75 -13
- fractal_server/migrations/versions/034a469ec2eb_task_groups.py +4 -8
- fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +1 -1
- fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +1 -0
- fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +1 -1
- fractal_server/migrations/versions/1a83a5260664_rename.py +1 -1
- fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +1 -0
- fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +1 -1
- fractal_server/migrations/versions/40d6d6511b20_add_index_to_history_models.py +47 -0
- fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +1 -1
- fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +1 -0
- fractal_server/migrations/versions/49d0856e9569_drop_table.py +2 -3
- fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +1 -1
- fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +1 -1
- fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +2 -1
- fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +7 -19
- fractal_server/migrations/versions/5bf02391cfef_v2.py +4 -10
- fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +1 -0
- fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +1 -1
- fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +1 -1
- fractal_server/migrations/versions/7910eed4cf97_user_project_dirs_and_usergroup_viewer_.py +60 -0
- fractal_server/migrations/versions/791ce783d3d8_add_indices.py +1 -1
- fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +1 -0
- fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +1 -0
- fractal_server/migrations/versions/88270f589c9b_add_prevent_new_submissions.py +39 -0
- fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +2 -4
- fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +1 -1
- fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +1 -0
- fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +1 -1
- fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +1 -1
- fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +1 -1
- fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +2 -4
- fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +1 -1
- fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +1 -1
- fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +1 -1
- fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +1 -1
- fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +1 -0
- fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +1 -0
- fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +1 -1
- fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +1 -0
- fractal_server/migrations/versions/bc0e8b3327a7_project_sharing.py +72 -0
- fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +1 -1
- fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +1 -1
- fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +4 -9
- fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +1 -0
- fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +1 -1
- fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +1 -0
- fractal_server/migrations/versions/e0e717ae2f26_delete_linkuserproject_ondelete_project.py +50 -0
- fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +1 -0
- fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +1 -1
- fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +1 -0
- fractal_server/migrations/versions/f0702066b007_one_submitted_job_per_dataset.py +40 -0
- fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +1 -1
- fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +1 -0
- fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +4 -9
- fractal_server/runner/config/_local.py +8 -5
- fractal_server/runner/config/_slurm.py +39 -33
- fractal_server/runner/config/slurm_mem_to_MB.py +0 -1
- fractal_server/runner/executors/base_runner.py +29 -4
- fractal_server/runner/executors/local/get_local_config.py +1 -0
- fractal_server/runner/executors/local/runner.py +14 -13
- fractal_server/runner/executors/slurm_common/_batching.py +9 -20
- fractal_server/runner/executors/slurm_common/base_slurm_runner.py +53 -27
- fractal_server/runner/executors/slurm_common/get_slurm_config.py +14 -7
- fractal_server/runner/executors/slurm_common/remote.py +3 -1
- fractal_server/runner/executors/slurm_common/slurm_config.py +2 -0
- fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +1 -3
- fractal_server/runner/executors/slurm_ssh/runner.py +16 -11
- fractal_server/runner/executors/slurm_ssh/tar_commands.py +1 -0
- fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +1 -0
- fractal_server/runner/executors/slurm_sudo/runner.py +16 -11
- fractal_server/runner/task_files.py +9 -3
- fractal_server/runner/v2/_local.py +12 -6
- fractal_server/runner/v2/_slurm_ssh.py +14 -7
- fractal_server/runner/v2/_slurm_sudo.py +14 -7
- fractal_server/runner/v2/db_tools.py +0 -1
- fractal_server/runner/v2/deduplicate_list.py +2 -1
- fractal_server/runner/v2/runner.py +44 -28
- fractal_server/runner/v2/runner_functions.py +22 -28
- fractal_server/runner/v2/submit_workflow.py +29 -15
- fractal_server/ssh/_fabric.py +6 -13
- fractal_server/string_tools.py +0 -1
- fractal_server/syringe.py +1 -1
- fractal_server/tasks/config/_pixi.py +1 -1
- fractal_server/tasks/config/_python.py +16 -9
- fractal_server/tasks/utils.py +0 -1
- fractal_server/tasks/v2/local/_utils.py +3 -3
- fractal_server/tasks/v2/local/collect.py +15 -18
- fractal_server/tasks/v2/local/collect_pixi.py +14 -16
- fractal_server/tasks/v2/local/deactivate.py +14 -15
- fractal_server/tasks/v2/local/deactivate_pixi.py +7 -7
- fractal_server/tasks/v2/local/delete.py +6 -8
- fractal_server/tasks/v2/local/reactivate.py +12 -12
- fractal_server/tasks/v2/local/reactivate_pixi.py +12 -12
- fractal_server/tasks/v2/ssh/_utils.py +3 -3
- fractal_server/tasks/v2/ssh/collect.py +19 -24
- fractal_server/tasks/v2/ssh/collect_pixi.py +22 -24
- fractal_server/tasks/v2/ssh/deactivate.py +17 -15
- fractal_server/tasks/v2/ssh/deactivate_pixi.py +8 -7
- fractal_server/tasks/v2/ssh/delete.py +12 -10
- fractal_server/tasks/v2/ssh/reactivate.py +16 -16
- fractal_server/tasks/v2/ssh/reactivate_pixi.py +13 -14
- fractal_server/tasks/v2/templates/1_create_venv.sh +2 -0
- fractal_server/tasks/v2/templates/2_pip_install.sh +2 -0
- fractal_server/tasks/v2/templates/3_pip_freeze.sh +2 -0
- fractal_server/tasks/v2/templates/4_pip_show.sh +2 -0
- fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +3 -1
- fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +2 -0
- fractal_server/tasks/v2/templates/pixi_1_extract.sh +2 -0
- fractal_server/tasks/v2/templates/pixi_2_install.sh +2 -0
- fractal_server/tasks/v2/templates/pixi_3_post_install.sh +2 -0
- fractal_server/tasks/v2/utils_background.py +10 -10
- fractal_server/tasks/v2/utils_database.py +5 -5
- fractal_server/tasks/v2/utils_package_names.py +1 -2
- fractal_server/tasks/v2/utils_pixi.py +1 -3
- fractal_server/types/__init__.py +98 -1
- fractal_server/types/validators/__init__.py +3 -0
- fractal_server/types/validators/_common_validators.py +33 -3
- fractal_server/types/validators/_workflow_task_arguments_validators.py +1 -2
- fractal_server/utils.py +1 -0
- fractal_server/zip_tools.py +34 -0
- {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/METADATA +3 -2
- fractal_server-2.18.0.dist-info/RECORD +275 -0
- fractal_server/app/routes/admin/v2/project.py +0 -41
- fractal_server-2.17.1a1.dist-info/RECORD +0 -264
- {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/WHEEL +0 -0
- {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/entry_points.txt +0 -0
- {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,21 +12,21 @@ from sqlmodel import select
|
|
|
12
12
|
|
|
13
13
|
from fractal_server.app.db import AsyncSession
|
|
14
14
|
from fractal_server.app.db import get_async_db
|
|
15
|
+
from fractal_server.app.models import LinkUserProjectV2
|
|
15
16
|
from fractal_server.app.models import UserOAuth
|
|
16
17
|
from fractal_server.app.models.v2 import HistoryRun
|
|
17
18
|
from fractal_server.app.models.v2 import HistoryUnit
|
|
18
19
|
from fractal_server.app.models.v2 import JobV2
|
|
19
|
-
from fractal_server.app.models.v2 import ProjectV2
|
|
20
20
|
from fractal_server.app.routes.auth import current_superuser_act
|
|
21
21
|
from fractal_server.app.routes.aux._job import _write_shutdown_file
|
|
22
22
|
from fractal_server.app.routes.aux._runner import _check_shutdown_is_supported
|
|
23
|
-
from fractal_server.app.routes.pagination import get_pagination_params
|
|
24
23
|
from fractal_server.app.routes.pagination import PaginationRequest
|
|
25
24
|
from fractal_server.app.routes.pagination import PaginationResponse
|
|
25
|
+
from fractal_server.app.routes.pagination import get_pagination_params
|
|
26
26
|
from fractal_server.app.schemas.v2 import HistoryUnitStatus
|
|
27
|
-
from fractal_server.app.schemas.v2 import
|
|
28
|
-
from fractal_server.app.schemas.v2 import
|
|
29
|
-
from fractal_server.app.schemas.v2 import
|
|
27
|
+
from fractal_server.app.schemas.v2 import JobRead
|
|
28
|
+
from fractal_server.app.schemas.v2 import JobStatusType
|
|
29
|
+
from fractal_server.app.schemas.v2 import JobUpdate
|
|
30
30
|
from fractal_server.runner.filenames import WORKFLOW_LOG_FILENAME
|
|
31
31
|
from fractal_server.utils import get_timestamp
|
|
32
32
|
from fractal_server.zip_tools import _zip_folder_to_byte_stream_iterator
|
|
@@ -34,14 +34,14 @@ from fractal_server.zip_tools import _zip_folder_to_byte_stream_iterator
|
|
|
34
34
|
router = APIRouter()
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
@router.get("/", response_model=PaginationResponse[
|
|
37
|
+
@router.get("/", response_model=PaginationResponse[JobRead])
|
|
38
38
|
async def view_job(
|
|
39
39
|
id: int | None = None,
|
|
40
40
|
user_id: int | None = None,
|
|
41
41
|
project_id: int | None = None,
|
|
42
42
|
dataset_id: int | None = None,
|
|
43
43
|
workflow_id: int | None = None,
|
|
44
|
-
status:
|
|
44
|
+
status: JobStatusType | None = None,
|
|
45
45
|
start_timestamp_min: AwareDatetime | None = None,
|
|
46
46
|
start_timestamp_max: AwareDatetime | None = None,
|
|
47
47
|
end_timestamp_min: AwareDatetime | None = None,
|
|
@@ -50,12 +50,13 @@ async def view_job(
|
|
|
50
50
|
pagination: PaginationRequest = Depends(get_pagination_params),
|
|
51
51
|
user: UserOAuth = Depends(current_superuser_act),
|
|
52
52
|
db: AsyncSession = Depends(get_async_db),
|
|
53
|
-
) -> PaginationResponse[
|
|
53
|
+
) -> PaginationResponse[JobRead]:
|
|
54
54
|
"""
|
|
55
|
-
Query `
|
|
55
|
+
Query `JobV2` table.
|
|
56
56
|
|
|
57
57
|
Args:
|
|
58
58
|
id: If not `None`, select a given `applyworkflow.id`.
|
|
59
|
+
user_id:
|
|
59
60
|
project_id: If not `None`, select a given `applyworkflow.project_id`.
|
|
60
61
|
dataset_id: If not `None`, select a given
|
|
61
62
|
`applyworkflow.input_dataset_id`.
|
|
@@ -84,11 +85,21 @@ async def view_job(
|
|
|
84
85
|
stm = stm.where(JobV2.id == id)
|
|
85
86
|
stm_count = stm_count.where(JobV2.id == id)
|
|
86
87
|
if user_id is not None:
|
|
87
|
-
stm =
|
|
88
|
-
|
|
88
|
+
stm = (
|
|
89
|
+
stm.join(
|
|
90
|
+
LinkUserProjectV2,
|
|
91
|
+
LinkUserProjectV2.project_id == JobV2.project_id,
|
|
92
|
+
)
|
|
93
|
+
.where(LinkUserProjectV2.user_id == user_id)
|
|
94
|
+
.where(LinkUserProjectV2.is_owner.is_(True))
|
|
89
95
|
)
|
|
90
|
-
stm_count =
|
|
91
|
-
|
|
96
|
+
stm_count = (
|
|
97
|
+
stm_count.join(
|
|
98
|
+
LinkUserProjectV2,
|
|
99
|
+
LinkUserProjectV2.project_id == JobV2.project_id,
|
|
100
|
+
)
|
|
101
|
+
.where(LinkUserProjectV2.user_id == user_id)
|
|
102
|
+
.where(LinkUserProjectV2.is_owner.is_(True))
|
|
92
103
|
)
|
|
93
104
|
if project_id is not None:
|
|
94
105
|
stm = stm.where(JobV2.project_id == project_id)
|
|
@@ -135,21 +146,21 @@ async def view_job(
|
|
|
135
146
|
for job in job_list:
|
|
136
147
|
setattr(job, "log", None)
|
|
137
148
|
|
|
138
|
-
return
|
|
149
|
+
return dict(
|
|
139
150
|
total_count=total_count,
|
|
140
151
|
page_size=page_size,
|
|
141
152
|
current_page=page,
|
|
142
|
-
items=
|
|
153
|
+
items=job_list,
|
|
143
154
|
)
|
|
144
155
|
|
|
145
156
|
|
|
146
|
-
@router.get("/{job_id}/", response_model=
|
|
157
|
+
@router.get("/{job_id}/", response_model=JobRead)
|
|
147
158
|
async def view_single_job(
|
|
148
159
|
job_id: int,
|
|
149
160
|
show_tmp_logs: bool = False,
|
|
150
161
|
user: UserOAuth = Depends(current_superuser_act),
|
|
151
162
|
db: AsyncSession = Depends(get_async_db),
|
|
152
|
-
) ->
|
|
163
|
+
) -> JobRead:
|
|
153
164
|
job = await db.get(JobV2, job_id)
|
|
154
165
|
if not job:
|
|
155
166
|
raise HTTPException(
|
|
@@ -158,7 +169,7 @@ async def view_single_job(
|
|
|
158
169
|
)
|
|
159
170
|
await db.close()
|
|
160
171
|
|
|
161
|
-
if show_tmp_logs and (job.status ==
|
|
172
|
+
if show_tmp_logs and (job.status == JobStatusType.SUBMITTED):
|
|
162
173
|
try:
|
|
163
174
|
with open(f"{job.working_dir}/{WORKFLOW_LOG_FILENAME}") as f:
|
|
164
175
|
job.log = f.read()
|
|
@@ -168,13 +179,13 @@ async def view_single_job(
|
|
|
168
179
|
return job
|
|
169
180
|
|
|
170
181
|
|
|
171
|
-
@router.patch("/{job_id}/", response_model=
|
|
182
|
+
@router.patch("/{job_id}/", response_model=JobRead)
|
|
172
183
|
async def update_job(
|
|
173
|
-
job_update:
|
|
184
|
+
job_update: JobUpdate,
|
|
174
185
|
job_id: int,
|
|
175
186
|
user: UserOAuth = Depends(current_superuser_act),
|
|
176
187
|
db: AsyncSession = Depends(get_async_db),
|
|
177
|
-
) ->
|
|
188
|
+
) -> JobRead | None:
|
|
178
189
|
"""
|
|
179
190
|
Change the status of an existing job.
|
|
180
191
|
|
|
@@ -187,13 +198,13 @@ async def update_job(
|
|
|
187
198
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
188
199
|
detail=f"Job {job_id} not found",
|
|
189
200
|
)
|
|
190
|
-
if job.status !=
|
|
201
|
+
if job.status != JobStatusType.SUBMITTED:
|
|
191
202
|
raise HTTPException(
|
|
192
203
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
193
204
|
detail=f"Job {job_id} has status {job.status=} != 'submitted'.",
|
|
194
205
|
)
|
|
195
206
|
|
|
196
|
-
if job_update.status !=
|
|
207
|
+
if job_update.status != JobStatusType.FAILED:
|
|
197
208
|
raise HTTPException(
|
|
198
209
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
199
210
|
detail=f"Cannot set job status to {job_update.status}",
|
|
@@ -206,7 +217,7 @@ async def update_job(
|
|
|
206
217
|
job,
|
|
207
218
|
"log",
|
|
208
219
|
f"{job.log or ''}\nThis job was manually marked as "
|
|
209
|
-
f"'{
|
|
220
|
+
f"'{JobStatusType.FAILED}' by an admin ({timestamp.isoformat()}).",
|
|
210
221
|
)
|
|
211
222
|
|
|
212
223
|
res = await db.execute(
|
|
@@ -6,8 +6,6 @@ from fastapi import status
|
|
|
6
6
|
from sqlmodel import func
|
|
7
7
|
from sqlmodel import select
|
|
8
8
|
|
|
9
|
-
from ._aux_functions import _check_profile_name
|
|
10
|
-
from ._aux_functions import _get_profile_or_404
|
|
11
9
|
from fractal_server.app.db import AsyncSession
|
|
12
10
|
from fractal_server.app.db import get_async_db
|
|
13
11
|
from fractal_server.app.models import Profile
|
|
@@ -16,6 +14,9 @@ from fractal_server.app.routes.auth import current_superuser_act
|
|
|
16
14
|
from fractal_server.app.schemas.v2 import ProfileCreate
|
|
17
15
|
from fractal_server.app.schemas.v2 import ProfileRead
|
|
18
16
|
|
|
17
|
+
from ._aux_functions import _check_profile_name
|
|
18
|
+
from ._aux_functions import _get_profile_or_404
|
|
19
|
+
|
|
19
20
|
router = APIRouter()
|
|
20
21
|
|
|
21
22
|
|
|
@@ -6,9 +6,6 @@ from fastapi import status
|
|
|
6
6
|
from sqlalchemy.exc import IntegrityError
|
|
7
7
|
from sqlmodel import select
|
|
8
8
|
|
|
9
|
-
from ._aux_functions import _check_resource_name
|
|
10
|
-
from ._aux_functions import _get_resource_or_404
|
|
11
|
-
from .profile import _check_profile_name
|
|
12
9
|
from fractal_server.app.db import AsyncSession
|
|
13
10
|
from fractal_server.app.db import get_async_db
|
|
14
11
|
from fractal_server.app.models import UserOAuth
|
|
@@ -22,6 +19,10 @@ from fractal_server.app.schemas.v2 import ResourceRead
|
|
|
22
19
|
from fractal_server.config import get_settings
|
|
23
20
|
from fractal_server.syringe import Inject
|
|
24
21
|
|
|
22
|
+
from ._aux_functions import _check_resource_name
|
|
23
|
+
from ._aux_functions import _get_resource_or_404
|
|
24
|
+
from .profile import _check_profile_name
|
|
25
|
+
|
|
25
26
|
router = APIRouter()
|
|
26
27
|
|
|
27
28
|
|
|
@@ -47,8 +48,7 @@ def _check_type_match_or_422(new_resource: ResourceCreate) -> None:
|
|
|
47
48
|
raise HTTPException(
|
|
48
49
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
49
50
|
detail=(
|
|
50
|
-
f"{settings.FRACTAL_RUNNER_BACKEND=} != "
|
|
51
|
-
f"{new_resource.type=}"
|
|
51
|
+
f"{settings.FRACTAL_RUNNER_BACKEND=} != {new_resource.type=}"
|
|
52
52
|
),
|
|
53
53
|
)
|
|
54
54
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from fastapi import APIRouter
|
|
2
|
+
from fastapi import Depends
|
|
3
|
+
from sqlalchemy import func
|
|
4
|
+
from sqlmodel import select
|
|
5
|
+
|
|
6
|
+
from fractal_server.app.db import AsyncSession
|
|
7
|
+
from fractal_server.app.db import get_async_db
|
|
8
|
+
from fractal_server.app.models import LinkUserProjectV2
|
|
9
|
+
from fractal_server.app.models import UserOAuth
|
|
10
|
+
from fractal_server.app.models.v2 import ProjectV2
|
|
11
|
+
from fractal_server.app.routes.auth import current_superuser_act
|
|
12
|
+
from fractal_server.app.routes.pagination import PaginationRequest
|
|
13
|
+
from fractal_server.app.routes.pagination import PaginationResponse
|
|
14
|
+
from fractal_server.app.routes.pagination import get_pagination_params
|
|
15
|
+
from fractal_server.app.schemas.v2 import LinkUserProjectRead
|
|
16
|
+
|
|
17
|
+
router = APIRouter()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@router.get("/", response_model=PaginationResponse[LinkUserProjectRead])
|
|
21
|
+
async def view_link_user_project(
|
|
22
|
+
# User info
|
|
23
|
+
user_id: int | None = None,
|
|
24
|
+
# Project info
|
|
25
|
+
project_id: int | None = None,
|
|
26
|
+
project_name: str | None = None,
|
|
27
|
+
# Permissions
|
|
28
|
+
is_owner: bool | None = None,
|
|
29
|
+
is_verified: bool | None = None,
|
|
30
|
+
# -----
|
|
31
|
+
pagination: PaginationRequest = Depends(get_pagination_params),
|
|
32
|
+
superuser: UserOAuth = Depends(current_superuser_act),
|
|
33
|
+
db: AsyncSession = Depends(get_async_db),
|
|
34
|
+
) -> PaginationResponse[LinkUserProjectRead]:
|
|
35
|
+
page = pagination.page
|
|
36
|
+
page_size = pagination.page_size
|
|
37
|
+
|
|
38
|
+
stm = (
|
|
39
|
+
select(
|
|
40
|
+
LinkUserProjectV2,
|
|
41
|
+
UserOAuth.email,
|
|
42
|
+
ProjectV2.name,
|
|
43
|
+
)
|
|
44
|
+
.join(UserOAuth, UserOAuth.id == LinkUserProjectV2.user_id)
|
|
45
|
+
.join(ProjectV2, ProjectV2.id == LinkUserProjectV2.project_id)
|
|
46
|
+
.order_by(UserOAuth.email, ProjectV2.name)
|
|
47
|
+
)
|
|
48
|
+
stm_count = (
|
|
49
|
+
select(func.count())
|
|
50
|
+
.select_from(LinkUserProjectV2)
|
|
51
|
+
.join(UserOAuth, UserOAuth.id == LinkUserProjectV2.user_id)
|
|
52
|
+
.join(ProjectV2, ProjectV2.id == LinkUserProjectV2.project_id)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if project_id is not None:
|
|
56
|
+
stm = stm.where(LinkUserProjectV2.project_id == project_id)
|
|
57
|
+
stm_count = stm_count.where(LinkUserProjectV2.project_id == project_id)
|
|
58
|
+
if project_name is not None:
|
|
59
|
+
stm = stm.where(ProjectV2.name.icontains(project_name))
|
|
60
|
+
stm_count = stm_count.where(ProjectV2.name.icontains(project_name))
|
|
61
|
+
if user_id is not None:
|
|
62
|
+
stm = stm.where(LinkUserProjectV2.user_id == user_id)
|
|
63
|
+
stm_count = stm_count.where(LinkUserProjectV2.user_id == user_id)
|
|
64
|
+
if is_owner is not None:
|
|
65
|
+
stm = stm.where(LinkUserProjectV2.is_owner == is_owner)
|
|
66
|
+
stm_count = stm_count.where(LinkUserProjectV2.is_owner == is_owner)
|
|
67
|
+
if is_verified is not None:
|
|
68
|
+
stm = stm.where(LinkUserProjectV2.is_verified == is_verified)
|
|
69
|
+
stm_count = stm_count.where(
|
|
70
|
+
LinkUserProjectV2.is_verified == is_verified
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
res_total_count = await db.execute(stm_count)
|
|
74
|
+
|
|
75
|
+
total_count = res_total_count.scalar()
|
|
76
|
+
if page_size is None:
|
|
77
|
+
page_size = total_count
|
|
78
|
+
else:
|
|
79
|
+
stm = stm.offset((page - 1) * page_size).limit(page_size)
|
|
80
|
+
|
|
81
|
+
res = await db.execute(stm)
|
|
82
|
+
items = res.all()
|
|
83
|
+
|
|
84
|
+
return PaginationResponse[LinkUserProjectRead](
|
|
85
|
+
total_count=total_count,
|
|
86
|
+
page_size=page_size,
|
|
87
|
+
current_page=page,
|
|
88
|
+
items=[
|
|
89
|
+
dict(
|
|
90
|
+
# User info
|
|
91
|
+
user_id=linkuserproject.user_id,
|
|
92
|
+
user_email=user_email,
|
|
93
|
+
# Project info
|
|
94
|
+
project_id=linkuserproject.project_id,
|
|
95
|
+
project_name=project_name,
|
|
96
|
+
# Permissions
|
|
97
|
+
is_verified=linkuserproject.is_verified,
|
|
98
|
+
is_owner=linkuserproject.is_owner,
|
|
99
|
+
permissions=linkuserproject.permissions,
|
|
100
|
+
)
|
|
101
|
+
for linkuserproject, user_email, project_name in items
|
|
102
|
+
],
|
|
103
|
+
)
|
|
@@ -8,21 +8,22 @@ from sqlmodel import select
|
|
|
8
8
|
|
|
9
9
|
from fractal_server.app.db import AsyncSession
|
|
10
10
|
from fractal_server.app.db import get_async_db
|
|
11
|
+
from fractal_server.app.models import LinkUserProjectV2
|
|
11
12
|
from fractal_server.app.models import TaskGroupV2
|
|
12
13
|
from fractal_server.app.models import UserOAuth
|
|
13
14
|
from fractal_server.app.models.v2 import TaskV2
|
|
14
15
|
from fractal_server.app.models.v2 import WorkflowTaskV2
|
|
15
16
|
from fractal_server.app.models.v2 import WorkflowV2
|
|
16
17
|
from fractal_server.app.routes.auth import current_superuser_act
|
|
17
|
-
from fractal_server.app.routes.pagination import get_pagination_params
|
|
18
18
|
from fractal_server.app.routes.pagination import PaginationRequest
|
|
19
19
|
from fractal_server.app.routes.pagination import PaginationResponse
|
|
20
|
+
from fractal_server.app.routes.pagination import get_pagination_params
|
|
20
21
|
from fractal_server.app.schemas.v2.task import TaskType
|
|
21
22
|
|
|
22
23
|
router = APIRouter()
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
class
|
|
26
|
+
class TaskMinimal(BaseModel):
|
|
26
27
|
id: int
|
|
27
28
|
name: str
|
|
28
29
|
type: str
|
|
@@ -38,7 +39,7 @@ class ProjectUser(BaseModel):
|
|
|
38
39
|
email: EmailStr
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
class
|
|
42
|
+
class TaskRelationship(BaseModel):
|
|
42
43
|
workflow_id: int
|
|
43
44
|
workflow_name: str
|
|
44
45
|
project_id: int
|
|
@@ -46,12 +47,12 @@ class TaskV2Relationship(BaseModel):
|
|
|
46
47
|
project_users: list[ProjectUser] = Field(default_factory=list)
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
class
|
|
50
|
-
task:
|
|
51
|
-
relationships: list[
|
|
50
|
+
class TaskInfo(BaseModel):
|
|
51
|
+
task: TaskMinimal
|
|
52
|
+
relationships: list[TaskRelationship]
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
@router.get("/", response_model=PaginationResponse[
|
|
55
|
+
@router.get("/", response_model=PaginationResponse[TaskInfo])
|
|
55
56
|
async def query_tasks(
|
|
56
57
|
id: int | None = None,
|
|
57
58
|
source: str | None = None,
|
|
@@ -65,7 +66,7 @@ async def query_tasks(
|
|
|
65
66
|
pagination: PaginationRequest = Depends(get_pagination_params),
|
|
66
67
|
user: UserOAuth = Depends(current_superuser_act),
|
|
67
68
|
db: AsyncSession = Depends(get_async_db),
|
|
68
|
-
) -> PaginationResponse[
|
|
69
|
+
) -> PaginationResponse[TaskInfo]:
|
|
69
70
|
"""
|
|
70
71
|
Query `TaskV2` and get information about related workflows and projects.
|
|
71
72
|
"""
|
|
@@ -106,16 +107,12 @@ async def query_tasks(
|
|
|
106
107
|
stm = stm.where(TaskV2.authors.icontains(author))
|
|
107
108
|
stm_count = stm_count.where(TaskV2.authors.icontains(author))
|
|
108
109
|
if resource_id is not None:
|
|
109
|
-
stm = (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
stm_count.join(TaskGroupV2)
|
|
116
|
-
.where(TaskGroupV2.id == TaskV2.taskgroupv2_id)
|
|
117
|
-
.where(TaskGroupV2.resource_id == resource_id)
|
|
118
|
-
)
|
|
110
|
+
stm = stm.join(
|
|
111
|
+
TaskGroupV2, TaskGroupV2.id == TaskV2.taskgroupv2_id
|
|
112
|
+
).where(TaskGroupV2.resource_id == resource_id)
|
|
113
|
+
stm_count = stm_count.join(
|
|
114
|
+
TaskGroupV2, TaskGroupV2.id == TaskV2.taskgroupv2_id
|
|
115
|
+
).where(TaskGroupV2.resource_id == resource_id)
|
|
119
116
|
|
|
120
117
|
# Find total number of elements
|
|
121
118
|
res_total_count = await db.execute(stm_count)
|
|
@@ -133,13 +130,31 @@ async def query_tasks(
|
|
|
133
130
|
for task in task_list:
|
|
134
131
|
stm = (
|
|
135
132
|
select(WorkflowV2)
|
|
136
|
-
.join(
|
|
137
|
-
|
|
133
|
+
.join(
|
|
134
|
+
WorkflowTaskV2,
|
|
135
|
+
WorkflowTaskV2.workflow_id == WorkflowV2.id,
|
|
136
|
+
)
|
|
138
137
|
.where(WorkflowTaskV2.task_id == task.id)
|
|
139
138
|
)
|
|
140
139
|
res = await db.execute(stm)
|
|
141
140
|
wf_list = res.scalars().all()
|
|
142
141
|
|
|
142
|
+
project_users = {}
|
|
143
|
+
for project_id in set([workflow.project_id for workflow in wf_list]):
|
|
144
|
+
res = await db.execute(
|
|
145
|
+
select(UserOAuth.id, UserOAuth.email)
|
|
146
|
+
.join(
|
|
147
|
+
LinkUserProjectV2,
|
|
148
|
+
LinkUserProjectV2.user_id == UserOAuth.id,
|
|
149
|
+
)
|
|
150
|
+
.where(LinkUserProjectV2.project_id == project_id)
|
|
151
|
+
.where(LinkUserProjectV2.is_owner.is_(True))
|
|
152
|
+
)
|
|
153
|
+
project_users[project_id] = [
|
|
154
|
+
ProjectUser(id=p_user[0], email=p_user[1])
|
|
155
|
+
for p_user in res.all()
|
|
156
|
+
]
|
|
157
|
+
|
|
143
158
|
task_info_list.append(
|
|
144
159
|
dict(
|
|
145
160
|
task=task.model_dump(),
|
|
@@ -149,17 +164,13 @@ async def query_tasks(
|
|
|
149
164
|
workflow_name=workflow.name,
|
|
150
165
|
project_id=workflow.project.id,
|
|
151
166
|
project_name=workflow.project.name,
|
|
152
|
-
project_users=[
|
|
153
|
-
dict(id=user.id, email=user.email)
|
|
154
|
-
for user in workflow.project.user_list
|
|
155
|
-
],
|
|
167
|
+
project_users=project_users[workflow.project_id],
|
|
156
168
|
)
|
|
157
169
|
for workflow in wf_list
|
|
158
170
|
],
|
|
159
171
|
)
|
|
160
172
|
)
|
|
161
|
-
|
|
162
|
-
return PaginationResponse[TaskV2Info](
|
|
173
|
+
return dict(
|
|
163
174
|
total_count=total_count,
|
|
164
175
|
page_size=page_size,
|
|
165
176
|
current_page=page,
|
|
@@ -5,6 +5,7 @@ from fastapi import status
|
|
|
5
5
|
from pydantic.types import AwareDatetime
|
|
6
6
|
from sqlalchemy.sql.operators import is_
|
|
7
7
|
from sqlalchemy.sql.operators import is_not
|
|
8
|
+
from sqlmodel import func
|
|
8
9
|
from sqlmodel import select
|
|
9
10
|
|
|
10
11
|
from fractal_server.app.db import AsyncSession
|
|
@@ -16,53 +17,94 @@ from fractal_server.app.routes.auth import current_superuser_act
|
|
|
16
17
|
from fractal_server.app.routes.auth._aux_auth import (
|
|
17
18
|
_verify_user_belongs_to_group,
|
|
18
19
|
)
|
|
19
|
-
from fractal_server.app.
|
|
20
|
-
from fractal_server.app.
|
|
21
|
-
from fractal_server.app.
|
|
20
|
+
from fractal_server.app.routes.pagination import PaginationRequest
|
|
21
|
+
from fractal_server.app.routes.pagination import PaginationResponse
|
|
22
|
+
from fractal_server.app.routes.pagination import get_pagination_params
|
|
23
|
+
from fractal_server.app.schemas.v2 import TaskGroupActivityAction
|
|
24
|
+
from fractal_server.app.schemas.v2 import TaskGroupActivityRead
|
|
25
|
+
from fractal_server.app.schemas.v2 import TaskGroupActivityStatus
|
|
26
|
+
from fractal_server.app.schemas.v2 import TaskGroupOriginEnum
|
|
22
27
|
from fractal_server.app.schemas.v2 import TaskGroupReadSuperuser
|
|
23
|
-
from fractal_server.app.schemas.v2 import
|
|
24
|
-
from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
|
|
28
|
+
from fractal_server.app.schemas.v2 import TaskGroupUpdate
|
|
25
29
|
from fractal_server.logger import set_logger
|
|
26
30
|
|
|
27
|
-
|
|
28
31
|
router = APIRouter()
|
|
29
32
|
|
|
30
33
|
logger = set_logger(__name__)
|
|
31
34
|
|
|
32
35
|
|
|
33
|
-
@router.get(
|
|
36
|
+
@router.get(
|
|
37
|
+
"/activity/", response_model=PaginationResponse[TaskGroupActivityRead]
|
|
38
|
+
)
|
|
34
39
|
async def get_task_group_activity_list(
|
|
35
40
|
task_group_activity_id: int | None = None,
|
|
36
41
|
user_id: int | None = None,
|
|
37
42
|
taskgroupv2_id: int | None = None,
|
|
38
43
|
pkg_name: str | None = None,
|
|
39
|
-
status:
|
|
40
|
-
action:
|
|
44
|
+
status: TaskGroupActivityStatus | None = None,
|
|
45
|
+
action: TaskGroupActivityAction | None = None,
|
|
41
46
|
timestamp_started_min: AwareDatetime | None = None,
|
|
47
|
+
pagination: PaginationRequest = Depends(get_pagination_params),
|
|
42
48
|
superuser: UserOAuth = Depends(current_superuser_act),
|
|
43
49
|
db: AsyncSession = Depends(get_async_db),
|
|
44
|
-
) ->
|
|
45
|
-
|
|
50
|
+
) -> PaginationResponse[TaskGroupActivityRead]:
|
|
51
|
+
# Assign pagination parameters
|
|
52
|
+
page = pagination.page
|
|
53
|
+
page_size = pagination.page_size
|
|
54
|
+
|
|
55
|
+
stm = select(TaskGroupActivityV2).order_by(
|
|
56
|
+
TaskGroupActivityV2.timestamp_started.desc()
|
|
57
|
+
)
|
|
58
|
+
stm_count = select(func.count(TaskGroupActivityV2.id))
|
|
46
59
|
if task_group_activity_id is not None:
|
|
47
60
|
stm = stm.where(TaskGroupActivityV2.id == task_group_activity_id)
|
|
61
|
+
stm_count = stm_count.where(
|
|
62
|
+
TaskGroupActivityV2.id == task_group_activity_id
|
|
63
|
+
)
|
|
48
64
|
if user_id:
|
|
49
65
|
stm = stm.where(TaskGroupActivityV2.user_id == user_id)
|
|
66
|
+
stm_count = stm_count.where(TaskGroupActivityV2.user_id == user_id)
|
|
50
67
|
if taskgroupv2_id:
|
|
51
68
|
stm = stm.where(TaskGroupActivityV2.taskgroupv2_id == taskgroupv2_id)
|
|
69
|
+
stm_count = stm_count.where(
|
|
70
|
+
TaskGroupActivityV2.taskgroupv2_id == taskgroupv2_id
|
|
71
|
+
)
|
|
52
72
|
if pkg_name:
|
|
53
73
|
stm = stm.where(TaskGroupActivityV2.pkg_name.icontains(pkg_name))
|
|
74
|
+
stm_count = stm_count.where(
|
|
75
|
+
TaskGroupActivityV2.pkg_name.icontains(pkg_name)
|
|
76
|
+
)
|
|
54
77
|
if status:
|
|
55
78
|
stm = stm.where(TaskGroupActivityV2.status == status)
|
|
79
|
+
stm_count = stm_count.where(TaskGroupActivityV2.status == status)
|
|
56
80
|
if action:
|
|
57
81
|
stm = stm.where(TaskGroupActivityV2.action == action)
|
|
82
|
+
stm_count = stm_count.where(TaskGroupActivityV2.action == action)
|
|
58
83
|
if timestamp_started_min is not None:
|
|
59
84
|
stm = stm.where(
|
|
60
85
|
TaskGroupActivityV2.timestamp_started >= timestamp_started_min
|
|
61
86
|
)
|
|
87
|
+
stm_count = stm_count.where(
|
|
88
|
+
TaskGroupActivityV2.timestamp_started >= timestamp_started_min
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Find total number of elements
|
|
92
|
+
res_total_count = await db.execute(stm_count)
|
|
93
|
+
total_count = res_total_count.scalar()
|
|
94
|
+
if page_size is None:
|
|
95
|
+
page_size = total_count
|
|
96
|
+
else:
|
|
97
|
+
stm = stm.offset((page - 1) * page_size).limit(page_size)
|
|
62
98
|
|
|
63
99
|
res = await db.execute(stm)
|
|
64
100
|
activities = res.scalars().all()
|
|
65
|
-
|
|
101
|
+
|
|
102
|
+
return dict(
|
|
103
|
+
total_count=total_count,
|
|
104
|
+
page_size=page_size,
|
|
105
|
+
current_page=page,
|
|
106
|
+
items=activities,
|
|
107
|
+
)
|
|
66
108
|
|
|
67
109
|
|
|
68
110
|
@router.get("/{task_group_id}/", response_model=TaskGroupReadSuperuser)
|
|
@@ -80,21 +122,27 @@ async def query_task_group(
|
|
|
80
122
|
return task_group
|
|
81
123
|
|
|
82
124
|
|
|
83
|
-
@router.get("/", response_model=
|
|
125
|
+
@router.get("/", response_model=PaginationResponse[TaskGroupReadSuperuser])
|
|
84
126
|
async def query_task_group_list(
|
|
85
127
|
user_id: int | None = None,
|
|
86
128
|
user_group_id: int | None = None,
|
|
87
129
|
private: bool | None = None,
|
|
88
130
|
active: bool | None = None,
|
|
89
131
|
pkg_name: str | None = None,
|
|
90
|
-
origin:
|
|
132
|
+
origin: TaskGroupOriginEnum | None = None,
|
|
91
133
|
timestamp_last_used_min: AwareDatetime | None = None,
|
|
92
134
|
timestamp_last_used_max: AwareDatetime | None = None,
|
|
93
135
|
resource_id: int | None = None,
|
|
136
|
+
pagination: PaginationRequest = Depends(get_pagination_params),
|
|
94
137
|
user: UserOAuth = Depends(current_superuser_act),
|
|
95
138
|
db: AsyncSession = Depends(get_async_db),
|
|
96
|
-
) ->
|
|
139
|
+
) -> PaginationResponse[TaskGroupReadSuperuser]:
|
|
140
|
+
# Assign pagination parameters
|
|
141
|
+
page = pagination.page
|
|
142
|
+
page_size = pagination.page_size
|
|
143
|
+
|
|
97
144
|
stm = select(TaskGroupV2)
|
|
145
|
+
stm_count = select(func.count(TaskGroupV2.id))
|
|
98
146
|
|
|
99
147
|
if user_group_id is not None and private is True:
|
|
100
148
|
raise HTTPException(
|
|
@@ -106,43 +154,72 @@ async def query_task_group_list(
|
|
|
106
154
|
)
|
|
107
155
|
if user_id is not None:
|
|
108
156
|
stm = stm.where(TaskGroupV2.user_id == user_id)
|
|
157
|
+
stm_count = stm_count.where(TaskGroupV2.user_id == user_id)
|
|
109
158
|
if user_group_id is not None:
|
|
110
159
|
stm = stm.where(TaskGroupV2.user_group_id == user_group_id)
|
|
160
|
+
stm_count = stm_count.where(TaskGroupV2.user_group_id == user_group_id)
|
|
111
161
|
if private is not None:
|
|
112
162
|
if private is True:
|
|
113
163
|
stm = stm.where(is_(TaskGroupV2.user_group_id, None))
|
|
164
|
+
stm_count = stm_count.where(is_(TaskGroupV2.user_group_id, None))
|
|
114
165
|
else:
|
|
115
166
|
stm = stm.where(is_not(TaskGroupV2.user_group_id, None))
|
|
167
|
+
stm_count = stm_count.where(is_not(TaskGroupV2.user_group_id, None))
|
|
116
168
|
if active is not None:
|
|
117
169
|
if active is True:
|
|
118
170
|
stm = stm.where(is_(TaskGroupV2.active, True))
|
|
171
|
+
stm_count = stm_count.where(is_(TaskGroupV2.active, True))
|
|
119
172
|
else:
|
|
120
173
|
stm = stm.where(is_(TaskGroupV2.active, False))
|
|
174
|
+
stm_count = stm_count.where(is_(TaskGroupV2.active, False))
|
|
121
175
|
if origin is not None:
|
|
122
176
|
stm = stm.where(TaskGroupV2.origin == origin)
|
|
177
|
+
stm_count = stm_count.where(TaskGroupV2.origin == origin)
|
|
123
178
|
if pkg_name is not None:
|
|
124
179
|
stm = stm.where(TaskGroupV2.pkg_name.icontains(pkg_name))
|
|
180
|
+
stm_count = stm_count.where(TaskGroupV2.pkg_name.icontains(pkg_name))
|
|
125
181
|
if timestamp_last_used_min is not None:
|
|
126
182
|
stm = stm.where(
|
|
127
183
|
TaskGroupV2.timestamp_last_used >= timestamp_last_used_min
|
|
128
184
|
)
|
|
185
|
+
stm_count = stm_count.where(
|
|
186
|
+
TaskGroupV2.timestamp_last_used >= timestamp_last_used_min
|
|
187
|
+
)
|
|
129
188
|
if timestamp_last_used_max is not None:
|
|
130
189
|
stm = stm.where(
|
|
131
190
|
TaskGroupV2.timestamp_last_used <= timestamp_last_used_max
|
|
132
191
|
)
|
|
192
|
+
stm_count = stm_count.where(
|
|
193
|
+
TaskGroupV2.timestamp_last_used <= timestamp_last_used_max
|
|
194
|
+
)
|
|
133
195
|
if resource_id is not None:
|
|
134
196
|
stm = stm.where(TaskGroupV2.resource_id == resource_id)
|
|
197
|
+
stm_count = stm_count.where(TaskGroupV2.resource_id == resource_id)
|
|
198
|
+
|
|
199
|
+
# Find total number of elements
|
|
200
|
+
res_total_count = await db.execute(stm_count)
|
|
201
|
+
total_count = res_total_count.scalar()
|
|
202
|
+
if page_size is None:
|
|
203
|
+
page_size = total_count
|
|
204
|
+
else:
|
|
205
|
+
stm = stm.offset((page - 1) * page_size).limit(page_size)
|
|
135
206
|
|
|
136
207
|
stm = stm.order_by(TaskGroupV2.id)
|
|
137
208
|
res = await db.execute(stm)
|
|
138
209
|
task_groups_list = res.scalars().all()
|
|
139
|
-
|
|
210
|
+
|
|
211
|
+
return dict(
|
|
212
|
+
total_count=total_count,
|
|
213
|
+
page_size=page_size,
|
|
214
|
+
current_page=page,
|
|
215
|
+
items=task_groups_list,
|
|
216
|
+
)
|
|
140
217
|
|
|
141
218
|
|
|
142
219
|
@router.patch("/{task_group_id}/", response_model=TaskGroupReadSuperuser)
|
|
143
220
|
async def patch_task_group(
|
|
144
221
|
task_group_id: int,
|
|
145
|
-
task_group_update:
|
|
222
|
+
task_group_update: TaskGroupUpdate,
|
|
146
223
|
user: UserOAuth = Depends(current_superuser_act),
|
|
147
224
|
db: AsyncSession = Depends(get_async_db),
|
|
148
225
|
) -> list[TaskGroupReadSuperuser]:
|