fractal-server 2.7.0a4__tar.gz → 2.7.0a6__tar.gz
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-2.7.0a4 → fractal_server-2.7.0a6}/PKG-INFO +1 -1
- fractal_server-2.7.0a6/fractal_server/__init__.py +1 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/v2/task.py +0 -5
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/task_collection.py +2 -2
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/__init__.py +4 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/_aux_functions.py +1 -7
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +72 -11
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/task_collection.py +49 -39
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/task_group.py +10 -6
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/workflow.py +14 -82
- fractal_server-2.7.0a6/fractal_server/app/routes/api/v2/workflow_import.py +355 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/workflowtask.py +0 -1
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/group.py +27 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/__init__.py +13 -7
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/__init__.py +1 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/dumps.py +0 -1
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/manifest.py +13 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/task.py +20 -10
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/workflowtask.py +3 -4
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/data_migrations/2_7_0.py +62 -3
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/utils.py +19 -5
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v1/background_operations.py +3 -3
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v1/get_collection_data.py +2 -2
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/background_operations.py +4 -4
- fractal_server-2.7.0a6/fractal_server/tasks/v2/endpoint_operations.py +124 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/pyproject.toml +2 -2
- fractal_server-2.7.0a4/fractal_server/__init__.py +0 -1
- fractal_server-2.7.0a4/fractal_server/tasks/v2/endpoint_operations.py +0 -44
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/LICENSE +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/README.md +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/__main__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/linkusergroup.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/security.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/user_settings.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v1/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v1/dataset.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v1/job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v1/project.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v1/state.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v1/task.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v1/workflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/collection_state.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/dataset.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/project.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/task.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/models/v2/workflowtask.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/v1.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/v2/job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/v2/project.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/_aux_functions.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/dataset.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/project.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/task.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/workflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v1/workflowtask.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/dataset.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/images.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/project.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/status.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/submit.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/task.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/current_user.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/login.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/oauth.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/register.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/router.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/auth/users.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/aux/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/aux/_job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/aux/_runner.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/.gitignore +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/async_wrap.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/components.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/compress_folder.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/exceptions.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/ssh/executor.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/executors/slurm/sudo/executor.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/extract_archive.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/filenames.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/run_subprocess.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/shutdown.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/task_files.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_common.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_local/executor.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/common.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local/executor.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/runner.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/runner_functions.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/v2/task_interface.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/runner/versions.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/_validators.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/user.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/user_group.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/user_settings.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/applyworkflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/dataset.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/dumps.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/manifest.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/project.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/state.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/task.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/task_collection.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v1/workflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/dataset.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/job.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/project.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/status.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/task_collection.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/task_group.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/schemas/v2/workflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/security/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/user_settings.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/config.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/data_migrations/tools.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/gunicorn_fractal.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/images/models.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/logger.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/main.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/README +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/env.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/naming_convention.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/script.py.mako +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/py.typed +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/ssh/_fabric.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/syringe.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v1/_TaskCollectPip.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v1/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v1/endpoint_operations.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v1/utils.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/_venv_pip.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/background_operations_ssh.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/database_operations.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/templates/_1_create_venv.sh +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/templates/_2_upgrade_pip.sh +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/templates/_3_pip_install.sh +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/templates/_4_pip_freeze.sh +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/templates/_5_pip_show.sh +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/tasks/v2/utils.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/urls.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/utils.py +0 -0
- {fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/zip_tools.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__VERSION__ = "2.7.0a6"
|
{fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/admin/v2/task.py
RENAMED
@@ -29,7 +29,6 @@ class TaskV2Minimal(BaseModel):
|
|
29
29
|
command_non_parallel: Optional[str] = None
|
30
30
|
command_parallel: Optional[str]
|
31
31
|
source: Optional[str] = None
|
32
|
-
owner: Optional[str] = None
|
33
32
|
version: Optional[str] = None
|
34
33
|
|
35
34
|
|
@@ -60,7 +59,6 @@ async def query_tasks(
|
|
60
59
|
source: Optional[str] = None,
|
61
60
|
version: Optional[str] = None,
|
62
61
|
name: Optional[str] = None,
|
63
|
-
owner: Optional[str] = None,
|
64
62
|
max_number_of_results: int = 25,
|
65
63
|
user: UserOAuth = Depends(current_active_superuser),
|
66
64
|
db: AsyncSession = Depends(get_async_db),
|
@@ -75,7 +73,6 @@ async def query_tasks(
|
|
75
73
|
`task.source`.
|
76
74
|
version: If not `None`, query for matching `task.version`.
|
77
75
|
name: If not `None`, query for contained case insensitive `task.name`.
|
78
|
-
owner: If not `None`, query for matching `task.owner`.
|
79
76
|
max_number_of_results: The maximum length of the response.
|
80
77
|
"""
|
81
78
|
|
@@ -89,8 +86,6 @@ async def query_tasks(
|
|
89
86
|
stm = stm.where(TaskV2.version == version)
|
90
87
|
if name is not None:
|
91
88
|
stm = stm.where(TaskV2.name.icontains(name))
|
92
|
-
if owner is not None:
|
93
|
-
stm = stm.where(TaskV2.owner == owner)
|
94
89
|
|
95
90
|
res = await db.execute(stm)
|
96
91
|
task_list = res.scalars().all()
|
@@ -27,7 +27,7 @@ from fractal_server.app.models import UserOAuth
|
|
27
27
|
from fractal_server.app.routes.auth import current_active_user
|
28
28
|
from fractal_server.app.routes.auth import current_active_verified_user
|
29
29
|
from fractal_server.string_tools import slugify_task_name_for_source_v1
|
30
|
-
from fractal_server.tasks.utils import
|
30
|
+
from fractal_server.tasks.utils import get_collection_log_v1
|
31
31
|
from fractal_server.tasks.v1._TaskCollectPip import _TaskCollectPip
|
32
32
|
from fractal_server.tasks.v1.background_operations import (
|
33
33
|
background_collect_pip,
|
@@ -232,7 +232,7 @@ async def check_collection_status(
|
|
232
232
|
# In some cases (i.e. a successful or ongoing task collection), data.log is
|
233
233
|
# not set; if so, we collect the current logs
|
234
234
|
if verbose and not data.log:
|
235
|
-
data.log =
|
235
|
+
data.log = get_collection_log_v1(data.venv_path)
|
236
236
|
state.data = data.sanitised_dict()
|
237
237
|
close_logger(logger)
|
238
238
|
await db.close()
|
{fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/__init__.py
RENAMED
@@ -14,6 +14,7 @@ from .task_collection import router as task_collection_router_v2
|
|
14
14
|
from .task_collection_custom import router as task_collection_router_v2_custom
|
15
15
|
from .task_group import router as task_group_router_v2
|
16
16
|
from .workflow import router as workflow_router_v2
|
17
|
+
from .workflow_import import router as workflow_import_router_v2
|
17
18
|
from .workflowtask import router as workflowtask_router_v2
|
18
19
|
from fractal_server.config import get_settings
|
19
20
|
from fractal_server.syringe import Inject
|
@@ -42,5 +43,8 @@ router_api_v2.include_router(
|
|
42
43
|
task_group_router_v2, prefix="/task-group", tags=["V2 TaskGroup"]
|
43
44
|
)
|
44
45
|
router_api_v2.include_router(workflow_router_v2, tags=["V2 Workflow"])
|
46
|
+
router_api_v2.include_router(
|
47
|
+
workflow_import_router_v2, tags=["V2 Workflow Import"]
|
48
|
+
)
|
45
49
|
router_api_v2.include_router(workflowtask_router_v2, tags=["V2 WorkflowTask"])
|
46
50
|
router_api_v2.include_router(status_router_v2, tags=["V2 Status"])
|
{fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/_aux_functions.py
RENAMED
@@ -332,7 +332,6 @@ async def _workflow_insert_task(
|
|
332
332
|
*,
|
333
333
|
workflow_id: int,
|
334
334
|
task_id: int,
|
335
|
-
order: Optional[int] = None,
|
336
335
|
meta_parallel: Optional[dict[str, Any]] = None,
|
337
336
|
meta_non_parallel: Optional[dict[str, Any]] = None,
|
338
337
|
args_non_parallel: Optional[dict[str, Any]] = None,
|
@@ -347,7 +346,6 @@ async def _workflow_insert_task(
|
|
347
346
|
workflow_id:
|
348
347
|
task_id:
|
349
348
|
|
350
|
-
order:
|
351
349
|
meta_parallel:
|
352
350
|
meta_non_parallel:
|
353
351
|
args_non_parallel:
|
@@ -359,9 +357,6 @@ async def _workflow_insert_task(
|
|
359
357
|
if db_workflow is None:
|
360
358
|
raise ValueError(f"Workflow {workflow_id} does not exist")
|
361
359
|
|
362
|
-
if order is None:
|
363
|
-
order = len(db_workflow.task_list)
|
364
|
-
|
365
360
|
# Get task from db
|
366
361
|
db_task = await db.get(TaskV2, task_id)
|
367
362
|
if db_task is None:
|
@@ -397,8 +392,7 @@ async def _workflow_insert_task(
|
|
397
392
|
meta_non_parallel=final_meta_non_parallel,
|
398
393
|
**input_filters_kwarg,
|
399
394
|
)
|
400
|
-
db_workflow.task_list.
|
401
|
-
db_workflow.task_list.reorder() # type: ignore
|
395
|
+
db_workflow.task_list.append(wf_task)
|
402
396
|
flag_modified(db_workflow, "task_list")
|
403
397
|
await db.commit()
|
404
398
|
|
@@ -9,13 +9,21 @@ from fastapi import HTTPException
|
|
9
9
|
from fastapi import status
|
10
10
|
from sqlmodel import select
|
11
11
|
|
12
|
-
from
|
13
|
-
from
|
14
|
-
from
|
15
|
-
from
|
16
|
-
from
|
17
|
-
from
|
18
|
-
from
|
12
|
+
from fractal_server.app.db import AsyncSession
|
13
|
+
from fractal_server.app.models import LinkUserGroup
|
14
|
+
from fractal_server.app.models import UserGroup
|
15
|
+
from fractal_server.app.models import UserOAuth
|
16
|
+
from fractal_server.app.models.v2 import CollectionStateV2
|
17
|
+
from fractal_server.app.models.v2 import TaskGroupV2
|
18
|
+
from fractal_server.app.models.v2 import TaskV2
|
19
|
+
from fractal_server.app.models.v2 import WorkflowTaskV2
|
20
|
+
from fractal_server.app.routes.auth._aux_auth import _get_default_usergroup_id
|
21
|
+
from fractal_server.app.routes.auth._aux_auth import (
|
22
|
+
_verify_user_belongs_to_group,
|
23
|
+
)
|
24
|
+
from fractal_server.logger import set_logger
|
25
|
+
|
26
|
+
logger = set_logger(__name__)
|
19
27
|
|
20
28
|
|
21
29
|
async def _get_task_group_or_404(
|
@@ -211,6 +219,33 @@ async def _get_valid_user_group_id(
|
|
211
219
|
return user_group_id
|
212
220
|
|
213
221
|
|
222
|
+
async def _get_collection_status_message(
|
223
|
+
task_group: TaskGroupV2, db: AsyncSession
|
224
|
+
) -> str:
|
225
|
+
res = await db.execute(
|
226
|
+
select(CollectionStateV2).where(
|
227
|
+
CollectionStateV2.taskgroupv2_id == task_group.id
|
228
|
+
)
|
229
|
+
)
|
230
|
+
states = res.scalars().all()
|
231
|
+
if len(states) > 1:
|
232
|
+
msg = (
|
233
|
+
"Expected one CollectionStateV2 associated to TaskGroup "
|
234
|
+
f"{task_group.id}, found {len(states)} "
|
235
|
+
f"(IDs: {[state.id for state in states]}).\n"
|
236
|
+
"Warning: this should have not happened, please contact an admin."
|
237
|
+
)
|
238
|
+
elif len(states) == 1:
|
239
|
+
msg = (
|
240
|
+
f"\nThere exists a task collection state (ID={states[0].id}) for "
|
241
|
+
f"this task group (ID={task_group.id}), with status "
|
242
|
+
f"{states[0].data.get('status')}."
|
243
|
+
)
|
244
|
+
else:
|
245
|
+
msg = ""
|
246
|
+
return msg
|
247
|
+
|
248
|
+
|
214
249
|
async def _verify_non_duplication_user_constraint(
|
215
250
|
db: AsyncSession,
|
216
251
|
user_id: int,
|
@@ -226,11 +261,24 @@ async def _verify_non_duplication_user_constraint(
|
|
226
261
|
res = await db.execute(stm)
|
227
262
|
duplicate = res.scalars().all()
|
228
263
|
if duplicate:
|
264
|
+
user = await db.get(UserOAuth, user_id)
|
265
|
+
if len(duplicate) > 1:
|
266
|
+
raise HTTPException(
|
267
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
268
|
+
detail=(
|
269
|
+
"Invalid state:\n"
|
270
|
+
f"User '{user.email}' already owns {len(duplicate)} task "
|
271
|
+
f"groups with name='{pkg_name}' and {version=} "
|
272
|
+
f"(IDs: {[group.id for group in duplicate]}).\n"
|
273
|
+
"This should have not happened: please contact an admin."
|
274
|
+
),
|
275
|
+
)
|
276
|
+
state_msg = await _get_collection_status_message(duplicate[0], db)
|
229
277
|
raise HTTPException(
|
230
278
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
231
279
|
detail=(
|
232
|
-
"
|
233
|
-
f"
|
280
|
+
f"User '{user.email}' already owns a task group "
|
281
|
+
f"with name='{pkg_name}' and {version=}.{state_msg}"
|
234
282
|
),
|
235
283
|
)
|
236
284
|
|
@@ -253,11 +301,24 @@ async def _verify_non_duplication_group_constraint(
|
|
253
301
|
res = await db.execute(stm)
|
254
302
|
duplicate = res.scalars().all()
|
255
303
|
if duplicate:
|
304
|
+
user_group = await db.get(UserGroup, user_group_id)
|
305
|
+
if len(duplicate) > 1:
|
306
|
+
raise HTTPException(
|
307
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
308
|
+
detail=(
|
309
|
+
"Invalid state:\n"
|
310
|
+
f"UserGroup '{user_group.name}' already owns "
|
311
|
+
f"{len(duplicate)} task groups with name='{pkg_name}' and "
|
312
|
+
f"{version=} (IDs: {[group.id for group in duplicate]}).\n"
|
313
|
+
"This should have not happened: please contact an admin."
|
314
|
+
),
|
315
|
+
)
|
316
|
+
state_msg = await _get_collection_status_message(duplicate[0], db)
|
256
317
|
raise HTTPException(
|
257
318
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
258
319
|
detail=(
|
259
|
-
"
|
260
|
-
f"
|
320
|
+
f"UserGroup {user_group.name} already owns a task group "
|
321
|
+
f"with {pkg_name=} and {version=}.{state_msg}"
|
261
322
|
),
|
262
323
|
)
|
263
324
|
|
@@ -31,7 +31,7 @@ from fractal_server.app.models import UserOAuth
|
|
31
31
|
from fractal_server.app.routes.auth import current_active_user
|
32
32
|
from fractal_server.app.routes.auth import current_active_verified_user
|
33
33
|
from fractal_server.tasks.utils import _normalize_package_name
|
34
|
-
from fractal_server.tasks.utils import
|
34
|
+
from fractal_server.tasks.utils import get_collection_log_v2
|
35
35
|
from fractal_server.tasks.v2.background_operations import (
|
36
36
|
background_collect_pip,
|
37
37
|
)
|
@@ -70,33 +70,40 @@ async def collect_tasks_pip(
|
|
70
70
|
# Get settings
|
71
71
|
settings = Inject(get_settings)
|
72
72
|
|
73
|
+
# Initialize task-group attributes
|
74
|
+
task_group_attrs = dict(user_id=user.id)
|
75
|
+
|
73
76
|
# Set/check python version
|
74
77
|
if task_collect.python_version is None:
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
+
task_group_attrs[
|
79
|
+
"python_version"
|
80
|
+
] = settings.FRACTAL_TASKS_PYTHON_DEFAULT_VERSION
|
81
|
+
else:
|
82
|
+
task_group_attrs["python_version"] = task_collect.python_version
|
78
83
|
try:
|
79
|
-
get_python_interpreter_v2(
|
84
|
+
get_python_interpreter_v2(
|
85
|
+
python_version=task_group_attrs["python_version"]
|
86
|
+
)
|
80
87
|
except ValueError:
|
81
88
|
raise HTTPException(
|
82
89
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
83
90
|
detail=(
|
84
|
-
f"Python version {
|
91
|
+
f"Python version {task_group_attrs['python_version']} is "
|
85
92
|
"not available for Fractal task collection."
|
86
93
|
),
|
87
94
|
)
|
88
95
|
|
89
|
-
#
|
90
|
-
task_group_attrs = dict(
|
91
|
-
user_id=user.id,
|
92
|
-
python_version=task_collect.python_version,
|
93
|
-
)
|
96
|
+
# Set pip_extras
|
94
97
|
if task_collect.package_extras is not None:
|
95
98
|
task_group_attrs["pip_extras"] = task_collect.package_extras
|
99
|
+
|
100
|
+
# Set pinned_package_versions
|
96
101
|
if task_collect.pinned_package_versions is not None:
|
97
102
|
task_group_attrs[
|
98
103
|
"pinned_package_versions"
|
99
104
|
] = task_collect.pinned_package_versions
|
105
|
+
|
106
|
+
# Set pkg_name, version, origin and wheel_path
|
100
107
|
if task_collect.package.endswith(".whl"):
|
101
108
|
try:
|
102
109
|
task_group_attrs["wheel_path"] = task_collect.package
|
@@ -119,19 +126,11 @@ async def collect_tasks_pip(
|
|
119
126
|
pkg_name = task_collect.package
|
120
127
|
task_group_attrs["pkg_name"] = _normalize_package_name(pkg_name)
|
121
128
|
task_group_attrs["origin"] = "pypi"
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
task_collect.package_version = latest_version
|
128
|
-
else:
|
129
|
-
task_group_attrs["version"] = task_collect.package_version
|
130
|
-
|
131
|
-
# Validate user settings (backend-specific)
|
132
|
-
user_settings = await validate_user_settings(
|
133
|
-
user=user, backend=settings.FRACTAL_RUNNER_BACKEND, db=db
|
134
|
-
)
|
129
|
+
latest_version = await get_package_version_from_pypi(
|
130
|
+
task_collect.package,
|
131
|
+
task_collect.package_version,
|
132
|
+
)
|
133
|
+
task_group_attrs["version"] = latest_version
|
135
134
|
|
136
135
|
# Validate query parameters related to user-group ownership
|
137
136
|
user_group_id = await _get_valid_user_group_id(
|
@@ -140,9 +139,16 @@ async def collect_tasks_pip(
|
|
140
139
|
user_id=user.id,
|
141
140
|
db=db,
|
142
141
|
)
|
142
|
+
|
143
|
+
# Set user_group_id
|
143
144
|
task_group_attrs["user_group_id"] = user_group_id
|
144
145
|
|
145
|
-
#
|
146
|
+
# Validate user settings (backend-specific)
|
147
|
+
user_settings = await validate_user_settings(
|
148
|
+
user=user, backend=settings.FRACTAL_RUNNER_BACKEND, db=db
|
149
|
+
)
|
150
|
+
|
151
|
+
# Set path and venv_path
|
146
152
|
if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
|
147
153
|
base_tasks_path = user_settings.ssh_tasks_dir
|
148
154
|
else:
|
@@ -165,6 +171,8 @@ async def collect_tasks_pip(
|
|
165
171
|
detail=f"Invalid task-group object. Original error: {e}",
|
166
172
|
)
|
167
173
|
|
174
|
+
# Database checks
|
175
|
+
|
168
176
|
# Verify non-duplication constraints
|
169
177
|
await _verify_non_duplication_user_constraint(
|
170
178
|
user_id=user.id,
|
@@ -191,15 +199,18 @@ async def collect_tasks_pip(
|
|
191
199
|
),
|
192
200
|
)
|
193
201
|
|
194
|
-
#
|
202
|
+
# On-disk checks
|
203
|
+
|
195
204
|
if settings.FRACTAL_RUNNER_BACKEND != "slurm_ssh":
|
205
|
+
|
206
|
+
# Verify that folder does not exist (for local collection)
|
196
207
|
if Path(task_group_path).exists():
|
197
208
|
raise HTTPException(
|
198
209
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
199
210
|
detail=f"{task_group_path} already exists.",
|
200
211
|
)
|
201
212
|
|
202
|
-
|
213
|
+
# Verify that wheel file exists
|
203
214
|
wheel_path = task_group_attrs.get("wheel_path", None)
|
204
215
|
if wheel_path is not None:
|
205
216
|
if not Path(wheel_path).exists():
|
@@ -216,13 +227,15 @@ async def collect_tasks_pip(
|
|
216
227
|
db.expunge(task_group)
|
217
228
|
|
218
229
|
# All checks are OK, proceed with task collection
|
219
|
-
|
230
|
+
collection_state_data = dict(
|
220
231
|
status=CollectionStatusV2.PENDING,
|
221
|
-
|
222
|
-
|
232
|
+
package=task_group.pkg_name,
|
233
|
+
version=task_group.version,
|
234
|
+
path=task_group.path,
|
235
|
+
venv_path=task_group.venv_path,
|
223
236
|
)
|
224
237
|
state = CollectionStateV2(
|
225
|
-
data=
|
238
|
+
data=collection_state_data, taskgroupv2_id=task_group.id
|
226
239
|
)
|
227
240
|
db.add(state)
|
228
241
|
await db.commit()
|
@@ -270,7 +283,7 @@ async def collect_tasks_pip(
|
|
270
283
|
reset_logger_handlers(logger)
|
271
284
|
info = (
|
272
285
|
"Collecting tasks in the background. "
|
273
|
-
f"GET /task/collect/{state.id} to query collection status"
|
286
|
+
f"GET /task/collect/{state.id}/ to query collection status"
|
274
287
|
)
|
275
288
|
state.data["info"] = info
|
276
289
|
response.status_code = status.HTTP_201_CREATED
|
@@ -306,20 +319,17 @@ async def check_collection_status(
|
|
306
319
|
else:
|
307
320
|
# Non-SSH mode
|
308
321
|
# In some cases (i.e. a successful or ongoing task collection),
|
309
|
-
# state.data
|
322
|
+
# state.data["log"] is not set; if so, we collect the current logs.
|
310
323
|
if verbose and not state.data.get("log"):
|
311
|
-
if "
|
324
|
+
if "path" not in state.data.keys():
|
312
325
|
await db.close()
|
313
326
|
raise HTTPException(
|
314
327
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
315
328
|
detail=(
|
316
|
-
f"No '
|
329
|
+
f"No 'path' in CollectionStateV2[{state_id}].data"
|
317
330
|
),
|
318
331
|
)
|
319
|
-
state.data["log"] =
|
320
|
-
Path(state.data["venv_path"])
|
321
|
-
)
|
322
|
-
state.data["venv_path"] = str(state.data["venv_path"])
|
332
|
+
state.data["log"] = get_collection_log_v2(Path(state.data["path"]))
|
323
333
|
|
324
334
|
reset_logger_handlers(logger)
|
325
335
|
await db.close()
|
{fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/task_group.py
RENAMED
@@ -143,12 +143,16 @@ async def patch_task_group(
|
|
143
143
|
user_id=user.id,
|
144
144
|
db=db,
|
145
145
|
)
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
146
|
+
if (
|
147
|
+
"user_group_id" in task_group_update.dict(exclude_unset=True)
|
148
|
+
and task_group_update.user_group_id != task_group.user_group_id
|
149
|
+
):
|
150
|
+
await _verify_non_duplication_group_constraint(
|
151
|
+
db=db,
|
152
|
+
pkg_name=task_group.pkg_name,
|
153
|
+
version=task_group.version,
|
154
|
+
user_group_id=task_group_update.user_group_id,
|
155
|
+
)
|
152
156
|
for key, value in task_group_update.dict(exclude_unset=True).items():
|
153
157
|
if (key == "user_group_id") and (value is not None):
|
154
158
|
await _verify_user_belongs_to_group(
|
{fractal_server-2.7.0a4 → fractal_server-2.7.0a6}/fractal_server/app/routes/api/v2/workflow.py
RENAMED
@@ -11,25 +11,21 @@ from ....db import AsyncSession
|
|
11
11
|
from ....db import get_async_db
|
12
12
|
from ....models.v2 import JobV2
|
13
13
|
from ....models.v2 import ProjectV2
|
14
|
-
from ....models.v2 import TaskV2
|
15
14
|
from ....models.v2 import WorkflowV2
|
16
15
|
from ....schemas.v2 import WorkflowCreateV2
|
17
16
|
from ....schemas.v2 import WorkflowExportV2
|
18
|
-
from ....schemas.v2 import WorkflowImportV2
|
19
17
|
from ....schemas.v2 import WorkflowReadV2
|
20
18
|
from ....schemas.v2 import WorkflowReadV2WithWarnings
|
21
|
-
from ....schemas.v2 import WorkflowTaskCreateV2
|
22
19
|
from ....schemas.v2 import WorkflowUpdateV2
|
23
20
|
from ._aux_functions import _check_workflow_exists
|
24
21
|
from ._aux_functions import _get_project_check_owner
|
25
22
|
from ._aux_functions import _get_submitted_jobs_statement
|
26
23
|
from ._aux_functions import _get_workflow_check_owner
|
27
|
-
from ._aux_functions import _workflow_insert_task
|
28
24
|
from ._aux_functions_tasks import _add_warnings_to_workflow_tasks
|
29
25
|
from fractal_server.app.models import UserOAuth
|
26
|
+
from fractal_server.app.models.v2.task import TaskGroupV2
|
30
27
|
from fractal_server.app.routes.auth import current_active_user
|
31
28
|
|
32
|
-
|
33
29
|
router = APIRouter()
|
34
30
|
|
35
31
|
|
@@ -256,85 +252,21 @@ async def export_worfklow(
|
|
256
252
|
user_id=user.id,
|
257
253
|
db=db,
|
258
254
|
)
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
async def import_workflow(
|
268
|
-
project_id: int,
|
269
|
-
workflow: WorkflowImportV2,
|
270
|
-
user: UserOAuth = Depends(current_active_user),
|
271
|
-
db: AsyncSession = Depends(get_async_db),
|
272
|
-
) -> Optional[WorkflowReadV2]:
|
273
|
-
"""
|
274
|
-
Import an existing workflow into a project
|
275
|
-
|
276
|
-
Also create all required objects (i.e. Workflow and WorkflowTask's) along
|
277
|
-
the way.
|
278
|
-
"""
|
279
|
-
|
280
|
-
# Preliminary checks
|
281
|
-
await _get_project_check_owner(
|
282
|
-
project_id=project_id,
|
283
|
-
user_id=user.id,
|
284
|
-
db=db,
|
285
|
-
)
|
286
|
-
|
287
|
-
await _check_workflow_exists(
|
288
|
-
name=workflow.name, project_id=project_id, db=db
|
289
|
-
)
|
290
|
-
|
291
|
-
# Check that all required tasks are available
|
292
|
-
source_to_id = {}
|
293
|
-
|
294
|
-
for wf_task in workflow.task_list:
|
295
|
-
|
296
|
-
source = wf_task.task.source
|
297
|
-
if source not in source_to_id.keys():
|
298
|
-
stm = select(TaskV2).where(TaskV2.source == source)
|
299
|
-
tasks_by_source = (await db.execute(stm)).scalars().all()
|
300
|
-
if len(tasks_by_source) != 1:
|
301
|
-
raise HTTPException(
|
302
|
-
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
303
|
-
detail=(
|
304
|
-
f"Found {len(tasks_by_source)} tasks "
|
305
|
-
f"with {source=}."
|
306
|
-
),
|
307
|
-
)
|
308
|
-
source_to_id[source] = tasks_by_source[0].id
|
309
|
-
|
310
|
-
# Create new Workflow (with empty task_list)
|
311
|
-
db_workflow = WorkflowV2(
|
312
|
-
project_id=project_id,
|
313
|
-
**workflow.dict(exclude_none=True, exclude={"task_list"}),
|
314
|
-
)
|
315
|
-
db.add(db_workflow)
|
316
|
-
await db.commit()
|
317
|
-
await db.refresh(db_workflow)
|
318
|
-
|
319
|
-
# Insert tasks
|
320
|
-
|
321
|
-
for wf_task in workflow.task_list:
|
322
|
-
source = wf_task.task.source
|
323
|
-
task_id = source_to_id[source]
|
324
|
-
|
325
|
-
new_wf_task = WorkflowTaskCreateV2(
|
326
|
-
**wf_task.dict(exclude_none=True, exclude={"task"})
|
327
|
-
)
|
328
|
-
# Insert task
|
329
|
-
await _workflow_insert_task(
|
330
|
-
**new_wf_task.dict(),
|
331
|
-
workflow_id=db_workflow.id,
|
332
|
-
task_id=task_id,
|
333
|
-
db=db,
|
255
|
+
wf_task_list = []
|
256
|
+
for wftask in workflow.task_list:
|
257
|
+
task_group = await db.get(TaskGroupV2, wftask.task.taskgroupv2_id)
|
258
|
+
wf_task_list.append(wftask.dict())
|
259
|
+
wf_task_list[-1]["task"] = dict(
|
260
|
+
pkg_name=task_group.pkg_name,
|
261
|
+
version=task_group.version,
|
262
|
+
name=wftask.task.name,
|
334
263
|
)
|
335
264
|
|
336
|
-
|
337
|
-
|
265
|
+
wf = WorkflowExportV2(
|
266
|
+
**workflow.model_dump(),
|
267
|
+
task_list=wf_task_list,
|
268
|
+
)
|
269
|
+
return wf
|
338
270
|
|
339
271
|
|
340
272
|
@router.get("/workflow/", response_model=list[WorkflowReadV2])
|