fractal-server 2.12.0a1__tar.gz → 2.12.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.0a1 → fractal_server-2.12.1}/PKG-INFO +2 -2
- fractal_server-2.12.1/fractal_server/__init__.py +1 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/__main__.py +17 -63
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/images.py +0 -12
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -1
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/ssh/executor.py +14 -23
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/sudo/executor.py +52 -17
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/security/__init__.py +6 -3
- fractal_server-2.12.1/fractal_server/app/security/signup_email.py +48 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/config.py +92 -51
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/main.py +12 -9
- fractal_server-2.12.1/fractal_server/migrations/env.py +49 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/local/collect.py +9 -8
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/local/deactivate.py +3 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/local/reactivate.py +3 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/ssh/collect.py +8 -8
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/ssh/deactivate.py +3 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/ssh/reactivate.py +9 -6
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/pyproject.toml +4 -3
- fractal_server-2.12.0a1/fractal_server/__init__.py +0 -1
- fractal_server-2.12.0a1/fractal_server/app/security/signup_email.py +0 -39
- fractal_server-2.12.0a1/fractal_server/migrations/env.py +0 -96
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/LICENSE +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/README.md +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/linkusergroup.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/security.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/user_settings.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/dataset.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/job.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/project.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/task.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/task_group.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/models/v2/workflowtask.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/admin/v2/job.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/admin/v2/project.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/admin/v2/task.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/dataset.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/job.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/project.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/status.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/submit.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/task.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/task_group.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/workflow.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/current_user.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/group.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/login.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/oauth.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/register.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/router.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/auth/users.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/aux/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/aux/_job.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/aux/_runner.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/components.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/compress_folder.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/exceptions.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/executors/slurm/utils_executors.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/extract_archive.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/filenames.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/run_subprocess.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/shutdown.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/task_files.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local/executor.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/runner.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/runner_functions.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/v2/task_interface.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/runner/versions.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/_filter_validators.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/_validators.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/user.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/user_group.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/user_settings.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/dataset.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/dumps.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/job.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/manifest.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/project.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/status.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/task.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/task_collection.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/task_group.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/workflow.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/user_settings.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/data_migrations/tools.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/gunicorn_fractal.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/images/models.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/logger.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/naming_convention.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/py.typed +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/ssh/_fabric.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/syringe.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/utils.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/local/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/local/_utils.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/utils_background.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/utils_database.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/utils_package_names.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/tasks/v2/utils_templates.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/urls.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/utils.py +0 -0
- {fractal_server-2.12.0a1 → fractal_server-2.12.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.12.
|
3
|
+
Version: 2.12.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
|
@@ -27,7 +27,7 @@ Requires-Dist: pydantic (>=1.10.8,<2)
|
|
27
27
|
Requires-Dist: python-dotenv (>=1.0.0,<1.1.0)
|
28
28
|
Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
|
29
29
|
Requires-Dist: sqlmodel (==0.0.21)
|
30
|
-
Requires-Dist: uvicorn (
|
30
|
+
Requires-Dist: uvicorn (>=0.29.0,<0.35.0)
|
31
31
|
Requires-Dist: uvicorn-worker (==0.2.0)
|
32
32
|
Project-URL: Documentation, https://fractal-analytics-platform.github.io/fractal-server
|
33
33
|
Project-URL: Repository, https://github.com/fractal-analytics-platform/fractal-server
|
@@ -0,0 +1 @@
|
|
1
|
+
__VERSION__ = "2.12.1"
|
@@ -63,45 +63,18 @@ update_db_data_parser = subparsers.add_parser(
|
|
63
63
|
description="Apply data-migration script to an existing database.",
|
64
64
|
)
|
65
65
|
|
66
|
-
# fractalctl email-
|
67
|
-
|
68
|
-
"email-
|
66
|
+
# fractalctl encrypt-email-password
|
67
|
+
encrypt_email_password_parser = subparsers.add_parser(
|
68
|
+
"encrypt-email-password",
|
69
69
|
description=(
|
70
70
|
"Generate valid values for environment variables "
|
71
|
-
"
|
71
|
+
"FRACTAL_EMAIL_PASSWORD and FRACTAL_EMAIL_PASSWORD_KEY."
|
72
72
|
),
|
73
73
|
)
|
74
|
-
email_settings_parser.add_argument(
|
75
|
-
"sender",
|
76
|
-
type=str,
|
77
|
-
help="Email of the sender",
|
78
|
-
)
|
79
|
-
email_settings_parser.add_argument(
|
80
|
-
"server",
|
81
|
-
type=str,
|
82
|
-
help="SMPT server used to send emails",
|
83
|
-
)
|
84
|
-
email_settings_parser.add_argument(
|
85
|
-
"port",
|
86
|
-
type=int,
|
87
|
-
help="Port of the SMPT server",
|
88
|
-
)
|
89
|
-
email_settings_parser.add_argument(
|
90
|
-
"instance",
|
91
|
-
type=str,
|
92
|
-
help="Name of the Fractal instance sending emails",
|
93
|
-
)
|
94
|
-
email_settings_parser.add_argument(
|
95
|
-
"--skip-starttls",
|
96
|
-
action="store_true",
|
97
|
-
default=False,
|
98
|
-
help="If set, skip the execution of `starttls` when sending emails",
|
99
|
-
)
|
100
74
|
|
101
75
|
|
102
76
|
def save_openapi(dest="openapi.json"):
|
103
77
|
from fractal_server.main import start_application
|
104
|
-
import json
|
105
78
|
|
106
79
|
app = start_application()
|
107
80
|
openapi_schema = app.openapi()
|
@@ -129,6 +102,11 @@ def set_db(skip_init_data: bool = False):
|
|
129
102
|
from pathlib import Path
|
130
103
|
import fractal_server
|
131
104
|
|
105
|
+
# Check settings
|
106
|
+
settings = Inject(get_settings)
|
107
|
+
settings.check_db()
|
108
|
+
|
109
|
+
# Perform migrations
|
132
110
|
alembic_ini = Path(fractal_server.__file__).parent / "alembic.ini"
|
133
111
|
alembic_args = ["-c", alembic_ini.as_posix(), "upgrade", "head"]
|
134
112
|
print(f"START: Run alembic.config, with argv={alembic_args}")
|
@@ -138,12 +116,10 @@ def set_db(skip_init_data: bool = False):
|
|
138
116
|
if skip_init_data:
|
139
117
|
return
|
140
118
|
|
141
|
-
#
|
119
|
+
# Create default group and user
|
142
120
|
print()
|
143
121
|
_create_first_group()
|
144
122
|
print()
|
145
|
-
# NOTE: It will be fixed with #1739
|
146
|
-
settings = Inject(get_settings)
|
147
123
|
asyncio.run(
|
148
124
|
_create_first_user(
|
149
125
|
email=settings.FRACTAL_DEFAULT_ADMIN_EMAIL,
|
@@ -224,31 +200,15 @@ def update_db_data():
|
|
224
200
|
current_update_db_data_module.fix_db()
|
225
201
|
|
226
202
|
|
227
|
-
def
|
228
|
-
sender: str,
|
229
|
-
server: str,
|
230
|
-
port: int,
|
231
|
-
instance: str,
|
232
|
-
skip_starttls: bool,
|
233
|
-
):
|
203
|
+
def print_encrypted_password():
|
234
204
|
from cryptography.fernet import Fernet
|
235
205
|
|
236
|
-
password = input(
|
206
|
+
password = input("Insert email password: ").encode("utf-8")
|
237
207
|
key = Fernet.generate_key().decode("utf-8")
|
238
|
-
|
239
|
-
dict(
|
240
|
-
sender=sender,
|
241
|
-
password=password,
|
242
|
-
smtp_server=server,
|
243
|
-
port=port,
|
244
|
-
instance_name=instance,
|
245
|
-
use_starttls=(not skip_starttls),
|
246
|
-
)
|
247
|
-
).encode("utf-8")
|
248
|
-
email_settings = Fernet(key).encrypt(fractal_mail_settings).decode("utf-8")
|
208
|
+
encrypted_password = Fernet(key).encrypt(password).decode("utf-8")
|
249
209
|
|
250
|
-
print(f"\
|
251
|
-
print(f"
|
210
|
+
print(f"\nFRACTAL_EMAIL_PASSWORD={encrypted_password}")
|
211
|
+
print(f"FRACTAL_EMAIL_PASSWORD_KEY={key}")
|
252
212
|
|
253
213
|
|
254
214
|
def run():
|
@@ -267,14 +227,8 @@ def run():
|
|
267
227
|
port=args.port,
|
268
228
|
reload=args.reload,
|
269
229
|
)
|
270
|
-
elif args.cmd == "email-
|
271
|
-
|
272
|
-
sender=args.sender,
|
273
|
-
server=args.server,
|
274
|
-
port=args.port,
|
275
|
-
instance=args.instance,
|
276
|
-
skip_starttls=args.skip_starttls,
|
277
|
-
)
|
230
|
+
elif args.cmd == "encrypt-email-password":
|
231
|
+
print_encrypted_password()
|
278
232
|
else:
|
279
233
|
sys.exit(f"Error: invalid command '{args.cmd}'.")
|
280
234
|
|
{fractal_server-2.12.0a1 → fractal_server-2.12.1}/fractal_server/app/routes/api/v2/images.py
RENAMED
@@ -118,7 +118,6 @@ async def post_new_image(
|
|
118
118
|
async def query_dataset_images(
|
119
119
|
project_id: int,
|
120
120
|
dataset_id: int,
|
121
|
-
use_dataset_filters: bool = False, # query param
|
122
121
|
page: int = 1, # query param
|
123
122
|
page_size: Optional[int] = None, # query param
|
124
123
|
query: Optional[ImageQuery] = None, # body
|
@@ -138,17 +137,6 @@ async def query_dataset_images(
|
|
138
137
|
dataset = output["dataset"]
|
139
138
|
images = dataset.images
|
140
139
|
|
141
|
-
if use_dataset_filters is True:
|
142
|
-
images = [
|
143
|
-
image
|
144
|
-
for image in images
|
145
|
-
if match_filter(
|
146
|
-
image=image,
|
147
|
-
type_filters=dataset.type_filters,
|
148
|
-
attribute_filters=dataset.attribute_filters,
|
149
|
-
)
|
150
|
-
]
|
151
|
-
|
152
140
|
attributes = {}
|
153
141
|
for image in images:
|
154
142
|
for k, v in image["attributes"].items():
|
@@ -88,7 +88,6 @@ class SlurmJob:
|
|
88
88
|
self,
|
89
89
|
num_tasks_tot: int,
|
90
90
|
slurm_config: SlurmConfig,
|
91
|
-
workflow_task_file_prefix: Optional[str] = None,
|
92
91
|
slurm_file_prefix: Optional[str] = None,
|
93
92
|
wftask_file_prefixes: Optional[tuple[str, ...]] = None,
|
94
93
|
single_task_submission: bool = False,
|
@@ -62,7 +62,6 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
62
62
|
shutdown_file:
|
63
63
|
python_remote: Equal to `settings.FRACTAL_SLURM_WORKER_PYTHON`
|
64
64
|
wait_thread_cls: Class for waiting thread
|
65
|
-
keep_pickle_files:
|
66
65
|
workflow_dir_local:
|
67
66
|
Directory for both the cfut/SLURM and fractal-server files and logs
|
68
67
|
workflow_dir_remote:
|
@@ -84,7 +83,6 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
84
83
|
python_remote: str
|
85
84
|
|
86
85
|
wait_thread_cls = FractalSlurmWaitThread
|
87
|
-
keep_pickle_files: bool
|
88
86
|
|
89
87
|
common_script_lines: list[str]
|
90
88
|
slurm_account: Optional[str]
|
@@ -100,8 +98,6 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
100
98
|
# Folders and files
|
101
99
|
workflow_dir_local: Path,
|
102
100
|
workflow_dir_remote: Path,
|
103
|
-
# Runner options
|
104
|
-
keep_pickle_files: bool = False,
|
105
101
|
# Monitoring options
|
106
102
|
slurm_poll_interval: Optional[int] = None,
|
107
103
|
# SLURM submission script options
|
@@ -120,7 +116,6 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
120
116
|
fractal_ssh:
|
121
117
|
workflow_dir_local:
|
122
118
|
workflow_dir_remote:
|
123
|
-
keep_pickle_files:
|
124
119
|
slurm_poll_interval:
|
125
120
|
common_script_lines:
|
126
121
|
slurm_account:
|
@@ -194,7 +189,6 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
194
189
|
raise e
|
195
190
|
|
196
191
|
# Set/initialize some more options
|
197
|
-
self.keep_pickle_files = keep_pickle_files
|
198
192
|
self.map_jobid_to_slurm_files_local = {}
|
199
193
|
|
200
194
|
def _validate_common_script_lines(self):
|
@@ -901,12 +895,11 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
901
895
|
pass
|
902
896
|
for job_id in remaining_job_ids:
|
903
897
|
self._cleanup(job_id)
|
904
|
-
|
905
|
-
for
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
path.unlink()
|
898
|
+
for job in remaining_jobs:
|
899
|
+
for path in job.output_pickle_files_local:
|
900
|
+
path.unlink()
|
901
|
+
for path in job.input_pickle_files_local:
|
902
|
+
path.unlink()
|
910
903
|
|
911
904
|
def _completion(self, job_ids: list[str]) -> None:
|
912
905
|
"""
|
@@ -1001,8 +994,7 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
1001
994
|
f"Future {future} (SLURM job ID: {job_id}) "
|
1002
995
|
"was already cancelled."
|
1003
996
|
)
|
1004
|
-
|
1005
|
-
in_path.unlink()
|
997
|
+
in_path.unlink()
|
1006
998
|
self._cleanup(job_id)
|
1007
999
|
self._handle_remaining_jobs(
|
1008
1000
|
remaining_futures=remaining_futures,
|
@@ -1062,17 +1054,15 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
1062
1054
|
remaining_job_ids=remaining_job_ids,
|
1063
1055
|
)
|
1064
1056
|
return
|
1065
|
-
|
1066
|
-
out_path.unlink()
|
1057
|
+
out_path.unlink()
|
1067
1058
|
except InvalidStateError:
|
1068
1059
|
logger.warning(
|
1069
1060
|
f"Future {future} (SLURM job ID: {job_id}) was "
|
1070
1061
|
"already cancelled, exit from "
|
1071
1062
|
"FractalSlurmSSHExecutor._completion."
|
1072
1063
|
)
|
1073
|
-
|
1074
|
-
|
1075
|
-
in_path.unlink()
|
1064
|
+
out_path.unlink()
|
1065
|
+
in_path.unlink()
|
1076
1066
|
|
1077
1067
|
self._cleanup(job_id)
|
1078
1068
|
self._handle_remaining_jobs(
|
@@ -1082,8 +1072,7 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
1082
1072
|
return
|
1083
1073
|
|
1084
1074
|
# Clean up input pickle file
|
1085
|
-
|
1086
|
-
in_path.unlink()
|
1075
|
+
in_path.unlink()
|
1087
1076
|
self._cleanup(job_id)
|
1088
1077
|
if job.single_task_submission:
|
1089
1078
|
future.set_result(outputs[0])
|
@@ -1210,8 +1199,10 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
1210
1199
|
script_lines = slurm_config.sort_script_lines(script_lines)
|
1211
1200
|
logger.debug(script_lines)
|
1212
1201
|
|
1213
|
-
# Always print output of `pwd`
|
1214
|
-
script_lines.append(
|
1202
|
+
# Always print output of `uname -n` and `pwd`
|
1203
|
+
script_lines.append(
|
1204
|
+
'"Hostname: `uname -n`; current directory: `pwd`"\n'
|
1205
|
+
)
|
1215
1206
|
|
1216
1207
|
# Complete script preamble
|
1217
1208
|
script_lines.append("\n")
|
@@ -10,6 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# Copyright 2022 (C) Friedrich Miescher Institute for Biomedical Research and
|
12
12
|
# University of Zurich
|
13
|
+
import json
|
13
14
|
import math
|
14
15
|
import shlex
|
15
16
|
import subprocess # nosec
|
@@ -161,7 +162,6 @@ class SlurmJob:
|
|
161
162
|
self,
|
162
163
|
num_tasks_tot: int,
|
163
164
|
slurm_config: SlurmConfig,
|
164
|
-
workflow_task_file_prefix: Optional[str] = None,
|
165
165
|
slurm_file_prefix: Optional[str] = None,
|
166
166
|
wftask_file_prefixes: Optional[tuple[str, ...]] = None,
|
167
167
|
single_task_submission: bool = False,
|
@@ -219,7 +219,6 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
219
219
|
workflow_dir_local: Path
|
220
220
|
workflow_dir_remote: Path
|
221
221
|
map_jobid_to_slurm_files: dict[str, tuple[str, str, str]]
|
222
|
-
keep_pickle_files: bool
|
223
222
|
slurm_account: Optional[str]
|
224
223
|
jobs: dict[str, tuple[Future, SlurmJob]]
|
225
224
|
|
@@ -232,7 +231,6 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
232
231
|
user_cache_dir: Optional[str] = None,
|
233
232
|
common_script_lines: Optional[list[str]] = None,
|
234
233
|
slurm_poll_interval: Optional[int] = None,
|
235
|
-
keep_pickle_files: bool = False,
|
236
234
|
slurm_account: Optional[str] = None,
|
237
235
|
*args,
|
238
236
|
**kwargs,
|
@@ -253,11 +251,18 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
253
251
|
# raised within `__init__`).
|
254
252
|
self.wait_thread.shutdown_callback = self.shutdown
|
255
253
|
|
256
|
-
self.keep_pickle_files = keep_pickle_files
|
257
254
|
self.slurm_user = slurm_user
|
258
255
|
self.slurm_account = slurm_account
|
259
256
|
|
260
257
|
self.common_script_lines = common_script_lines or []
|
258
|
+
settings = Inject(get_settings)
|
259
|
+
|
260
|
+
if settings.FRACTAL_SLURM_WORKER_PYTHON is not None:
|
261
|
+
try:
|
262
|
+
self.check_remote_python_interpreter()
|
263
|
+
except Exception as e:
|
264
|
+
self._stop_and_join_wait_thread()
|
265
|
+
raise RuntimeError(f"Original error {str(e)}")
|
261
266
|
|
262
267
|
# Check that SLURM account is not set here
|
263
268
|
try:
|
@@ -289,7 +294,6 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
289
294
|
# Set the attribute slurm_poll_interval for self.wait_thread (see
|
290
295
|
# cfut.SlurmWaitThread)
|
291
296
|
if not slurm_poll_interval:
|
292
|
-
settings = Inject(get_settings)
|
293
297
|
slurm_poll_interval = settings.FRACTAL_SLURM_POLL_INTERVAL
|
294
298
|
self.wait_thread.slurm_poll_interval = slurm_poll_interval
|
295
299
|
self.wait_thread.slurm_user = self.slurm_user
|
@@ -608,7 +612,14 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
608
612
|
_prefixes = []
|
609
613
|
_subfolder_names = []
|
610
614
|
for component in components:
|
611
|
-
|
615
|
+
# In Fractal, `component` is a `dict` by construction (e.g.
|
616
|
+
# `component = {"zarr_url": "/something", "param": 1}``). The
|
617
|
+
# try/except covers the case of e.g. `executor.map([1, 2])`,
|
618
|
+
# which is useful for testing.
|
619
|
+
try:
|
620
|
+
actual_component = component.get(_COMPONENT_KEY_, None)
|
621
|
+
except AttributeError:
|
622
|
+
actual_component = str(component)
|
612
623
|
_task_file_paths = get_task_file_paths(
|
613
624
|
workflow_dir_local=task_files.workflow_dir_local,
|
614
625
|
workflow_dir_remote=task_files.workflow_dir_remote,
|
@@ -860,8 +871,7 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
860
871
|
" cancelled, exit from"
|
861
872
|
" FractalSlurmExecutor._completion."
|
862
873
|
)
|
863
|
-
|
864
|
-
in_path.unlink()
|
874
|
+
in_path.unlink()
|
865
875
|
self._cleanup(jobid)
|
866
876
|
return
|
867
877
|
|
@@ -903,23 +913,20 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
903
913
|
exc = TaskExecutionError(proxy.tb, **kwargs)
|
904
914
|
fut.set_exception(exc)
|
905
915
|
return
|
906
|
-
|
907
|
-
out_path.unlink()
|
916
|
+
out_path.unlink()
|
908
917
|
except InvalidStateError:
|
909
918
|
logger.warning(
|
910
919
|
f"Future {fut} (SLURM job ID: {jobid}) was already"
|
911
920
|
" cancelled, exit from"
|
912
921
|
" FractalSlurmExecutor._completion."
|
913
922
|
)
|
914
|
-
|
915
|
-
|
916
|
-
in_path.unlink()
|
923
|
+
out_path.unlink()
|
924
|
+
in_path.unlink()
|
917
925
|
self._cleanup(jobid)
|
918
926
|
return
|
919
927
|
|
920
928
|
# Clean up input pickle file
|
921
|
-
|
922
|
-
in_path.unlink()
|
929
|
+
in_path.unlink()
|
923
930
|
self._cleanup(jobid)
|
924
931
|
if job.single_task_submission:
|
925
932
|
fut.set_result(outputs[0])
|
@@ -1155,8 +1162,10 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
1155
1162
|
script_lines = slurm_config.sort_script_lines(script_lines)
|
1156
1163
|
logger.debug(script_lines)
|
1157
1164
|
|
1158
|
-
# Always print output of `pwd`
|
1159
|
-
script_lines.append(
|
1165
|
+
# Always print output of `uname -n` and `pwd`
|
1166
|
+
script_lines.append(
|
1167
|
+
'"Hostname: `uname -n`; current directory: `pwd`"\n'
|
1168
|
+
)
|
1160
1169
|
|
1161
1170
|
# Complete script preamble
|
1162
1171
|
script_lines.append("\n")
|
@@ -1243,3 +1252,29 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
1243
1252
|
)
|
1244
1253
|
self._stop_and_join_wait_thread()
|
1245
1254
|
logger.debug("[FractalSlurmExecutor.__exit__] End")
|
1255
|
+
|
1256
|
+
def check_remote_python_interpreter(self):
|
1257
|
+
"""
|
1258
|
+
Check fractal-server version on the _remote_ Python interpreter.
|
1259
|
+
"""
|
1260
|
+
settings = Inject(get_settings)
|
1261
|
+
output = _subprocess_run_or_raise(
|
1262
|
+
(
|
1263
|
+
f"{settings.FRACTAL_SLURM_WORKER_PYTHON} "
|
1264
|
+
"-m fractal_server.app.runner.versions"
|
1265
|
+
)
|
1266
|
+
)
|
1267
|
+
runner_version = json.loads(output.stdout.strip("\n"))[
|
1268
|
+
"fractal_server"
|
1269
|
+
]
|
1270
|
+
|
1271
|
+
if runner_version != __VERSION__:
|
1272
|
+
error_msg = (
|
1273
|
+
"Fractal-server version mismatch.\n"
|
1274
|
+
"Local interpreter: "
|
1275
|
+
f"({sys.executable}): {__VERSION__}.\n"
|
1276
|
+
"Remote interpreter: "
|
1277
|
+
f"({settings.FRACTAL_SLURM_WORKER_PYTHON}): {runner_version}."
|
1278
|
+
)
|
1279
|
+
logger.error(error_msg)
|
1280
|
+
raise ValueError(error_msg)
|
@@ -252,15 +252,18 @@ class UserManager(IntegerIDMixin, BaseUserManager[UserOAuth, int]):
|
|
252
252
|
# Send mail section
|
253
253
|
settings = Inject(get_settings)
|
254
254
|
|
255
|
-
if
|
255
|
+
if (
|
256
|
+
this_user.oauth_accounts
|
257
|
+
and settings.email_settings is not None
|
258
|
+
):
|
256
259
|
try:
|
257
260
|
logger.info(
|
258
261
|
"START sending email about new signup to "
|
259
|
-
f"{settings.
|
262
|
+
f"{settings.email_settings.recipients}."
|
260
263
|
)
|
261
264
|
mail_new_oauth_signup(
|
262
265
|
msg=f"New user registered: '{this_user.email}'.",
|
263
|
-
|
266
|
+
email_settings=settings.email_settings,
|
264
267
|
)
|
265
268
|
logger.info("END sending email about new signup.")
|
266
269
|
except Exception as e:
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import smtplib
|
2
|
+
from email.message import EmailMessage
|
3
|
+
from email.utils import formataddr
|
4
|
+
|
5
|
+
from cryptography.fernet import Fernet
|
6
|
+
|
7
|
+
from fractal_server.config import MailSettings
|
8
|
+
|
9
|
+
|
10
|
+
def mail_new_oauth_signup(msg: str, email_settings: MailSettings):
|
11
|
+
"""
|
12
|
+
Send an email using the specified settings to notify a new OAuth signup.
|
13
|
+
"""
|
14
|
+
|
15
|
+
mail_msg = EmailMessage()
|
16
|
+
mail_msg.set_content(msg)
|
17
|
+
mail_msg["From"] = formataddr(
|
18
|
+
(email_settings.sender, email_settings.sender)
|
19
|
+
)
|
20
|
+
mail_msg["To"] = ", ".join(
|
21
|
+
[
|
22
|
+
formataddr((recipient, recipient))
|
23
|
+
for recipient in email_settings.recipients
|
24
|
+
]
|
25
|
+
)
|
26
|
+
mail_msg[
|
27
|
+
"Subject"
|
28
|
+
] = f"[Fractal, {email_settings.instance_name}] New OAuth signup"
|
29
|
+
|
30
|
+
with smtplib.SMTP(
|
31
|
+
email_settings.smtp_server, email_settings.port
|
32
|
+
) as server:
|
33
|
+
server.ehlo()
|
34
|
+
if email_settings.use_starttls:
|
35
|
+
server.starttls()
|
36
|
+
server.ehlo()
|
37
|
+
if email_settings.use_login:
|
38
|
+
password = (
|
39
|
+
Fernet(email_settings.encryption_key)
|
40
|
+
.decrypt(email_settings.encrypted_password)
|
41
|
+
.decode("utf-8")
|
42
|
+
)
|
43
|
+
server.login(user=email_settings.sender, password=password)
|
44
|
+
server.sendmail(
|
45
|
+
from_addr=email_settings.sender,
|
46
|
+
to_addrs=email_settings.recipients,
|
47
|
+
msg=mail_msg.as_string(),
|
48
|
+
)
|