fractal-server 2.12.1__tar.gz → 2.13.1__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.12.1 → fractal_server-2.13.1}/PKG-INFO +9 -10
- fractal_server-2.13.1/fractal_server/__init__.py +1 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/security.py +9 -12
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/__init__.py +4 -0
- fractal_server-2.13.1/fractal_server/app/models/v2/accounting.py +35 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/dataset.py +2 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/job.py +11 -9
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/task.py +2 -3
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/task_group.py +6 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/workflowtask.py +15 -8
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/__init__.py +4 -0
- fractal_server-2.13.1/fractal_server/app/routes/admin/v2/accounting.py +108 -0
- fractal_server-2.13.1/fractal_server/app/routes/admin/v2/impersonate.py +35 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/job.py +5 -13
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/task.py +1 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/task_group.py +5 -13
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +3 -3
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/dataset.py +4 -4
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/images.py +11 -11
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/project.py +2 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/status.py +1 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/submit.py +9 -6
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/task.py +4 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/task_collection.py +3 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/task_group.py +4 -7
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/workflow.py +3 -3
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/workflow_import.py +3 -3
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/workflowtask.py +3 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/_aux_auth.py +4 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/current_user.py +3 -5
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/group.py +1 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/users.py +2 -4
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/aux/_runner.py +1 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/aux/validate_user_settings.py +1 -2
- fractal_server-2.13.1/fractal_server/app/runner/executors/_job_states.py +13 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/_slurm_config.py +26 -18
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +31 -22
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +2 -5
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/ssh/executor.py +21 -27
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +1 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +37 -47
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/sudo/executor.py +25 -24
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/__init__.py +4 -9
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_local/__init__.py +3 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_local/_local_config.py +5 -4
- fractal_server-2.13.1/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +4 -4
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +2 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +4 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/deduplicate_list.py +1 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/runner.py +25 -10
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/runner_functions.py +12 -11
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/task_interface.py +15 -7
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/_filter_validators.py +6 -3
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/_validators.py +7 -5
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/user.py +23 -18
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/user_group.py +25 -11
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/user_settings.py +31 -24
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/__init__.py +1 -0
- fractal_server-2.13.1/fractal_server/app/schemas/v2/accounting.py +18 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/dataset.py +48 -35
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/dumps.py +16 -14
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/job.py +49 -29
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/manifest.py +32 -28
- fractal_server-2.13.1/fractal_server/app/schemas/v2/project.py +39 -0
- fractal_server-2.13.1/fractal_server/app/schemas/v2/task.py +222 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/task_collection.py +41 -30
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/task_group.py +39 -20
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/workflow.py +24 -12
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/workflowtask.py +63 -61
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/security/__init__.py +1 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/config.py +86 -73
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/images/models.py +18 -12
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/main.py +1 -1
- fractal_server-2.13.1/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +57 -0
- fractal_server-2.13.1/fractal_server/py.typed +0 -0
- fractal_server-2.13.1/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/utils_background.py +2 -2
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/utils_database.py +1 -1
- {fractal_server-2.12.1 → fractal_server-2.13.1}/pyproject.toml +11 -12
- fractal_server-2.12.1/fractal_server/__init__.py +0 -1
- fractal_server-2.12.1/fractal_server/app/routes/aux/__init__.py +0 -20
- fractal_server-2.12.1/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -3
- fractal_server-2.12.1/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -3
- fractal_server-2.12.1/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -121
- fractal_server-2.12.1/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -108
- fractal_server-2.12.1/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -42
- fractal_server-2.12.1/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -157
- fractal_server-2.12.1/fractal_server/app/schemas/v2/project.py +0 -29
- fractal_server-2.12.1/fractal_server/app/schemas/v2/task.py +0 -211
- {fractal_server-2.12.1 → fractal_server-2.13.1}/LICENSE +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/README.md +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/__main__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/linkusergroup.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/user_settings.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/project.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/project.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/job.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/login.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/oauth.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/register.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/auth/router.py +0 -0
- {fractal_server-2.12.1/fractal_server/app/runner → fractal_server-2.13.1/fractal_server/app/routes/aux}/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/aux/_job.py +0 -0
- {fractal_server-2.12.1/fractal_server/app/runner/executors → fractal_server-2.13.1/fractal_server/app/runner}/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/components.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/compress_folder.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/exceptions.py +0 -0
- {fractal_server-2.12.1/fractal_server/app/runner/executors/slurm → fractal_server-2.13.1/fractal_server/app/runner/executors}/__init__.py +0 -0
- {fractal_server-2.12.1/fractal_server/app/runner/v2/_slurm_common → fractal_server-2.13.1/fractal_server/app/runner/executors/slurm}/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
- {fractal_server-2.12.1/fractal_server/tasks/v2 → fractal_server-2.13.1/fractal_server/app/runner/executors/slurm/ssh}/__init__.py +0 -0
- /fractal_server-2.12.1/fractal_server/py.typed → /fractal_server-2.13.1/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/executors/slurm/utils_executors.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/extract_archive.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/filenames.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/run_subprocess.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/shutdown.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/task_files.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_local/executor.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/runner/versions.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/schemas/v2/status.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/security/signup_email.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/user_settings.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/data_migrations/tools.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/gunicorn_fractal.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/logger.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/env.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/naming_convention.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/ssh/_fabric.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/syringe.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/utils.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/local/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/local/_utils.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/local/collect.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/local/deactivate.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/local/reactivate.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/ssh/collect.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/utils_package_names.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/tasks/v2/utils_templates.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/urls.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/utils.py +0 -0
- {fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/zip_tools.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: fractal-server
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.13.1
|
4
4
|
Summary: Backend component of the Fractal analytics platform
|
5
5
|
Home-page: https://github.com/fractal-analytics-platform/fractal-server
|
6
6
|
License: BSD-3-Clause
|
@@ -13,22 +13,21 @@ Classifier: Programming Language :: Python :: 3.10
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
15
15
|
Requires-Dist: alembic (>=1.13.1,<2.0.0)
|
16
|
-
Requires-Dist: cloudpickle (>=3.
|
17
|
-
Requires-Dist:
|
18
|
-
Requires-Dist: cryptography (>=44.0.0,<44.1.0)
|
16
|
+
Requires-Dist: cloudpickle (>=3.1.0,<3.2.0)
|
17
|
+
Requires-Dist: cryptography (>=44.0.1,<44.1.0)
|
19
18
|
Requires-Dist: fabric (>=3.2.2,<3.3.0)
|
20
19
|
Requires-Dist: fastapi (>=0.115.0,<0.116.0)
|
21
20
|
Requires-Dist: fastapi-users[oauth] (>=14,<15)
|
22
|
-
Requires-Dist: gunicorn (>=
|
23
|
-
Requires-Dist: packaging (>=
|
24
|
-
Requires-Dist: psutil (==5.9.8)
|
21
|
+
Requires-Dist: gunicorn (>=23.0,<24.0)
|
22
|
+
Requires-Dist: packaging (>=24.0.0,<25.0.0)
|
25
23
|
Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0)
|
26
|
-
Requires-Dist: pydantic (>=
|
24
|
+
Requires-Dist: pydantic (>=2.10.0,<2.11.0)
|
25
|
+
Requires-Dist: pydantic-settings (>=2.7.0)
|
27
26
|
Requires-Dist: python-dotenv (>=1.0.0,<1.1.0)
|
28
27
|
Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
|
29
|
-
Requires-Dist: sqlmodel (==0.0.
|
28
|
+
Requires-Dist: sqlmodel (==0.0.22)
|
30
29
|
Requires-Dist: uvicorn (>=0.29.0,<0.35.0)
|
31
|
-
Requires-Dist: uvicorn-worker (==0.
|
30
|
+
Requires-Dist: uvicorn-worker (==0.3.0)
|
32
31
|
Project-URL: Documentation, https://fractal-analytics-platform.github.io/fractal-server
|
33
32
|
Project-URL: Repository, https://github.com/fractal-analytics-platform/fractal-server
|
34
33
|
Project-URL: changelog, https://github.com/fractal-analytics-platform/fractal-server/blob/main/CHANGELOG.md
|
@@ -0,0 +1 @@
|
|
1
|
+
__VERSION__ = "2.13.1"
|
@@ -12,6 +12,7 @@
|
|
12
12
|
from datetime import datetime
|
13
13
|
from typing import Optional
|
14
14
|
|
15
|
+
from pydantic import ConfigDict
|
15
16
|
from pydantic import EmailStr
|
16
17
|
from sqlalchemy import Column
|
17
18
|
from sqlalchemy.types import DateTime
|
@@ -50,13 +51,11 @@ class OAuthAccount(SQLModel, table=True):
|
|
50
51
|
user: Optional["UserOAuth"] = Relationship(back_populates="oauth_accounts")
|
51
52
|
oauth_name: str = Field(index=True, nullable=False)
|
52
53
|
access_token: str = Field(nullable=False)
|
53
|
-
expires_at: Optional[int] = Field(nullable=True)
|
54
|
-
refresh_token: Optional[str] = Field(nullable=True)
|
54
|
+
expires_at: Optional[int] = Field(nullable=True, default=None)
|
55
|
+
refresh_token: Optional[str] = Field(nullable=True, default=None)
|
55
56
|
account_id: str = Field(index=True, nullable=False)
|
56
57
|
account_email: str = Field(nullable=False)
|
57
|
-
|
58
|
-
class Config:
|
59
|
-
orm_mode = True
|
58
|
+
model_config = ConfigDict(from_attributes=True)
|
60
59
|
|
61
60
|
|
62
61
|
class UserOAuth(SQLModel, table=True):
|
@@ -88,11 +87,11 @@ class UserOAuth(SQLModel, table=True):
|
|
88
87
|
sa_column_kwargs={"unique": True, "index": True}, nullable=False
|
89
88
|
)
|
90
89
|
hashed_password: str
|
91
|
-
is_active: bool = Field(True, nullable=False)
|
92
|
-
is_superuser: bool = Field(False, nullable=False)
|
93
|
-
is_verified: bool = Field(False, nullable=False)
|
90
|
+
is_active: bool = Field(default=True, nullable=False)
|
91
|
+
is_superuser: bool = Field(default=False, nullable=False)
|
92
|
+
is_verified: bool = Field(default=False, nullable=False)
|
94
93
|
|
95
|
-
username: Optional[str]
|
94
|
+
username: Optional[str] = None
|
96
95
|
|
97
96
|
oauth_accounts: list["OAuthAccount"] = Relationship(
|
98
97
|
back_populates="user",
|
@@ -105,9 +104,7 @@ class UserOAuth(SQLModel, table=True):
|
|
105
104
|
settings: Optional[UserSettings] = Relationship(
|
106
105
|
sa_relationship_kwargs=dict(lazy="selectin", cascade="all, delete")
|
107
106
|
)
|
108
|
-
|
109
|
-
class Config:
|
110
|
-
orm_mode = True
|
107
|
+
model_config = ConfigDict(from_attributes=True)
|
111
108
|
|
112
109
|
|
113
110
|
class UserGroup(SQLModel, table=True):
|
@@ -2,6 +2,8 @@
|
|
2
2
|
v2 `models` module
|
3
3
|
"""
|
4
4
|
from ..linkuserproject import LinkUserProjectV2
|
5
|
+
from .accounting import AccountingRecord
|
6
|
+
from .accounting import AccountingRecordSlurm
|
5
7
|
from .dataset import DatasetV2
|
6
8
|
from .job import JobV2
|
7
9
|
from .project import ProjectV2
|
@@ -12,6 +14,8 @@ from .workflow import WorkflowV2
|
|
12
14
|
from .workflowtask import WorkflowTaskV2
|
13
15
|
|
14
16
|
__all__ = [
|
17
|
+
"AccountingRecord",
|
18
|
+
"AccountingRecordSlurm",
|
15
19
|
"LinkUserProjectV2",
|
16
20
|
"DatasetV2",
|
17
21
|
"JobV2",
|
@@ -0,0 +1,35 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
from sqlalchemy import Column
|
5
|
+
from sqlalchemy import Integer
|
6
|
+
from sqlalchemy.dialects.postgresql import ARRAY
|
7
|
+
from sqlalchemy.types import DateTime
|
8
|
+
from sqlmodel import Field
|
9
|
+
from sqlmodel import SQLModel
|
10
|
+
|
11
|
+
from ....utils import get_timestamp
|
12
|
+
|
13
|
+
|
14
|
+
class AccountingRecord(SQLModel, table=True):
|
15
|
+
id: Optional[int] = Field(default=None, primary_key=True)
|
16
|
+
user_id: int = Field(foreign_key="user_oauth.id", nullable=False)
|
17
|
+
timestamp: datetime = Field(
|
18
|
+
default_factory=get_timestamp,
|
19
|
+
sa_column=Column(DateTime(timezone=True), nullable=False),
|
20
|
+
)
|
21
|
+
num_tasks: int
|
22
|
+
num_new_images: int
|
23
|
+
|
24
|
+
|
25
|
+
class AccountingRecordSlurm(SQLModel, table=True):
|
26
|
+
id: Optional[int] = Field(default=None, primary_key=True)
|
27
|
+
user_id: int = Field(foreign_key="user_oauth.id", nullable=False)
|
28
|
+
timestamp: datetime = Field(
|
29
|
+
default_factory=get_timestamp,
|
30
|
+
sa_column=Column(DateTime(timezone=True), nullable=False),
|
31
|
+
)
|
32
|
+
slurm_job_ids: list[int] = Field(
|
33
|
+
default_factory=list,
|
34
|
+
sa_column=Column(ARRAY(Integer)),
|
35
|
+
)
|
@@ -2,6 +2,7 @@ from datetime import datetime
|
|
2
2
|
from typing import Any
|
3
3
|
from typing import Optional
|
4
4
|
|
5
|
+
from pydantic import ConfigDict
|
5
6
|
from sqlalchemy import Column
|
6
7
|
from sqlalchemy.types import DateTime
|
7
8
|
from sqlalchemy.types import JSON
|
@@ -14,8 +15,7 @@ from fractal_server.images.models import AttributeFiltersType
|
|
14
15
|
|
15
16
|
|
16
17
|
class DatasetV2(SQLModel, table=True):
|
17
|
-
|
18
|
-
arbitrary_types_allowed = True
|
18
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
19
19
|
|
20
20
|
id: Optional[int] = Field(default=None, primary_key=True)
|
21
21
|
name: str
|
@@ -2,6 +2,7 @@ from datetime import datetime
|
|
2
2
|
from typing import Any
|
3
3
|
from typing import Optional
|
4
4
|
|
5
|
+
from pydantic import ConfigDict
|
5
6
|
from sqlalchemy import Column
|
6
7
|
from sqlalchemy.types import DateTime
|
7
8
|
from sqlalchemy.types import JSON
|
@@ -14,16 +15,17 @@ from fractal_server.images.models import AttributeFiltersType
|
|
14
15
|
|
15
16
|
|
16
17
|
class JobV2(SQLModel, table=True):
|
17
|
-
|
18
|
-
arbitrary_types_allowed = True
|
18
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
19
19
|
|
20
20
|
id: Optional[int] = Field(default=None, primary_key=True)
|
21
|
-
project_id: Optional[int] = Field(foreign_key="projectv2.id")
|
22
|
-
workflow_id: Optional[int] = Field(
|
23
|
-
|
21
|
+
project_id: Optional[int] = Field(foreign_key="projectv2.id", default=None)
|
22
|
+
workflow_id: Optional[int] = Field(
|
23
|
+
foreign_key="workflowv2.id", default=None
|
24
|
+
)
|
25
|
+
dataset_id: Optional[int] = Field(foreign_key="datasetv2.id", default=None)
|
24
26
|
|
25
27
|
user_email: str = Field(nullable=False)
|
26
|
-
slurm_account: Optional[str]
|
28
|
+
slurm_account: Optional[str] = None
|
27
29
|
|
28
30
|
dataset_dump: dict[str, Any] = Field(
|
29
31
|
sa_column=Column(JSON, nullable=False)
|
@@ -35,9 +37,9 @@ class JobV2(SQLModel, table=True):
|
|
35
37
|
sa_column=Column(JSON, nullable=False)
|
36
38
|
)
|
37
39
|
|
38
|
-
worker_init: Optional[str]
|
39
|
-
working_dir: Optional[str]
|
40
|
-
working_dir_user: Optional[str]
|
40
|
+
worker_init: Optional[str] = None
|
41
|
+
working_dir: Optional[str] = None
|
42
|
+
working_dir_user: Optional[str] = None
|
41
43
|
first_task_index: int
|
42
44
|
last_task_index: int
|
43
45
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
from typing import Any
|
2
2
|
from typing import Optional
|
3
3
|
|
4
|
-
from pydantic import HttpUrl
|
5
4
|
from sqlalchemy import Column
|
6
5
|
from sqlalchemy.types import JSON
|
7
6
|
from sqlmodel import Field
|
@@ -31,9 +30,9 @@ class TaskV2(SQLModel, table=True):
|
|
31
30
|
args_schema_parallel: Optional[dict[str, Any]] = Field(
|
32
31
|
sa_column=Column(JSON), default=None
|
33
32
|
)
|
34
|
-
args_schema_version: Optional[str]
|
33
|
+
args_schema_version: Optional[str] = None
|
35
34
|
docs_info: Optional[str] = None
|
36
|
-
docs_link: Optional[
|
35
|
+
docs_link: Optional[str] = None
|
37
36
|
|
38
37
|
input_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
|
39
38
|
output_types: dict[str, bool] = Field(sa_column=Column(JSON), default={})
|
@@ -22,7 +22,9 @@ class TaskGroupV2(SQLModel, table=True):
|
|
22
22
|
)
|
23
23
|
|
24
24
|
user_id: int = Field(foreign_key="user_oauth.id")
|
25
|
-
user_group_id: Optional[int] = Field(
|
25
|
+
user_group_id: Optional[int] = Field(
|
26
|
+
foreign_key="usergroup.id", default=None
|
27
|
+
)
|
26
28
|
|
27
29
|
origin: str
|
28
30
|
pkg_name: str
|
@@ -97,7 +99,9 @@ class TaskGroupActivityV2(SQLModel, table=True):
|
|
97
99
|
|
98
100
|
id: Optional[int] = Field(default=None, primary_key=True)
|
99
101
|
user_id: int = Field(foreign_key="user_oauth.id")
|
100
|
-
taskgroupv2_id: Optional[int] = Field(
|
102
|
+
taskgroupv2_id: Optional[int] = Field(
|
103
|
+
default=None, foreign_key="taskgroupv2.id"
|
104
|
+
)
|
101
105
|
timestamp_started: datetime = Field(
|
102
106
|
default_factory=get_timestamp,
|
103
107
|
sa_column=Column(DateTime(timezone=True), nullable=False),
|
{fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/models/v2/workflowtask.py
RENAMED
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Any
|
2
2
|
from typing import Optional
|
3
3
|
|
4
|
+
from pydantic import ConfigDict
|
4
5
|
from sqlalchemy import Column
|
5
6
|
from sqlalchemy.types import JSON
|
6
7
|
from sqlmodel import Field
|
@@ -11,18 +12,24 @@ from .task import TaskV2
|
|
11
12
|
|
12
13
|
|
13
14
|
class WorkflowTaskV2(SQLModel, table=True):
|
14
|
-
|
15
|
-
arbitrary_types_allowed = True
|
16
|
-
fields = {"parent": {"exclude": True}}
|
15
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
17
16
|
|
18
17
|
id: Optional[int] = Field(default=None, primary_key=True)
|
19
18
|
|
20
19
|
workflow_id: int = Field(foreign_key="workflowv2.id")
|
21
|
-
order: Optional[int]
|
22
|
-
meta_parallel: Optional[dict[str, Any]] = Field(
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
order: Optional[int] = None
|
21
|
+
meta_parallel: Optional[dict[str, Any]] = Field(
|
22
|
+
sa_column=Column(JSON), default=None
|
23
|
+
)
|
24
|
+
meta_non_parallel: Optional[dict[str, Any]] = Field(
|
25
|
+
sa_column=Column(JSON), default=None
|
26
|
+
)
|
27
|
+
args_parallel: Optional[dict[str, Any]] = Field(
|
28
|
+
sa_column=Column(JSON), default=None
|
29
|
+
)
|
30
|
+
args_non_parallel: Optional[dict[str, Any]] = Field(
|
31
|
+
sa_column=Column(JSON), default=None
|
32
|
+
)
|
26
33
|
|
27
34
|
type_filters: dict[str, bool] = Field(
|
28
35
|
sa_column=Column(JSON, nullable=False, server_default="{}")
|
{fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/__init__.py
RENAMED
@@ -3,6 +3,8 @@
|
|
3
3
|
"""
|
4
4
|
from fastapi import APIRouter
|
5
5
|
|
6
|
+
from .accounting import router as accounting_router
|
7
|
+
from .impersonate import router as impersonate_router
|
6
8
|
from .job import router as job_router
|
7
9
|
from .project import router as project_router
|
8
10
|
from .task import router as task_router
|
@@ -11,6 +13,7 @@ from .task_group_lifecycle import router as task_group_lifecycle_router
|
|
11
13
|
|
12
14
|
router_admin_v2 = APIRouter()
|
13
15
|
|
16
|
+
router_admin_v2.include_router(accounting_router, prefix="/accounting")
|
14
17
|
router_admin_v2.include_router(job_router, prefix="/job")
|
15
18
|
router_admin_v2.include_router(project_router, prefix="/project")
|
16
19
|
router_admin_v2.include_router(task_router, prefix="/task")
|
@@ -18,3 +21,4 @@ router_admin_v2.include_router(task_group_router, prefix="/task-group")
|
|
18
21
|
router_admin_v2.include_router(
|
19
22
|
task_group_lifecycle_router, prefix="/task-group"
|
20
23
|
)
|
24
|
+
router_admin_v2.include_router(impersonate_router, prefix="/impersonate")
|
@@ -0,0 +1,108 @@
|
|
1
|
+
from itertools import chain
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
from fastapi import APIRouter
|
5
|
+
from fastapi import Depends
|
6
|
+
from fastapi import HTTPException
|
7
|
+
from fastapi import Query
|
8
|
+
from fastapi import status
|
9
|
+
from fastapi.responses import JSONResponse
|
10
|
+
from pydantic import BaseModel
|
11
|
+
from pydantic.types import AwareDatetime
|
12
|
+
from sqlmodel import func
|
13
|
+
from sqlmodel import select
|
14
|
+
|
15
|
+
from fractal_server.app.db import AsyncSession
|
16
|
+
from fractal_server.app.db import get_async_db
|
17
|
+
from fractal_server.app.models import UserOAuth
|
18
|
+
from fractal_server.app.models.v2 import AccountingRecord
|
19
|
+
from fractal_server.app.models.v2 import AccountingRecordSlurm
|
20
|
+
from fractal_server.app.routes.auth import current_active_superuser
|
21
|
+
from fractal_server.app.schemas.v2 import AccountingRecordRead
|
22
|
+
|
23
|
+
|
24
|
+
class AccountingQuery(BaseModel):
|
25
|
+
user_id: Optional[int] = None
|
26
|
+
timestamp_min: Optional[AwareDatetime] = None
|
27
|
+
timestamp_max: Optional[AwareDatetime] = None
|
28
|
+
|
29
|
+
|
30
|
+
class AccountingPage(BaseModel):
|
31
|
+
total_count: int
|
32
|
+
page_size: int
|
33
|
+
current_page: int
|
34
|
+
records: list[AccountingRecordRead]
|
35
|
+
|
36
|
+
|
37
|
+
router = APIRouter()
|
38
|
+
|
39
|
+
|
40
|
+
@router.post("/", response_model=AccountingPage)
|
41
|
+
async def query_accounting(
|
42
|
+
query: AccountingQuery,
|
43
|
+
# pagination
|
44
|
+
page: int = Query(default=1, ge=1),
|
45
|
+
page_size: Optional[int] = Query(default=None, ge=1),
|
46
|
+
# dependencies
|
47
|
+
superuser: UserOAuth = Depends(current_active_superuser),
|
48
|
+
db: AsyncSession = Depends(get_async_db),
|
49
|
+
) -> AccountingPage:
|
50
|
+
|
51
|
+
if page_size is None and page > 1:
|
52
|
+
raise HTTPException(
|
53
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
54
|
+
detail=(f"Invalid pagination parameters: {page=}, {page_size=}."),
|
55
|
+
)
|
56
|
+
|
57
|
+
stm = select(AccountingRecord).order_by(AccountingRecord.id)
|
58
|
+
stm_count = select(func.count(AccountingRecord.id))
|
59
|
+
if query.user_id is not None:
|
60
|
+
stm = stm.where(AccountingRecord.user_id == query.user_id)
|
61
|
+
stm_count = stm_count.where(AccountingRecord.user_id == query.user_id)
|
62
|
+
if query.timestamp_min is not None:
|
63
|
+
stm = stm.where(AccountingRecord.timestamp >= query.timestamp_min)
|
64
|
+
stm_count = stm_count.where(
|
65
|
+
AccountingRecord.timestamp >= query.timestamp_min
|
66
|
+
)
|
67
|
+
if query.timestamp_max is not None:
|
68
|
+
stm = stm.where(AccountingRecord.timestamp <= query.timestamp_max)
|
69
|
+
stm_count = stm_count.where(
|
70
|
+
AccountingRecord.timestamp <= query.timestamp_max
|
71
|
+
)
|
72
|
+
if page_size is not None:
|
73
|
+
stm = stm.offset((page - 1) * page_size).limit(page_size)
|
74
|
+
|
75
|
+
res = await db.execute(stm)
|
76
|
+
records = res.scalars().all()
|
77
|
+
res_total_count = await db.execute(stm_count)
|
78
|
+
total_count = res_total_count.scalar()
|
79
|
+
|
80
|
+
actual_page_size = page_size or len(records)
|
81
|
+
return AccountingPage(
|
82
|
+
total_count=total_count,
|
83
|
+
page_size=actual_page_size,
|
84
|
+
current_page=page,
|
85
|
+
records=[record.model_dump() for record in records],
|
86
|
+
)
|
87
|
+
|
88
|
+
|
89
|
+
@router.post("/slurm/")
|
90
|
+
async def query_accounting_slurm(
|
91
|
+
query: AccountingQuery,
|
92
|
+
# dependencies
|
93
|
+
superuser: UserOAuth = Depends(current_active_superuser),
|
94
|
+
db: AsyncSession = Depends(get_async_db),
|
95
|
+
) -> JSONResponse:
|
96
|
+
|
97
|
+
stm = select(AccountingRecordSlurm.slurm_job_ids)
|
98
|
+
if query.user_id is not None:
|
99
|
+
stm = stm.where(AccountingRecordSlurm.user_id == query.user_id)
|
100
|
+
if query.timestamp_min is not None:
|
101
|
+
stm = stm.where(AccountingRecordSlurm.timestamp >= query.timestamp_min)
|
102
|
+
if query.timestamp_max is not None:
|
103
|
+
stm = stm.where(AccountingRecordSlurm.timestamp <= query.timestamp_max)
|
104
|
+
|
105
|
+
res = await db.execute(stm)
|
106
|
+
nested_slurm_job_ids = res.scalars().all()
|
107
|
+
aggregated_slurm_job_ids = list(chain(*nested_slurm_job_ids))
|
108
|
+
return JSONResponse(content=aggregated_slurm_job_ids, status_code=200)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
from fastapi import APIRouter
|
2
|
+
from fastapi import Depends
|
3
|
+
from fastapi.responses import JSONResponse
|
4
|
+
from fastapi_users.authentication import JWTStrategy
|
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 UserOAuth
|
9
|
+
from fractal_server.app.routes.auth import current_active_superuser
|
10
|
+
from fractal_server.app.routes.auth._aux_auth import _user_or_404
|
11
|
+
from fractal_server.config import get_settings
|
12
|
+
from fractal_server.syringe import Inject
|
13
|
+
|
14
|
+
router = APIRouter()
|
15
|
+
|
16
|
+
|
17
|
+
@router.get("/{user_id}/")
|
18
|
+
async def impersonate_user(
|
19
|
+
user_id: int,
|
20
|
+
superuser: UserOAuth = Depends(current_active_superuser),
|
21
|
+
db: AsyncSession = Depends(get_async_db),
|
22
|
+
) -> JSONResponse:
|
23
|
+
user = await _user_or_404(user_id, db)
|
24
|
+
|
25
|
+
settings = Inject(get_settings)
|
26
|
+
jwt_strategy = JWTStrategy(
|
27
|
+
secret=settings.JWT_SECRET_KEY, # type: ignore
|
28
|
+
lifetime_seconds=7200, # 2 hours
|
29
|
+
)
|
30
|
+
token = await jwt_strategy.write_token(user)
|
31
|
+
|
32
|
+
return JSONResponse(
|
33
|
+
content={"access_token": token, "token_type": "bearer"},
|
34
|
+
status_code=200,
|
35
|
+
)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
from datetime import datetime
|
2
1
|
from pathlib import Path
|
3
2
|
from typing import Optional
|
4
3
|
|
@@ -8,6 +7,7 @@ from fastapi import HTTPException
|
|
8
7
|
from fastapi import Response
|
9
8
|
from fastapi import status
|
10
9
|
from fastapi.responses import StreamingResponse
|
10
|
+
from pydantic.types import AwareDatetime
|
11
11
|
from sqlmodel import select
|
12
12
|
|
13
13
|
from fractal_server.app.db import AsyncSession
|
@@ -16,7 +16,6 @@ from fractal_server.app.models import UserOAuth
|
|
16
16
|
from fractal_server.app.models.v2 import JobV2
|
17
17
|
from fractal_server.app.models.v2 import ProjectV2
|
18
18
|
from fractal_server.app.routes.auth import current_active_superuser
|
19
|
-
from fractal_server.app.routes.aux import _raise_if_naive_datetime
|
20
19
|
from fractal_server.app.routes.aux._job import _write_shutdown_file
|
21
20
|
from fractal_server.app.routes.aux._runner import _check_shutdown_is_supported
|
22
21
|
from fractal_server.app.runner.filenames import WORKFLOW_LOG_FILENAME
|
@@ -37,10 +36,10 @@ async def view_job(
|
|
37
36
|
dataset_id: Optional[int] = None,
|
38
37
|
workflow_id: Optional[int] = None,
|
39
38
|
status: Optional[JobStatusTypeV2] = None,
|
40
|
-
start_timestamp_min: Optional[
|
41
|
-
start_timestamp_max: Optional[
|
42
|
-
end_timestamp_min: Optional[
|
43
|
-
end_timestamp_max: Optional[
|
39
|
+
start_timestamp_min: Optional[AwareDatetime] = None,
|
40
|
+
start_timestamp_max: Optional[AwareDatetime] = None,
|
41
|
+
end_timestamp_min: Optional[AwareDatetime] = None,
|
42
|
+
end_timestamp_max: Optional[AwareDatetime] = None,
|
44
43
|
log: bool = True,
|
45
44
|
user: UserOAuth = Depends(current_active_superuser),
|
46
45
|
db: AsyncSession = Depends(get_async_db),
|
@@ -67,13 +66,6 @@ async def view_job(
|
|
67
66
|
`job.log` is set to `None`.
|
68
67
|
"""
|
69
68
|
|
70
|
-
_raise_if_naive_datetime(
|
71
|
-
start_timestamp_min,
|
72
|
-
start_timestamp_max,
|
73
|
-
end_timestamp_min,
|
74
|
-
end_timestamp_max,
|
75
|
-
)
|
76
|
-
|
77
69
|
stm = select(JobV2)
|
78
70
|
|
79
71
|
if id is not None:
|
{fractal_server-2.12.1 → fractal_server-2.13.1}/fractal_server/app/routes/admin/v2/task_group.py
RENAMED
@@ -1,4 +1,3 @@
|
|
1
|
-
from datetime import datetime
|
2
1
|
from typing import Optional
|
3
2
|
|
4
3
|
from fastapi import APIRouter
|
@@ -6,6 +5,7 @@ from fastapi import Depends
|
|
6
5
|
from fastapi import HTTPException
|
7
6
|
from fastapi import Response
|
8
7
|
from fastapi import status
|
8
|
+
from pydantic.types import AwareDatetime
|
9
9
|
from sqlalchemy.sql.operators import is_
|
10
10
|
from sqlalchemy.sql.operators import is_not
|
11
11
|
from sqlmodel import select
|
@@ -20,7 +20,6 @@ from fractal_server.app.routes.auth import current_active_superuser
|
|
20
20
|
from fractal_server.app.routes.auth._aux_auth import (
|
21
21
|
_verify_user_belongs_to_group,
|
22
22
|
)
|
23
|
-
from fractal_server.app.routes.aux import _raise_if_naive_datetime
|
24
23
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
25
24
|
from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
|
26
25
|
from fractal_server.app.schemas.v2 import TaskGroupActivityV2Read
|
@@ -42,13 +41,11 @@ async def get_task_group_activity_list(
|
|
42
41
|
pkg_name: Optional[str] = None,
|
43
42
|
status: Optional[TaskGroupActivityStatusV2] = None,
|
44
43
|
action: Optional[TaskGroupActivityActionV2] = None,
|
45
|
-
timestamp_started_min: Optional[
|
44
|
+
timestamp_started_min: Optional[AwareDatetime] = None,
|
46
45
|
superuser: UserOAuth = Depends(current_active_superuser),
|
47
46
|
db: AsyncSession = Depends(get_async_db),
|
48
47
|
) -> list[TaskGroupActivityV2Read]:
|
49
48
|
|
50
|
-
_raise_if_naive_datetime(timestamp_started_min)
|
51
|
-
|
52
49
|
stm = select(TaskGroupActivityV2)
|
53
50
|
if task_group_activity_id is not None:
|
54
51
|
stm = stm.where(TaskGroupActivityV2.id == task_group_activity_id)
|
@@ -96,19 +93,14 @@ async def query_task_group_list(
|
|
96
93
|
active: Optional[bool] = None,
|
97
94
|
pkg_name: Optional[str] = None,
|
98
95
|
origin: Optional[TaskGroupV2OriginEnum] = None,
|
99
|
-
timestamp_last_used_min: Optional[
|
100
|
-
timestamp_last_used_max: Optional[
|
96
|
+
timestamp_last_used_min: Optional[AwareDatetime] = None,
|
97
|
+
timestamp_last_used_max: Optional[AwareDatetime] = None,
|
101
98
|
user: UserOAuth = Depends(current_active_superuser),
|
102
99
|
db: AsyncSession = Depends(get_async_db),
|
103
100
|
) -> list[TaskGroupReadV2]:
|
104
101
|
|
105
102
|
stm = select(TaskGroupV2)
|
106
103
|
|
107
|
-
_raise_if_naive_datetime(
|
108
|
-
timestamp_last_used_max,
|
109
|
-
timestamp_last_used_min,
|
110
|
-
)
|
111
|
-
|
112
104
|
if user_group_id is not None and private is True:
|
113
105
|
raise HTTPException(
|
114
106
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
@@ -163,7 +155,7 @@ async def patch_task_group(
|
|
163
155
|
detail=f"TaskGroupV2 {task_group_id} not found",
|
164
156
|
)
|
165
157
|
|
166
|
-
for key, value in task_group_update.
|
158
|
+
for key, value in task_group_update.model_dump(exclude_unset=True).items():
|
167
159
|
if (key == "user_group_id") and (value is not None):
|
168
160
|
await _verify_user_belongs_to_group(
|
169
161
|
user_id=user.id, user_group_id=value, db=db
|
@@ -55,7 +55,7 @@ async def get_package_version_from_pypi(
|
|
55
55
|
f"A TimeoutException occurred while getting {url}.\n"
|
56
56
|
f"Original error: {str(e)}."
|
57
57
|
)
|
58
|
-
logger.
|
58
|
+
logger.warning(error_msg)
|
59
59
|
raise HTTPException(
|
60
60
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
61
61
|
detail=error_msg,
|
@@ -65,7 +65,7 @@ async def get_package_version_from_pypi(
|
|
65
65
|
f"An unknown error occurred while getting {url}. "
|
66
66
|
f"Original error: {str(e)}."
|
67
67
|
)
|
68
|
-
logger.
|
68
|
+
logger.warning(error_msg)
|
69
69
|
raise HTTPException(
|
70
70
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
71
71
|
detail=error_msg,
|
@@ -85,7 +85,7 @@ async def get_package_version_from_pypi(
|
|
85
85
|
latest_version = response_data["info"]["version"]
|
86
86
|
available_releases = response_data["releases"].keys()
|
87
87
|
except KeyError as e:
|
88
|
-
logger.
|
88
|
+
logger.warning(
|
89
89
|
f"A KeyError occurred while getting {url}. "
|
90
90
|
f"Original error: {str(e)}."
|
91
91
|
)
|
@@ -60,7 +60,7 @@ async def create_dataset(
|
|
60
60
|
db_dataset = DatasetV2(
|
61
61
|
project_id=project_id,
|
62
62
|
zarr_dir="__PLACEHOLDER__",
|
63
|
-
**dataset.
|
63
|
+
**dataset.model_dump(exclude={"zarr_dir"}),
|
64
64
|
)
|
65
65
|
db.add(db_dataset)
|
66
66
|
await db.commit()
|
@@ -77,7 +77,7 @@ async def create_dataset(
|
|
77
77
|
await db.commit()
|
78
78
|
await db.refresh(db_dataset)
|
79
79
|
else:
|
80
|
-
db_dataset = DatasetV2(project_id=project_id, **dataset.
|
80
|
+
db_dataset = DatasetV2(project_id=project_id, **dataset.model_dump())
|
81
81
|
db.add(db_dataset)
|
82
82
|
await db.commit()
|
83
83
|
await db.refresh(db_dataset)
|
@@ -172,7 +172,7 @@ async def update_dataset(
|
|
172
172
|
),
|
173
173
|
)
|
174
174
|
|
175
|
-
for key, value in dataset_update.
|
175
|
+
for key, value in dataset_update.model_dump(exclude_unset=True).items():
|
176
176
|
setattr(db_dataset, key, value)
|
177
177
|
|
178
178
|
await db.commit()
|
@@ -316,7 +316,7 @@ async def import_dataset(
|
|
316
316
|
# Create new Dataset
|
317
317
|
db_dataset = DatasetV2(
|
318
318
|
project_id=project_id,
|
319
|
-
**dataset.
|
319
|
+
**dataset.model_dump(exclude_none=True),
|
320
320
|
)
|
321
321
|
db.add(db_dataset)
|
322
322
|
await db.commit()
|