fractal-server 2.3.7__tar.gz → 2.3.8__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.3.7 → fractal_server-2.3.8}/PKG-INFO +5 -5
- {fractal_server-2.3.7 → fractal_server-2.3.8}/README.md +2 -3
- fractal_server-2.3.8/fractal_server/__init__.py +1 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/admin/v1.py +2 -3
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/admin/v2.py +2 -3
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/_aux_functions.py +11 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/dataset.py +7 -2
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/job.py +2 -3
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/project.py +5 -10
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/task.py +4 -2
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/task_collection.py +2 -1
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/workflow.py +5 -2
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/workflowtask.py +4 -3
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/job.py +5 -9
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/aux/_job.py +0 -23
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/__init__.py +32 -21
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/config.py +1 -1
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/gunicorn_fractal.py +1 -1
- fractal_server-2.3.8/fractal_server/zip_tools.py +110 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/pyproject.toml +5 -4
- fractal_server-2.3.7/fractal_server/__init__.py +0 -1
- {fractal_server-2.3.7 → fractal_server-2.3.8}/LICENSE +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/__main__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/security.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v1/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v1/dataset.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v1/job.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v1/project.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v1/state.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v1/task.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v1/workflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/collection_state.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/dataset.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/job.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/project.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/task.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/models/v2/workflowtask.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/dataset.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/images.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/project.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/status.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/submit.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/task.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/task_legacy.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/workflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/auth.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/aux/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/aux/_runner.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/.gitignore +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/async_wrap.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/components.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/compress_folder.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/exceptions.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/ssh/executor.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/executors/slurm/sudo/executor.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/extract_archive.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/filenames.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/run_subprocess.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/shutdown.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/task_files.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_common.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_local/executor.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/common.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local/executor.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/runner.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/runner_functions.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/task_interface.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/v2/v1_compat.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/runner/versions.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/_validators.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/user.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/applyworkflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/dataset.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/dumps.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/manifest.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/project.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/state.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/task.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/task_collection.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v1/workflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/dataset.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/dumps.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/job.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/manifest.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/project.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/status.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/task.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/task_collection.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/workflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/security/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/images/models.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/logger.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/main.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/README +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/env.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/script.py.mako +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/py.typed +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/ssh/_fabric.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/syringe.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/utils.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v1/_TaskCollectPip.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v1/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v1/background_operations.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v1/endpoint_operations.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v1/get_collection_data.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v1/utils.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/_TaskCollectPip.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/_venv_pip.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/background_operations.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/background_operations_ssh.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/endpoint_operations.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/templates/_1_create_venv.sh +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/templates/_2_upgrade_pip.sh +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/templates/_3_pip_install.sh +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/templates/_4_pip_freeze.sh +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/templates/_5_pip_show.sh +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/tasks/v2/utils.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/urls.py +0 -0
- {fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fractal-server
|
3
|
-
Version: 2.3.
|
3
|
+
Version: 2.3.8
|
4
4
|
Summary: Server component of the Fractal analytics platform
|
5
5
|
Home-page: https://github.com/fractal-analytics-platform/fractal-server
|
6
6
|
License: BSD-3-Clause
|
@@ -23,7 +23,7 @@ Requires-Dist: bcrypt (==4.0.1)
|
|
23
23
|
Requires-Dist: cloudpickle (>=3.0.0,<3.1.0)
|
24
24
|
Requires-Dist: clusterfutures (>=0.5,<0.6)
|
25
25
|
Requires-Dist: fabric (>=3.2.2,<4.0.0)
|
26
|
-
Requires-Dist: fastapi (>=0.
|
26
|
+
Requires-Dist: fastapi (>=0.112.0,<0.113.0)
|
27
27
|
Requires-Dist: fastapi-users[oauth] (>=12.1.0,<13.0.0)
|
28
28
|
Requires-Dist: gunicorn (>=21.2,<23.0) ; extra == "gunicorn"
|
29
29
|
Requires-Dist: packaging (>=23.2,<24.0)
|
@@ -35,6 +35,7 @@ Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
35
35
|
Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
|
36
36
|
Requires-Dist: sqlmodel (>=0.0.21,<0.0.22)
|
37
37
|
Requires-Dist: uvicorn (>=0.29.0,<0.30.0)
|
38
|
+
Requires-Dist: uvicorn-worker (>=0.2.0,<0.3.0)
|
38
39
|
Project-URL: Changelog, https://github.com/fractal-analytics-platform/fractal-server/blob/main/CHANGELOG.md
|
39
40
|
Project-URL: Documentation, https://fractal-analytics-platform.github.io/fractal-server
|
40
41
|
Project-URL: Repository, https://github.com/fractal-analytics-platform/fractal-server
|
@@ -48,10 +49,9 @@ Description-Content-Type: text/markdown
|
|
48
49
|
[](https://opensource.org/licenses/BSD-3-Clause)
|
49
50
|
[](https://htmlpreview.github.io/?https://github.com/fractal-analytics-platform/fractal-server/blob/benchmark-api/benchmarks/bench.html)
|
50
51
|
|
51
|
-
Fractal is a framework to process
|
52
|
-
prepare it for interactive visualization.
|
52
|
+
[Fractal](https://fractal-analytics-platform.github.io/) is a framework developed at the [BioVisionCenter](https://www.biovisioncenter.uzh.ch/en.html) to process bioimaging data at scale in the OME-Zarr format and prepare the images for interactive visualization.
|
53
53
|
|
54
|
-

|
55
55
|
|
56
56
|
This is the server component of the fractal analytics platform.
|
57
57
|
Find more information about Fractal in general and the other repositories at
|
@@ -6,10 +6,9 @@
|
|
6
6
|
[](https://opensource.org/licenses/BSD-3-Clause)
|
7
7
|
[](https://htmlpreview.github.io/?https://github.com/fractal-analytics-platform/fractal-server/blob/benchmark-api/benchmarks/bench.html)
|
8
8
|
|
9
|
-
Fractal is a framework to process
|
10
|
-
prepare it for interactive visualization.
|
9
|
+
[Fractal](https://fractal-analytics-platform.github.io/) is a framework developed at the [BioVisionCenter](https://www.biovisioncenter.uzh.ch/en.html) to process bioimaging data at scale in the OME-Zarr format and prepare the images for interactive visualization.
|
11
10
|
|
12
|
-

|
13
12
|
|
14
13
|
This is the server component of the fractal analytics platform.
|
15
14
|
Find more information about Fractal in general and the other repositories at
|
@@ -0,0 +1 @@
|
|
1
|
+
__VERSION__ = "2.3.8"
|
@@ -18,6 +18,7 @@ from sqlmodel import select
|
|
18
18
|
from ....config import get_settings
|
19
19
|
from ....syringe import Inject
|
20
20
|
from ....utils import get_timestamp
|
21
|
+
from ....zip_tools import _zip_folder_to_byte_stream_iterator
|
21
22
|
from ...db import AsyncSession
|
22
23
|
from ...db import get_async_db
|
23
24
|
from ...models.security import UserOAuth as User
|
@@ -34,7 +35,6 @@ from ...schemas.v1 import ProjectReadV1
|
|
34
35
|
from ...schemas.v1 import WorkflowReadV1
|
35
36
|
from ...security import current_active_superuser
|
36
37
|
from ..aux._job import _write_shutdown_file
|
37
|
-
from ..aux._job import _zip_folder_to_byte_stream
|
38
38
|
from ..aux._runner import _check_shutdown_is_supported
|
39
39
|
|
40
40
|
router_admin_v1 = APIRouter()
|
@@ -387,9 +387,8 @@ async def download_job_logs(
|
|
387
387
|
# Create and return byte stream for zipped log folder
|
388
388
|
PREFIX_ZIP = Path(job.working_dir).name
|
389
389
|
zip_filename = f"{PREFIX_ZIP}_archive.zip"
|
390
|
-
byte_stream = _zip_folder_to_byte_stream(folder=job.working_dir)
|
391
390
|
return StreamingResponse(
|
392
|
-
|
391
|
+
_zip_folder_to_byte_stream_iterator(folder=job.working_dir),
|
393
392
|
media_type="application/x-zip-compressed",
|
394
393
|
headers={"Content-Disposition": f"attachment;filename={zip_filename}"},
|
395
394
|
)
|
@@ -21,6 +21,7 @@ from sqlmodel import select
|
|
21
21
|
from ....config import get_settings
|
22
22
|
from ....syringe import Inject
|
23
23
|
from ....utils import get_timestamp
|
24
|
+
from ....zip_tools import _zip_folder_to_byte_stream_iterator
|
24
25
|
from ...db import AsyncSession
|
25
26
|
from ...db import get_async_db
|
26
27
|
from ...models.security import UserOAuth as User
|
@@ -37,7 +38,6 @@ from ...schemas.v2 import JobUpdateV2
|
|
37
38
|
from ...schemas.v2 import ProjectReadV2
|
38
39
|
from ...security import current_active_superuser
|
39
40
|
from ..aux._job import _write_shutdown_file
|
40
|
-
from ..aux._job import _zip_folder_to_byte_stream
|
41
41
|
from ..aux._runner import _check_shutdown_is_supported
|
42
42
|
|
43
43
|
router_admin_v2 = APIRouter()
|
@@ -274,9 +274,8 @@ async def download_job_logs(
|
|
274
274
|
# Create and return byte stream for zipped log folder
|
275
275
|
PREFIX_ZIP = Path(job.working_dir).name
|
276
276
|
zip_filename = f"{PREFIX_ZIP}_archive.zip"
|
277
|
-
byte_stream = _zip_folder_to_byte_stream(folder=job.working_dir)
|
278
277
|
return StreamingResponse(
|
279
|
-
|
278
|
+
_zip_folder_to_byte_stream_iterator(folder=job.working_dir),
|
280
279
|
media_type="application/x-zip-compressed",
|
281
280
|
headers={"Content-Disposition": f"attachment;filename={zip_filename}"},
|
282
281
|
)
|
{fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/_aux_functions.py
RENAMED
@@ -11,6 +11,8 @@ from fastapi import status
|
|
11
11
|
from sqlmodel import select
|
12
12
|
from sqlmodel.sql.expression import SelectOfScalar
|
13
13
|
|
14
|
+
from .....config import get_settings
|
15
|
+
from .....syringe import Inject
|
14
16
|
from ....db import AsyncSession
|
15
17
|
from ....models.v1 import ApplyWorkflow
|
16
18
|
from ....models.v1 import Dataset
|
@@ -23,6 +25,15 @@ from ....schemas.v1 import JobStatusTypeV1
|
|
23
25
|
from ....security import User
|
24
26
|
|
25
27
|
|
28
|
+
def _raise_if_v1_is_read_only() -> None:
|
29
|
+
settings = Inject(get_settings)
|
30
|
+
if settings.FRACTAL_API_V1_MODE == "include_read_only":
|
31
|
+
raise HTTPException(
|
32
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
33
|
+
detail="Legacy API is in read-only mode.",
|
34
|
+
)
|
35
|
+
|
36
|
+
|
26
37
|
async def _get_project_check_owner(
|
27
38
|
*,
|
28
39
|
project_id: int,
|
@@ -33,7 +33,7 @@ from ._aux_functions import _get_dataset_check_owner
|
|
33
33
|
from ._aux_functions import _get_project_check_owner
|
34
34
|
from ._aux_functions import _get_submitted_jobs_statement
|
35
35
|
from ._aux_functions import _get_workflow_check_owner
|
36
|
-
|
36
|
+
from ._aux_functions import _raise_if_v1_is_read_only
|
37
37
|
|
38
38
|
router = APIRouter()
|
39
39
|
|
@@ -52,6 +52,7 @@ async def create_dataset(
|
|
52
52
|
"""
|
53
53
|
Add new dataset to current project
|
54
54
|
"""
|
55
|
+
_raise_if_v1_is_read_only()
|
55
56
|
await _get_project_check_owner(
|
56
57
|
project_id=project_id, user_id=user.id, db=db
|
57
58
|
)
|
@@ -133,7 +134,7 @@ async def update_dataset(
|
|
133
134
|
"""
|
134
135
|
Edit a dataset associated to the current project
|
135
136
|
"""
|
136
|
-
|
137
|
+
_raise_if_v1_is_read_only()
|
137
138
|
if dataset_update.history is not None:
|
138
139
|
raise HTTPException(
|
139
140
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
@@ -170,6 +171,7 @@ async def delete_dataset(
|
|
170
171
|
"""
|
171
172
|
Delete a dataset associated to the current project
|
172
173
|
"""
|
174
|
+
_raise_if_v1_is_read_only()
|
173
175
|
output = await _get_dataset_check_owner(
|
174
176
|
project_id=project_id,
|
175
177
|
dataset_id=dataset_id,
|
@@ -243,6 +245,7 @@ async def create_resource(
|
|
243
245
|
"""
|
244
246
|
Add resource to an existing dataset
|
245
247
|
"""
|
248
|
+
_raise_if_v1_is_read_only()
|
246
249
|
output = await _get_dataset_check_owner(
|
247
250
|
project_id=project_id,
|
248
251
|
dataset_id=dataset_id,
|
@@ -299,6 +302,7 @@ async def update_resource(
|
|
299
302
|
"""
|
300
303
|
Edit a resource of a dataset
|
301
304
|
"""
|
305
|
+
_raise_if_v1_is_read_only()
|
302
306
|
output = await _get_dataset_check_owner(
|
303
307
|
project_id=project_id,
|
304
308
|
dataset_id=dataset_id,
|
@@ -339,6 +343,7 @@ async def delete_resource(
|
|
339
343
|
"""
|
340
344
|
Delete a resource of a dataset
|
341
345
|
"""
|
346
|
+
_raise_if_v1_is_read_only()
|
342
347
|
# Get the dataset DB entry
|
343
348
|
output = await _get_dataset_check_owner(
|
344
349
|
project_id=project_id,
|
@@ -8,6 +8,7 @@ from fastapi import status
|
|
8
8
|
from fastapi.responses import StreamingResponse
|
9
9
|
from sqlmodel import select
|
10
10
|
|
11
|
+
from .....zip_tools import _zip_folder_to_byte_stream_iterator
|
11
12
|
from ....db import AsyncSession
|
12
13
|
from ....db import get_async_db
|
13
14
|
from ....models.v1 import ApplyWorkflow
|
@@ -18,7 +19,6 @@ from ....schemas.v1 import ApplyWorkflowReadV1
|
|
18
19
|
from ....security import current_active_user
|
19
20
|
from ....security import User
|
20
21
|
from ...aux._job import _write_shutdown_file
|
21
|
-
from ...aux._job import _zip_folder_to_byte_stream
|
22
22
|
from ...aux._runner import _check_shutdown_is_supported
|
23
23
|
from ._aux_functions import _get_job_check_owner
|
24
24
|
from ._aux_functions import _get_project_check_owner
|
@@ -128,9 +128,8 @@ async def download_job_logs(
|
|
128
128
|
# Create and return byte stream for zipped log folder
|
129
129
|
PREFIX_ZIP = Path(job.working_dir).name
|
130
130
|
zip_filename = f"{PREFIX_ZIP}_archive.zip"
|
131
|
-
byte_stream = _zip_folder_to_byte_stream(folder=job.working_dir)
|
132
131
|
return StreamingResponse(
|
133
|
-
|
132
|
+
_zip_folder_to_byte_stream_iterator(folder=job.working_dir),
|
134
133
|
media_type="application/x-zip-compressed",
|
135
134
|
headers={"Content-Disposition": f"attachment;filename={zip_filename}"},
|
136
135
|
)
|
@@ -42,6 +42,7 @@ from ._aux_functions import _get_dataset_check_owner
|
|
42
42
|
from ._aux_functions import _get_project_check_owner
|
43
43
|
from ._aux_functions import _get_submitted_jobs_statement
|
44
44
|
from ._aux_functions import _get_workflow_check_owner
|
45
|
+
from ._aux_functions import _raise_if_v1_is_read_only
|
45
46
|
from ._aux_functions import clean_app_job_list_v1
|
46
47
|
|
47
48
|
router = APIRouter()
|
@@ -80,7 +81,7 @@ async def create_project(
|
|
80
81
|
"""
|
81
82
|
Create new poject
|
82
83
|
"""
|
83
|
-
|
84
|
+
_raise_if_v1_is_read_only()
|
84
85
|
# Check that there is no project with the same user and name
|
85
86
|
await _check_project_exists(
|
86
87
|
project_name=project.name, user_id=user.id, db=db
|
@@ -120,6 +121,7 @@ async def update_project(
|
|
120
121
|
user: User = Depends(current_active_user),
|
121
122
|
db: AsyncSession = Depends(get_async_db),
|
122
123
|
):
|
124
|
+
_raise_if_v1_is_read_only()
|
123
125
|
project = await _get_project_check_owner(
|
124
126
|
project_id=project_id, user_id=user.id, db=db
|
125
127
|
)
|
@@ -148,6 +150,7 @@ async def delete_project(
|
|
148
150
|
"""
|
149
151
|
Delete project
|
150
152
|
"""
|
153
|
+
_raise_if_v1_is_read_only()
|
151
154
|
project = await _get_project_check_owner(
|
152
155
|
project_id=project_id, user_id=user.id, db=db
|
153
156
|
)
|
@@ -249,16 +252,8 @@ async def apply_workflow(
|
|
249
252
|
user: User = Depends(current_active_verified_user),
|
250
253
|
db: AsyncSession = Depends(get_async_db),
|
251
254
|
) -> Optional[ApplyWorkflowReadV1]:
|
252
|
-
|
255
|
+
_raise_if_v1_is_read_only()
|
253
256
|
settings = Inject(get_settings)
|
254
|
-
if settings.FRACTAL_API_V1_MODE == "include_without_submission":
|
255
|
-
raise HTTPException(
|
256
|
-
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
257
|
-
detail=(
|
258
|
-
"Legacy API is still accessible, "
|
259
|
-
"but the submission of legacy jobs is not available."
|
260
|
-
),
|
261
|
-
)
|
262
257
|
|
263
258
|
# Remove non-submitted V1 jobs from the app state when the list grows
|
264
259
|
# beyond a threshold
|
@@ -21,6 +21,7 @@ from ....security import current_active_user
|
|
21
21
|
from ....security import current_active_verified_user
|
22
22
|
from ....security import User
|
23
23
|
from ._aux_functions import _get_task_check_owner
|
24
|
+
from ._aux_functions import _raise_if_v1_is_read_only
|
24
25
|
|
25
26
|
router = APIRouter()
|
26
27
|
|
@@ -75,7 +76,7 @@ async def patch_task(
|
|
75
76
|
"""
|
76
77
|
Edit a specific task (restricted to superusers and task owner)
|
77
78
|
"""
|
78
|
-
|
79
|
+
_raise_if_v1_is_read_only()
|
79
80
|
if task_update.source:
|
80
81
|
raise HTTPException(
|
81
82
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
@@ -121,6 +122,7 @@ async def create_task(
|
|
121
122
|
"""
|
122
123
|
Create a new task
|
123
124
|
"""
|
125
|
+
_raise_if_v1_is_read_only()
|
124
126
|
# Set task.owner attribute
|
125
127
|
if user.username:
|
126
128
|
owner = user.username
|
@@ -174,7 +176,7 @@ async def delete_task(
|
|
174
176
|
"""
|
175
177
|
Delete a task
|
176
178
|
"""
|
177
|
-
|
179
|
+
_raise_if_v1_is_read_only()
|
178
180
|
db_task = await _get_task_check_owner(task_id=task_id, user=user, db=db)
|
179
181
|
|
180
182
|
# Check that the Task is not in relationship with some WorkflowTask
|
{fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/task_collection.py
RENAMED
@@ -25,6 +25,7 @@ from ....schemas.v1 import TaskCollectStatusV1
|
|
25
25
|
from ....security import current_active_user
|
26
26
|
from ....security import current_active_verified_user
|
27
27
|
from ....security import User
|
28
|
+
from ._aux_functions import _raise_if_v1_is_read_only
|
28
29
|
from fractal_server.string_tools import slugify_task_name_for_source
|
29
30
|
from fractal_server.tasks.utils import get_collection_log
|
30
31
|
from fractal_server.tasks.v1._TaskCollectPip import _TaskCollectPip
|
@@ -71,7 +72,7 @@ async def collect_tasks_pip(
|
|
71
72
|
Trigger the creation of a dedicated virtual environment, the installation
|
72
73
|
of a package and the collection of tasks as advertised in the manifest.
|
73
74
|
"""
|
74
|
-
|
75
|
+
_raise_if_v1_is_read_only()
|
75
76
|
logger = set_logger(logger_name="collect_tasks_pip")
|
76
77
|
|
77
78
|
# Validate payload as _TaskCollectPip, which has more strict checks than
|
@@ -39,6 +39,7 @@ from ._aux_functions import _check_workflow_exists
|
|
39
39
|
from ._aux_functions import _get_project_check_owner
|
40
40
|
from ._aux_functions import _get_submitted_jobs_statement
|
41
41
|
from ._aux_functions import _get_workflow_check_owner
|
42
|
+
from ._aux_functions import _raise_if_v1_is_read_only
|
42
43
|
from ._aux_functions import _workflow_insert_task
|
43
44
|
|
44
45
|
|
@@ -84,6 +85,7 @@ async def create_workflow(
|
|
84
85
|
"""
|
85
86
|
Create a workflow, associate to a project
|
86
87
|
"""
|
88
|
+
_raise_if_v1_is_read_only()
|
87
89
|
await _get_project_check_owner(
|
88
90
|
project_id=project_id,
|
89
91
|
user_id=user.id,
|
@@ -136,6 +138,7 @@ async def update_workflow(
|
|
136
138
|
"""
|
137
139
|
Edit a workflow
|
138
140
|
"""
|
141
|
+
_raise_if_v1_is_read_only()
|
139
142
|
workflow = await _get_workflow_check_owner(
|
140
143
|
project_id=project_id, workflow_id=workflow_id, user_id=user.id, db=db
|
141
144
|
)
|
@@ -187,7 +190,7 @@ async def delete_workflow(
|
|
187
190
|
"""
|
188
191
|
Delete a workflow
|
189
192
|
"""
|
190
|
-
|
193
|
+
_raise_if_v1_is_read_only()
|
191
194
|
workflow = await _get_workflow_check_owner(
|
192
195
|
project_id=project_id, workflow_id=workflow_id, user_id=user.id, db=db
|
193
196
|
)
|
@@ -275,7 +278,7 @@ async def import_workflow(
|
|
275
278
|
Also create all required objects (i.e. Workflow and WorkflowTask's) along
|
276
279
|
the way.
|
277
280
|
"""
|
278
|
-
|
281
|
+
_raise_if_v1_is_read_only()
|
279
282
|
# Preliminary checks
|
280
283
|
await _get_project_check_owner(
|
281
284
|
project_id=project_id,
|
{fractal_server-2.3.7 → fractal_server-2.3.8}/fractal_server/app/routes/api/v1/workflowtask.py
RENAMED
@@ -30,6 +30,7 @@ from ....security import current_active_user
|
|
30
30
|
from ....security import User
|
31
31
|
from ._aux_functions import _get_workflow_check_owner
|
32
32
|
from ._aux_functions import _get_workflow_task_check_owner
|
33
|
+
from ._aux_functions import _raise_if_v1_is_read_only
|
33
34
|
from ._aux_functions import _workflow_insert_task
|
34
35
|
|
35
36
|
router = APIRouter()
|
@@ -51,7 +52,7 @@ async def create_workflowtask(
|
|
51
52
|
"""
|
52
53
|
Add a WorkflowTask to a Workflow
|
53
54
|
"""
|
54
|
-
|
55
|
+
_raise_if_v1_is_read_only()
|
55
56
|
workflow = await _get_workflow_check_owner(
|
56
57
|
project_id=project_id, workflow_id=workflow_id, user_id=user.id, db=db
|
57
58
|
)
|
@@ -112,7 +113,7 @@ async def update_workflowtask(
|
|
112
113
|
"""
|
113
114
|
Edit a WorkflowTask of a Workflow
|
114
115
|
"""
|
115
|
-
|
116
|
+
_raise_if_v1_is_read_only()
|
116
117
|
db_workflow_task, db_workflow = await _get_workflow_task_check_owner(
|
117
118
|
project_id=project_id,
|
118
119
|
workflow_task_id=workflow_task_id,
|
@@ -167,7 +168,7 @@ async def delete_workflowtask(
|
|
167
168
|
"""
|
168
169
|
Delete a WorkflowTask of a Workflow
|
169
170
|
"""
|
170
|
-
|
171
|
+
_raise_if_v1_is_read_only()
|
171
172
|
db_workflow_task, db_workflow = await _get_workflow_task_check_owner(
|
172
173
|
project_id=project_id,
|
173
174
|
workflow_task_id=workflow_task_id,
|
@@ -8,6 +8,7 @@ from fastapi import status
|
|
8
8
|
from fastapi.responses import StreamingResponse
|
9
9
|
from sqlmodel import select
|
10
10
|
|
11
|
+
from .....zip_tools import _zip_folder_to_byte_stream_iterator
|
11
12
|
from ....db import AsyncSession
|
12
13
|
from ....db import get_async_db
|
13
14
|
from ....models.v2 import JobV2
|
@@ -18,7 +19,6 @@ from ....schemas.v2 import JobStatusTypeV2
|
|
18
19
|
from ....security import current_active_user
|
19
20
|
from ....security import User
|
20
21
|
from ...aux._job import _write_shutdown_file
|
21
|
-
from ...aux._job import _zip_folder_to_byte_stream
|
22
22
|
from ...aux._runner import _check_shutdown_is_supported
|
23
23
|
from ._aux_functions import _get_job_check_owner
|
24
24
|
from ._aux_functions import _get_project_check_owner
|
@@ -118,7 +118,7 @@ async def download_job_logs(
|
|
118
118
|
db: AsyncSession = Depends(get_async_db),
|
119
119
|
) -> StreamingResponse:
|
120
120
|
"""
|
121
|
-
Download job folder
|
121
|
+
Download zipped job folder
|
122
122
|
"""
|
123
123
|
output = await _get_job_check_owner(
|
124
124
|
project_id=project_id,
|
@@ -127,15 +127,11 @@ async def download_job_logs(
|
|
127
127
|
db=db,
|
128
128
|
)
|
129
129
|
job = output["job"]
|
130
|
-
|
131
|
-
# Create and return byte stream for zipped log folder
|
132
|
-
PREFIX_ZIP = Path(job.working_dir).name
|
133
|
-
zip_filename = f"{PREFIX_ZIP}_archive.zip"
|
134
|
-
byte_stream = _zip_folder_to_byte_stream(folder=job.working_dir)
|
130
|
+
zip_name = f"{Path(job.working_dir).name}_archive.zip"
|
135
131
|
return StreamingResponse(
|
136
|
-
|
132
|
+
_zip_folder_to_byte_stream_iterator(folder=job.working_dir),
|
137
133
|
media_type="application/x-zip-compressed",
|
138
|
-
headers={"Content-Disposition": f"attachment;filename={
|
134
|
+
headers={"Content-Disposition": f"attachment;filename={zip_name}"},
|
139
135
|
)
|
140
136
|
|
141
137
|
|
@@ -1,9 +1,5 @@
|
|
1
|
-
import os
|
2
|
-
from io import BytesIO
|
3
1
|
from pathlib import Path
|
4
2
|
from typing import Union
|
5
|
-
from zipfile import ZIP_DEFLATED
|
6
|
-
from zipfile import ZipFile
|
7
3
|
|
8
4
|
from ...models.v1 import ApplyWorkflow
|
9
5
|
from ...models.v2 import JobV2
|
@@ -24,22 +20,3 @@ def _write_shutdown_file(*, job: Union[ApplyWorkflow, JobV2]):
|
|
24
20
|
shutdown_file = Path(job.working_dir) / SHUTDOWN_FILENAME
|
25
21
|
with shutdown_file.open("w") as f:
|
26
22
|
f.write(f"Trigger executor shutdown for {job.id=}.")
|
27
|
-
|
28
|
-
|
29
|
-
def _zip_folder_to_byte_stream(*, folder: str) -> BytesIO:
|
30
|
-
"""
|
31
|
-
Get byte stream with the zipped log folder of a job.
|
32
|
-
|
33
|
-
Args:
|
34
|
-
folder: the folder to zip
|
35
|
-
"""
|
36
|
-
|
37
|
-
byte_stream = BytesIO()
|
38
|
-
with ZipFile(byte_stream, mode="w", compression=ZIP_DEFLATED) as zipfile:
|
39
|
-
for root, dirs, files in os.walk(folder):
|
40
|
-
for file in files:
|
41
|
-
file_path = os.path.join(root, file)
|
42
|
-
archive_path = os.path.relpath(file_path, folder)
|
43
|
-
zipfile.write(file_path, archive_path)
|
44
|
-
|
45
|
-
return byte_stream
|
@@ -5,7 +5,6 @@ This module is the single entry point to the runner backend subsystem V2.
|
|
5
5
|
Other subystems should only import this module and not its submodules or
|
6
6
|
the individual backends.
|
7
7
|
"""
|
8
|
-
import logging
|
9
8
|
import os
|
10
9
|
import traceback
|
11
10
|
from pathlib import Path
|
@@ -21,6 +20,7 @@ from ....logger import set_logger
|
|
21
20
|
from ....ssh._fabric import FractalSSH
|
22
21
|
from ....syringe import Inject
|
23
22
|
from ....utils import get_timestamp
|
23
|
+
from ....zip_tools import _zip_folder_to_file_and_remove
|
24
24
|
from ...db import DB
|
25
25
|
from ...models.v2 import DatasetV2
|
26
26
|
from ...models.v2 import JobV2
|
@@ -114,9 +114,34 @@ async def submit_workflow(
|
|
114
114
|
|
115
115
|
with next(DB.get_sync_db()) as db_sync:
|
116
116
|
|
117
|
-
|
118
|
-
|
117
|
+
try:
|
118
|
+
job: Optional[JobV2] = db_sync.get(JobV2, job_id)
|
119
|
+
dataset: Optional[DatasetV2] = db_sync.get(DatasetV2, dataset_id)
|
120
|
+
workflow: Optional[WorkflowV2] = db_sync.get(
|
121
|
+
WorkflowV2, workflow_id
|
122
|
+
)
|
123
|
+
except Exception as e:
|
124
|
+
logger.error(
|
125
|
+
f"Error conneting to the database. Original error: {str(e)}"
|
126
|
+
)
|
127
|
+
reset_logger_handlers(logger)
|
128
|
+
return
|
129
|
+
|
130
|
+
if job is None:
|
119
131
|
logger.error(f"JobV2 {job_id} does not exist")
|
132
|
+
reset_logger_handlers(logger)
|
133
|
+
return
|
134
|
+
if dataset is None or workflow is None:
|
135
|
+
log_msg = ""
|
136
|
+
if not dataset:
|
137
|
+
log_msg += f"Cannot fetch dataset {dataset_id} from database\n"
|
138
|
+
if not workflow:
|
139
|
+
log_msg += (
|
140
|
+
f"Cannot fetch workflow {workflow_id} from database\n"
|
141
|
+
)
|
142
|
+
fail_job(
|
143
|
+
db=db_sync, job=job, log_msg=log_msg, logger_name=logger_name
|
144
|
+
)
|
120
145
|
return
|
121
146
|
|
122
147
|
# Declare runner backend and set `process_workflow` function
|
@@ -137,21 +162,6 @@ async def submit_workflow(
|
|
137
162
|
)
|
138
163
|
return
|
139
164
|
|
140
|
-
dataset: DatasetV2 = db_sync.get(DatasetV2, dataset_id)
|
141
|
-
workflow: WorkflowV2 = db_sync.get(WorkflowV2, workflow_id)
|
142
|
-
if not (dataset and workflow):
|
143
|
-
log_msg = ""
|
144
|
-
if not dataset:
|
145
|
-
log_msg += f"Cannot fetch dataset {dataset_id} from database\n"
|
146
|
-
if not workflow:
|
147
|
-
log_msg += (
|
148
|
-
f"Cannot fetch workflow {workflow_id} from database\n"
|
149
|
-
)
|
150
|
-
fail_job(
|
151
|
-
db=db_sync, job=job, log_msg=log_msg, logger_name=logger_name
|
152
|
-
)
|
153
|
-
return
|
154
|
-
|
155
165
|
# Define and create server-side working folder
|
156
166
|
WORKFLOW_DIR_LOCAL = Path(job.working_dir)
|
157
167
|
if WORKFLOW_DIR_LOCAL.exists():
|
@@ -192,9 +202,9 @@ async def submit_workflow(
|
|
192
202
|
fractal_ssh.mkdir(
|
193
203
|
folder=str(WORKFLOW_DIR_REMOTE),
|
194
204
|
)
|
195
|
-
|
205
|
+
logger.info(f"Created {str(WORKFLOW_DIR_REMOTE)} via SSH.")
|
196
206
|
else:
|
197
|
-
|
207
|
+
logger.error(
|
198
208
|
"Invalid FRACTAL_RUNNER_BACKEND="
|
199
209
|
f"{settings.FRACTAL_RUNNER_BACKEND}."
|
200
210
|
)
|
@@ -219,7 +229,7 @@ async def submit_workflow(
|
|
219
229
|
user=slurm_user,
|
220
230
|
)
|
221
231
|
else:
|
222
|
-
|
232
|
+
logger.info("Skip remote-subfolder creation")
|
223
233
|
except Exception as e:
|
224
234
|
error_type = type(e).__name__
|
225
235
|
fail_job(
|
@@ -448,3 +458,4 @@ async def submit_workflow(
|
|
448
458
|
finally:
|
449
459
|
reset_logger_handlers(logger)
|
450
460
|
db_sync.close()
|
461
|
+
_zip_folder_to_file_and_remove(folder=job.working_dir)
|