fractal-server 2.17.1a0__py3-none-any.whl → 2.17.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/__main__.py +19 -18
  3. fractal_server/app/db/__init__.py +3 -3
  4. fractal_server/app/models/__init__.py +1 -1
  5. fractal_server/app/models/linkuserproject.py +3 -1
  6. fractal_server/app/models/security.py +22 -17
  7. fractal_server/app/models/v2/__init__.py +3 -1
  8. fractal_server/app/models/v2/accounting.py +9 -1
  9. fractal_server/app/models/v2/dataset.py +5 -1
  10. fractal_server/app/models/v2/history.py +15 -1
  11. fractal_server/app/models/v2/job.py +4 -0
  12. fractal_server/app/models/v2/profile.py +29 -0
  13. fractal_server/app/models/v2/project.py +5 -14
  14. fractal_server/app/models/v2/resource.py +4 -0
  15. fractal_server/app/models/v2/task_group.py +5 -7
  16. fractal_server/app/models/v2/workflow.py +2 -1
  17. fractal_server/app/routes/admin/v2/__init__.py +1 -2
  18. fractal_server/app/routes/admin/v2/accounting.py +1 -1
  19. fractal_server/app/routes/admin/v2/job.py +9 -9
  20. fractal_server/app/routes/admin/v2/profile.py +3 -2
  21. fractal_server/app/routes/admin/v2/resource.py +5 -5
  22. fractal_server/app/routes/admin/v2/task.py +28 -18
  23. fractal_server/app/routes/admin/v2/task_group.py +0 -1
  24. fractal_server/app/routes/admin/v2/task_group_lifecycle.py +1 -2
  25. fractal_server/app/routes/api/__init__.py +1 -0
  26. fractal_server/app/routes/api/v2/__init__.py +5 -6
  27. fractal_server/app/routes/api/v2/_aux_functions.py +70 -63
  28. fractal_server/app/routes/api/v2/_aux_functions_history.py +43 -20
  29. fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +2 -4
  30. fractal_server/app/routes/api/v2/_aux_functions_tasks.py +5 -7
  31. fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +1 -2
  32. fractal_server/app/routes/api/v2/dataset.py +13 -32
  33. fractal_server/app/routes/api/v2/history.py +35 -21
  34. fractal_server/app/routes/api/v2/images.py +3 -2
  35. fractal_server/app/routes/api/v2/job.py +17 -14
  36. fractal_server/app/routes/api/v2/pre_submission_checks.py +5 -4
  37. fractal_server/app/routes/api/v2/project.py +22 -17
  38. fractal_server/app/routes/api/v2/status_legacy.py +12 -11
  39. fractal_server/app/routes/api/v2/submit.py +11 -12
  40. fractal_server/app/routes/api/v2/task.py +4 -3
  41. fractal_server/app/routes/api/v2/task_collection.py +28 -30
  42. fractal_server/app/routes/api/v2/task_collection_custom.py +8 -7
  43. fractal_server/app/routes/api/v2/task_collection_pixi.py +1 -2
  44. fractal_server/app/routes/api/v2/task_group.py +7 -6
  45. fractal_server/app/routes/api/v2/task_group_lifecycle.py +6 -6
  46. fractal_server/app/routes/api/v2/task_version_update.py +13 -12
  47. fractal_server/app/routes/api/v2/workflow.py +14 -31
  48. fractal_server/app/routes/api/v2/workflow_import.py +17 -19
  49. fractal_server/app/routes/api/v2/workflowtask.py +10 -12
  50. fractal_server/app/routes/auth/__init__.py +1 -3
  51. fractal_server/app/routes/auth/_aux_auth.py +1 -2
  52. fractal_server/app/routes/auth/current_user.py +4 -5
  53. fractal_server/app/routes/auth/group.py +7 -5
  54. fractal_server/app/routes/auth/login.py +1 -0
  55. fractal_server/app/routes/auth/oauth.py +4 -3
  56. fractal_server/app/routes/auth/register.py +4 -2
  57. fractal_server/app/routes/auth/users.py +10 -10
  58. fractal_server/app/routes/aux/_job.py +1 -1
  59. fractal_server/app/routes/aux/_runner.py +2 -2
  60. fractal_server/app/routes/pagination.py +1 -1
  61. fractal_server/app/schemas/user.py +3 -3
  62. fractal_server/app/schemas/v2/accounting.py +11 -0
  63. fractal_server/app/schemas/v2/dataset.py +28 -4
  64. fractal_server/app/schemas/v2/dumps.py +1 -0
  65. fractal_server/app/schemas/v2/manifest.py +4 -3
  66. fractal_server/app/schemas/v2/profile.py +53 -2
  67. fractal_server/app/schemas/v2/resource.py +109 -13
  68. fractal_server/app/schemas/v2/task.py +0 -1
  69. fractal_server/app/schemas/v2/task_collection.py +1 -1
  70. fractal_server/app/schemas/v2/workflowtask.py +4 -3
  71. fractal_server/app/security/__init__.py +4 -7
  72. fractal_server/app/security/signup_email.py +4 -5
  73. fractal_server/app/shutdown.py +23 -19
  74. fractal_server/config/_data.py +36 -25
  75. fractal_server/config/_database.py +19 -20
  76. fractal_server/config/_email.py +30 -38
  77. fractal_server/config/_main.py +34 -53
  78. fractal_server/config/_oauth.py +17 -21
  79. fractal_server/exceptions.py +4 -0
  80. fractal_server/images/models.py +3 -3
  81. fractal_server/images/status_tools.py +4 -2
  82. fractal_server/logger.py +1 -1
  83. fractal_server/main.py +4 -3
  84. fractal_server/migrations/versions/034a469ec2eb_task_groups.py +4 -8
  85. fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +1 -1
  86. fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +1 -0
  87. fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +1 -1
  88. fractal_server/migrations/versions/1a83a5260664_rename.py +1 -1
  89. fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +1 -0
  90. fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +1 -1
  91. fractal_server/migrations/versions/40d6d6511b20_add_index_to_history_models.py +47 -0
  92. fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +46 -0
  93. fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +1 -0
  94. fractal_server/migrations/versions/49d0856e9569_drop_table.py +62 -0
  95. fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +1 -1
  96. fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +1 -1
  97. fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +2 -1
  98. fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +7 -19
  99. fractal_server/migrations/versions/5bf02391cfef_v2.py +4 -10
  100. fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +1 -0
  101. fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +1 -1
  102. fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +29 -0
  103. fractal_server/migrations/versions/791ce783d3d8_add_indices.py +1 -1
  104. fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +1 -0
  105. fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +1 -0
  106. fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +2 -4
  107. fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +1 -1
  108. fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +1 -0
  109. fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +1 -1
  110. fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +1 -1
  111. fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +1 -1
  112. fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +2 -4
  113. fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +1 -1
  114. fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +1 -1
  115. fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +1 -1
  116. fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +1 -1
  117. fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +1 -0
  118. fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +1 -0
  119. fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +1 -1
  120. fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +1 -0
  121. fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +1 -1
  122. fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +49 -0
  123. fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +4 -9
  124. fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +1 -0
  125. fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +1 -1
  126. fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +1 -0
  127. fractal_server/migrations/versions/e0e717ae2f26_delete_linkuserproject_ondelete_project.py +50 -0
  128. fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +1 -0
  129. fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +1 -1
  130. fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +1 -0
  131. fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +1 -1
  132. fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +1 -0
  133. fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +4 -9
  134. fractal_server/runner/config/_local.py +8 -5
  135. fractal_server/runner/config/_slurm.py +37 -33
  136. fractal_server/runner/config/slurm_mem_to_MB.py +0 -1
  137. fractal_server/runner/executors/base_runner.py +29 -4
  138. fractal_server/runner/executors/local/get_local_config.py +1 -0
  139. fractal_server/runner/executors/local/runner.py +14 -13
  140. fractal_server/runner/executors/slurm_common/_batching.py +5 -10
  141. fractal_server/runner/executors/slurm_common/base_slurm_runner.py +53 -27
  142. fractal_server/runner/executors/slurm_common/get_slurm_config.py +14 -7
  143. fractal_server/runner/executors/slurm_common/remote.py +3 -1
  144. fractal_server/runner/executors/slurm_common/slurm_config.py +1 -0
  145. fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +1 -3
  146. fractal_server/runner/executors/slurm_ssh/runner.py +16 -11
  147. fractal_server/runner/executors/slurm_ssh/tar_commands.py +1 -0
  148. fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +1 -0
  149. fractal_server/runner/executors/slurm_sudo/runner.py +16 -11
  150. fractal_server/runner/task_files.py +9 -3
  151. fractal_server/runner/v2/_local.py +9 -4
  152. fractal_server/runner/v2/_slurm_ssh.py +11 -5
  153. fractal_server/runner/v2/_slurm_sudo.py +11 -5
  154. fractal_server/runner/v2/db_tools.py +0 -1
  155. fractal_server/runner/v2/deduplicate_list.py +2 -1
  156. fractal_server/runner/v2/runner.py +11 -14
  157. fractal_server/runner/v2/runner_functions.py +11 -14
  158. fractal_server/runner/v2/submit_workflow.py +7 -6
  159. fractal_server/ssh/_fabric.py +6 -13
  160. fractal_server/string_tools.py +0 -1
  161. fractal_server/syringe.py +1 -1
  162. fractal_server/tasks/config/_pixi.py +1 -1
  163. fractal_server/tasks/config/_python.py +16 -9
  164. fractal_server/tasks/utils.py +0 -1
  165. fractal_server/tasks/v2/local/_utils.py +1 -1
  166. fractal_server/tasks/v2/local/collect.py +10 -12
  167. fractal_server/tasks/v2/local/collect_pixi.py +9 -10
  168. fractal_server/tasks/v2/local/deactivate.py +7 -8
  169. fractal_server/tasks/v2/local/deactivate_pixi.py +4 -4
  170. fractal_server/tasks/v2/local/delete.py +1 -3
  171. fractal_server/tasks/v2/local/reactivate.py +7 -7
  172. fractal_server/tasks/v2/local/reactivate_pixi.py +7 -7
  173. fractal_server/tasks/v2/ssh/_utils.py +3 -3
  174. fractal_server/tasks/v2/ssh/collect.py +14 -19
  175. fractal_server/tasks/v2/ssh/collect_pixi.py +17 -19
  176. fractal_server/tasks/v2/ssh/deactivate.py +10 -8
  177. fractal_server/tasks/v2/ssh/deactivate_pixi.py +6 -5
  178. fractal_server/tasks/v2/ssh/delete.py +7 -5
  179. fractal_server/tasks/v2/ssh/reactivate.py +11 -11
  180. fractal_server/tasks/v2/ssh/reactivate_pixi.py +8 -9
  181. fractal_server/tasks/v2/templates/1_create_venv.sh +2 -0
  182. fractal_server/tasks/v2/templates/2_pip_install.sh +2 -0
  183. fractal_server/tasks/v2/templates/3_pip_freeze.sh +2 -0
  184. fractal_server/tasks/v2/templates/4_pip_show.sh +2 -0
  185. fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +3 -1
  186. fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +2 -0
  187. fractal_server/tasks/v2/templates/pixi_1_extract.sh +2 -0
  188. fractal_server/tasks/v2/templates/pixi_2_install.sh +2 -0
  189. fractal_server/tasks/v2/templates/pixi_3_post_install.sh +2 -0
  190. fractal_server/tasks/v2/utils_background.py +3 -3
  191. fractal_server/tasks/v2/utils_package_names.py +1 -2
  192. fractal_server/tasks/v2/utils_pixi.py +1 -3
  193. fractal_server/types/__init__.py +76 -1
  194. fractal_server/types/validators/_common_validators.py +1 -3
  195. fractal_server/types/validators/_workflow_task_arguments_validators.py +1 -2
  196. fractal_server/utils.py +1 -0
  197. fractal_server/zip_tools.py +34 -0
  198. {fractal_server-2.17.1a0.dist-info → fractal_server-2.17.2.dist-info}/METADATA +1 -1
  199. fractal_server-2.17.2.dist-info/RECORD +265 -0
  200. fractal_server/app/models/user_settings.py +0 -37
  201. fractal_server/app/routes/admin/v2/project.py +0 -41
  202. fractal_server/data_migrations/2_17_0.py +0 -339
  203. fractal_server-2.17.1a0.dist-info/RECORD +0 -262
  204. {fractal_server-2.17.1a0.dist-info → fractal_server-2.17.2.dist-info}/WHEEL +0 -0
  205. {fractal_server-2.17.1a0.dist-info → fractal_server-2.17.2.dist-info}/entry_points.txt +0 -0
  206. {fractal_server-2.17.1a0.dist-info → fractal_server-2.17.2.dist-info}/licenses/LICENSE +0 -0
@@ -11,68 +11,49 @@ from ._settings_config import SETTINGS_CONFIG_DICT
11
11
 
12
12
  class Settings(BaseSettings):
13
13
  """
14
- Contains all the configuration variables for Fractal Server
15
-
16
- The attributes of this class are set from the environment.
14
+ Contains the general configuration variables for Fractal Server.
15
+
16
+ Attributes:
17
+ JWT_EXPIRE_SECONDS:
18
+ JWT token lifetime, in seconds.
19
+ JWT_SECRET_KEY:
20
+ JWT secret.<br>
21
+ ⚠️ Set this variable to a secure string, and do not disclose it.
22
+ COOKIE_EXPIRE_SECONDS:
23
+ Cookie token lifetime, in seconds.
24
+ FRACTAL_RUNNER_BACKEND:
25
+ Select which runner backend to use.
26
+ FRACTAL_LOGGING_LEVEL:
27
+ Logging-level threshold for logging
28
+ Only logs of with this level (or higher) will appear in the console
29
+ logs.
30
+ FRACTAL_API_MAX_JOB_LIST_LENGTH:
31
+ Number of ids that can be stored in the `jobsV2` attribute of
32
+ `app.state`.
33
+ FRACTAL_GRACEFUL_SHUTDOWN_TIME:
34
+ Waiting time for the shutdown phase of executors, in seconds.
35
+ FRACTAL_HELP_URL:
36
+ The URL of an instance-specific Fractal help page.
37
+ FRACTAL_DEFAULT_GROUP_NAME:
38
+ Name of the default user group.
39
+
40
+ If set to `"All"`, then the user group with that name is a special
41
+ user group (e.g. it cannot be deleted, and new users are
42
+ automatically added to it). If set to `None` (the default value),
43
+ then user groups are all equivalent, independently on their name.
17
44
  """
18
45
 
19
46
  model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
20
47
 
21
48
  JWT_EXPIRE_SECONDS: int = 180
22
- """
23
- JWT token lifetime, in seconds.
24
- """
25
-
26
49
  JWT_SECRET_KEY: SecretStr
27
- """
28
- JWT secret
29
-
30
- ⚠️ **IMPORTANT**: set this variable to a secure string, and do not disclose
31
- it.
32
- """
33
-
34
50
  COOKIE_EXPIRE_SECONDS: int = 86400
35
- """
36
- Cookie token lifetime, in seconds.
37
- """
38
-
39
51
  # Note: we do not use ResourceType here to avoid circular imports
40
- FRACTAL_RUNNER_BACKEND: Literal[
41
- "local", "slurm_ssh", "slurm_sudo"
42
- ] = "local"
43
- """
44
- Select which runner backend to use.
45
- """
46
-
52
+ FRACTAL_RUNNER_BACKEND: Literal["local", "slurm_ssh", "slurm_sudo"] = (
53
+ "local"
54
+ )
47
55
  FRACTAL_LOGGING_LEVEL: int = logging.INFO
48
- """
49
- Logging-level threshold for logging
50
-
51
- Only logs of with this level (or higher) will appear in the console logs.
52
- """
53
-
54
56
  FRACTAL_API_MAX_JOB_LIST_LENGTH: int = 25
55
- """
56
- Number of ids that can be stored in the `jobsV2` attribute of
57
- `app.state`.
58
- """
59
-
60
- FRACTAL_GRACEFUL_SHUTDOWN_TIME: int = 30
61
- """
62
- Waiting time for the shutdown phase of executors
63
- """
64
-
57
+ FRACTAL_GRACEFUL_SHUTDOWN_TIME: float = 30.0
65
58
  FRACTAL_HELP_URL: HttpUrl | None = None
66
- """
67
- The URL of an instance-specific Fractal help page.
68
- """
69
-
70
59
  FRACTAL_DEFAULT_GROUP_NAME: Literal["All"] | None = None
71
- """
72
- Name of the default user group.
73
-
74
- If set to `"All"`, then the user group with that name is a special user
75
- group (e.g. it cannot be deleted, and new users are automatically added
76
- to it). If set to `None` (the default value), then user groups are all
77
- equivalent, independently on their name.
78
- """
@@ -1,20 +1,33 @@
1
1
  from typing import Annotated
2
2
  from typing import Self
3
3
 
4
- from pydantic import model_validator
5
4
  from pydantic import SecretStr
6
5
  from pydantic import StringConstraints
6
+ from pydantic import model_validator
7
7
  from pydantic_settings import BaseSettings
8
8
  from pydantic_settings import SettingsConfigDict
9
9
 
10
- from ._settings_config import SETTINGS_CONFIG_DICT
11
10
  from fractal_server.types import NonEmptyStr
12
11
 
12
+ from ._settings_config import SETTINGS_CONFIG_DICT
13
+
13
14
 
14
15
  class OAuthSettings(BaseSettings):
15
16
  """
16
- Minimal set of configurations needed for operating on the database (e.g
17
- for schema migrations).
17
+ Settings for integration with an OAuth identity provider.
18
+
19
+ Attributes:
20
+ OAUTH_CLIENT_NAME: Name of the client.
21
+ OAUTH_CLIENT_ID: ID of client.
22
+ OAUTH_CLIENT_SECRET:
23
+ Secret to authorise against the identity provider.
24
+ OAUTH_OIDC_CONFIG_ENDPOINT:
25
+ OpenID Connect configuration endpoint, for autodiscovery of
26
+ relevant endpoints.
27
+ OAUTH_REDIRECT_URL:
28
+ String to be used as `redirect_url` argument in
29
+ `fastapi_users.get_oauth_router`, and then in
30
+ `httpx_oauth.integrations.fastapi.OAuth2AuthorizeCallback`.
18
31
  """
19
32
 
20
33
  model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
@@ -26,27 +39,10 @@ class OAuthSettings(BaseSettings):
26
39
  ]
27
40
  | None
28
41
  ) = None
29
- """
30
- The name of the client.
31
- """
32
42
  OAUTH_CLIENT_ID: SecretStr | None = None
33
- """
34
- ID of client.
35
- """
36
43
  OAUTH_CLIENT_SECRET: SecretStr | None = None
37
- """
38
- Secret to authorise against the identity provider.
39
- """
40
44
  OAUTH_OIDC_CONFIG_ENDPOINT: SecretStr | None = None
41
- """
42
- OpenID configuration endpoint, for autodiscovery of relevant endpoints.
43
- """
44
45
  OAUTH_REDIRECT_URL: str | None = None
45
- """
46
- String to be used as `redirect_url` argument in
47
- `fastapi_users.get_oauth_router`, and then in
48
- `httpx_oauth.integrations.fastapi.OAuth2AuthorizeCallback`
49
- """
50
46
 
51
47
  @model_validator(mode="after")
52
48
  def check_configuration(self: Self) -> Self:
@@ -1,2 +1,6 @@
1
1
  class UnreachableBranchError(RuntimeError):
2
+ """
3
+ Exception marking a code branch that should have not been reached.
4
+ """
5
+
2
6
  pass
@@ -9,7 +9,7 @@ from fractal_server.types import ZarrDirStr
9
9
  from fractal_server.types import ZarrUrlStr
10
10
 
11
11
 
12
- class _SingleImageBase(BaseModel):
12
+ class SingleImageBase(BaseModel):
13
13
  """
14
14
  Base for SingleImage and SingleImageTaskOutput.
15
15
 
@@ -27,7 +27,7 @@ class _SingleImageBase(BaseModel):
27
27
  types: ImageTypes = Field(default_factory=dict)
28
28
 
29
29
 
30
- class SingleImageTaskOutput(_SingleImageBase):
30
+ class SingleImageTaskOutput(SingleImageBase):
31
31
  """
32
32
  `SingleImageBase`, with scalar `attributes` values (`None` included).
33
33
  """
@@ -35,7 +35,7 @@ class SingleImageTaskOutput(_SingleImageBase):
35
35
  attributes: ImageAttributesWithNone = Field(default_factory=dict)
36
36
 
37
37
 
38
- class SingleImage(_SingleImageBase):
38
+ class SingleImage(SingleImageBase):
39
39
  """
40
40
  `SingleImageBase`, with scalar `attributes` values (`None` excluded).
41
41
  """
@@ -37,10 +37,12 @@ def _prepare_query(
37
37
  """
38
38
  stm = (
39
39
  select(HistoryImageCache.zarr_url, HistoryUnit.status)
40
- .join(HistoryUnit)
40
+ .join(
41
+ HistoryUnit,
42
+ HistoryImageCache.latest_history_unit_id == HistoryUnit.id,
43
+ )
41
44
  .where(HistoryImageCache.dataset_id == dataset_id)
42
45
  .where(HistoryImageCache.workflowtask_id == workflowtask_id)
43
- .where(HistoryImageCache.latest_history_unit_id == HistoryUnit.id)
44
46
  )
45
47
  return stm
46
48
 
fractal_server/logger.py CHANGED
@@ -12,13 +12,13 @@
12
12
  """
13
13
  This module provides logging utilities
14
14
  """
15
+
15
16
  import logging
16
17
  from pathlib import Path
17
18
 
18
19
  from .config import get_settings
19
20
  from .syringe import Inject
20
21
 
21
-
22
22
  LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
23
23
  LOG_FORMATTER = logging.Formatter(LOG_FORMAT)
24
24
 
fractal_server/main.py CHANGED
@@ -4,6 +4,9 @@ from itertools import chain
4
4
 
5
5
  from fastapi import FastAPI
6
6
 
7
+ from fractal_server import __VERSION__
8
+ from fractal_server.app.schemas.v2 import ResourceType
9
+
7
10
  from .app.routes.aux._runner import _backend_supports_shutdown
8
11
  from .app.shutdown import cleanup_after_shutdown
9
12
  from .config import get_data_settings
@@ -15,8 +18,6 @@ from .logger import get_logger
15
18
  from .logger import reset_logger_handlers
16
19
  from .logger import set_logger
17
20
  from .syringe import Inject
18
- from fractal_server import __VERSION__
19
- from fractal_server.app.schemas.v2 import ResourceType
20
21
 
21
22
 
22
23
  def collect_routers(app: FastAPI) -> None:
@@ -27,9 +28,9 @@ def collect_routers(app: FastAPI) -> None:
27
28
  app:
28
29
  The application to register the routers to.
29
30
  """
31
+ from .app.routes.admin.v2 import router_admin_v2
30
32
  from .app.routes.api import router_api
31
33
  from .app.routes.api.v2 import router_api_v2
32
- from .app.routes.admin.v2 import router_admin_v2
33
34
  from .app.routes.auth.router import router_auth
34
35
 
35
36
  app.include_router(router_api, prefix="/api")
@@ -5,6 +5,7 @@ Revises: da2cb2ac4255
5
5
  Create Date: 2024-10-10 16:14:13.976231
6
6
 
7
7
  """
8
+
8
9
  from datetime import datetime
9
10
  from datetime import timezone
10
11
 
@@ -12,7 +13,6 @@ import sqlalchemy as sa
12
13
  import sqlmodel
13
14
  from alembic import op
14
15
 
15
-
16
16
  # revision identifiers, used by Alembic.
17
17
  revision = "034a469ec2eb"
18
18
  down_revision = "da2cb2ac4255"
@@ -26,15 +26,11 @@ def upgrade() -> None:
26
26
  sa.Column("id", sa.Integer(), nullable=False),
27
27
  sa.Column("user_id", sa.Integer(), nullable=False),
28
28
  sa.Column("user_group_id", sa.Integer(), nullable=True),
29
- sa.Column(
30
- "origin", sqlmodel.sql.sqltypes.AutoString(), nullable=False
31
- ),
29
+ sa.Column("origin", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
32
30
  sa.Column(
33
31
  "pkg_name", sqlmodel.sql.sqltypes.AutoString(), nullable=False
34
32
  ),
35
- sa.Column(
36
- "version", sqlmodel.sql.sqltypes.AutoString(), nullable=True
37
- ),
33
+ sa.Column("version", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
38
34
  sa.Column(
39
35
  "python_version", sqlmodel.sql.sqltypes.AutoString(), nullable=True
40
36
  ),
@@ -123,8 +119,8 @@ def upgrade() -> None:
123
119
  except BaseException as e:
124
120
  if op.get_bind().dialect.name != "sqlite":
125
121
  raise e
126
- import sqlite3
127
122
  import logging
123
+ import sqlite3
128
124
 
129
125
  logger = logging.getLogger("alembic.runtime.migration")
130
126
  logger.warning(
@@ -5,11 +5,11 @@ Revises: 5bf02391cfef
5
5
  Create Date: 2024-09-09 13:17:51.008231
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  import sqlmodel
10
11
  from alembic import op
11
12
 
12
-
13
13
  # revision identifiers, used by Alembic.
14
14
  revision = "091b01f51f88"
15
15
  down_revision = "5bf02391cfef"
@@ -5,6 +5,7 @@ Revises: 1a83a5260664
5
5
  Create Date: 2025-09-10 14:36:06.028179
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
  from sqlalchemy.dialects import postgresql
@@ -5,11 +5,11 @@ Revises: 8e8f227a3e36
5
5
  Create Date: 2024-10-30 14:34:28.219355
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  import sqlmodel
10
11
  from alembic import op
11
12
 
12
-
13
13
  # revision identifiers, used by Alembic.
14
14
  revision = "19eca0dd47a9"
15
15
  down_revision = "8e8f227a3e36"
@@ -5,8 +5,8 @@ Revises: b3ffb095f973
5
5
  Create Date: 2025-09-10 14:16:51.202765
6
6
 
7
7
  """
8
- from alembic import op
9
8
 
9
+ from alembic import op
10
10
 
11
11
  # revision identifiers, used by Alembic.
12
12
  revision = "1a83a5260664"
@@ -5,6 +5,7 @@ Revises: af8673379a5c
5
5
  Create Date: 2025-01-10 13:17:47.838607
6
6
 
7
7
  """
8
+
8
9
  import logging
9
10
 
10
11
  from alembic import op
@@ -5,10 +5,10 @@ Revises: d256a7379ab8
5
5
  Create Date: 2024-12-03 10:15:53.255958
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
11
-
12
12
  # revision identifiers, used by Alembic.
13
13
  revision = "316140ff7ee1"
14
14
  down_revision = "d256a7379ab8"
@@ -0,0 +1,47 @@
1
+ """add index to history models
2
+
3
+ Revision ID: 40d6d6511b20
4
+ Revises: 7673fe18c05d
5
+ Create Date: 2025-11-14 10:34:12.300920
6
+
7
+ """
8
+
9
+ from alembic import op
10
+
11
+ # revision identifiers, used by Alembic.
12
+ revision = "40d6d6511b20"
13
+ down_revision = "7673fe18c05d"
14
+ branch_labels = None
15
+ depends_on = None
16
+
17
+
18
+ def upgrade() -> None:
19
+ # ### commands auto generated by Alembic - please adjust! ###
20
+ with op.batch_alter_table("historyimagecache", schema=None) as batch_op:
21
+ batch_op.create_index(
22
+ batch_op.f("ix_historyimagecache_latest_history_unit_id"),
23
+ ["latest_history_unit_id"],
24
+ unique=False,
25
+ )
26
+
27
+ with op.batch_alter_table("historyunit", schema=None) as batch_op:
28
+ batch_op.create_index(
29
+ batch_op.f("ix_historyunit_history_run_id"),
30
+ ["history_run_id"],
31
+ unique=False,
32
+ )
33
+
34
+ # ### end Alembic commands ###
35
+
36
+
37
+ def downgrade() -> None:
38
+ # ### commands auto generated by Alembic - please adjust! ###
39
+ with op.batch_alter_table("historyunit", schema=None) as batch_op:
40
+ batch_op.drop_index(batch_op.f("ix_historyunit_history_run_id"))
41
+
42
+ with op.batch_alter_table("historyimagecache", schema=None) as batch_op:
43
+ batch_op.drop_index(
44
+ batch_op.f("ix_historyimagecache_latest_history_unit_id")
45
+ )
46
+
47
+ # ### end Alembic commands ###
@@ -0,0 +1,46 @@
1
+ """Make resource_id FK non-nullable
2
+
3
+ Revision ID: 45fbb391d7af
4
+ Revises: caba9fb1ea5e
5
+ Create Date: 2025-11-11 16:39:12.813766
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "45fbb391d7af"
14
+ down_revision = "caba9fb1ea5e"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade() -> None:
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ with op.batch_alter_table("projectv2", schema=None) as batch_op:
22
+ batch_op.alter_column(
23
+ "resource_id", existing_type=sa.INTEGER(), nullable=False
24
+ )
25
+
26
+ with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
27
+ batch_op.alter_column(
28
+ "resource_id", existing_type=sa.INTEGER(), nullable=False
29
+ )
30
+
31
+ # ### end Alembic commands ###
32
+
33
+
34
+ def downgrade() -> None:
35
+ # ### commands auto generated by Alembic - please adjust! ###
36
+ with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
37
+ batch_op.alter_column(
38
+ "resource_id", existing_type=sa.INTEGER(), nullable=True
39
+ )
40
+
41
+ with op.batch_alter_table("projectv2", schema=None) as batch_op:
42
+ batch_op.alter_column(
43
+ "resource_id", existing_type=sa.INTEGER(), nullable=True
44
+ )
45
+
46
+ # ### end Alembic commands ###
@@ -5,6 +5,7 @@ Revises: fbce16ff4e47
5
5
  Create Date: 2025-03-26 11:10:17.869028
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
  from sqlalchemy.dialects import postgresql
@@ -0,0 +1,62 @@
1
+ """Drop table
2
+
3
+ Revision ID: 49d0856e9569
4
+ Revises: 45fbb391d7af
5
+ Create Date: 2025-11-11 16:39:41.497832
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+ from sqlalchemy.dialects import postgresql
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "49d0856e9569"
15
+ down_revision = "45fbb391d7af"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade() -> None:
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ op.drop_table("user_settings")
23
+ # ### end Alembic commands ###
24
+
25
+
26
+ def downgrade() -> None:
27
+ # ### commands auto generated by Alembic - please adjust! ###
28
+ op.create_table(
29
+ "user_settings",
30
+ sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
31
+ sa.Column(
32
+ "slurm_accounts",
33
+ postgresql.JSONB(astext_type=sa.Text()),
34
+ server_default=sa.text("'[]'::json"),
35
+ autoincrement=False,
36
+ nullable=False,
37
+ ),
38
+ sa.Column("ssh_host", sa.VARCHAR(), autoincrement=False, nullable=True),
39
+ sa.Column(
40
+ "ssh_username", sa.VARCHAR(), autoincrement=False, nullable=True
41
+ ),
42
+ sa.Column(
43
+ "ssh_private_key_path",
44
+ sa.VARCHAR(),
45
+ autoincrement=False,
46
+ nullable=True,
47
+ ),
48
+ sa.Column(
49
+ "ssh_tasks_dir", sa.VARCHAR(), autoincrement=False, nullable=True
50
+ ),
51
+ sa.Column(
52
+ "ssh_jobs_dir", sa.VARCHAR(), autoincrement=False, nullable=True
53
+ ),
54
+ sa.Column(
55
+ "slurm_user", sa.VARCHAR(), autoincrement=False, nullable=True
56
+ ),
57
+ sa.Column(
58
+ "project_dir", sa.VARCHAR(), autoincrement=False, nullable=True
59
+ ),
60
+ sa.PrimaryKeyConstraint("id", name=op.f("pk_user_settings")),
61
+ )
62
+ # ### end Alembic commands ###
@@ -5,11 +5,11 @@ Revises: 50a13d6138fd
5
5
  Create Date: 2023-05-29 17:09:02.492639
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  import sqlmodel
10
11
  from alembic import op
11
12
 
12
-
13
13
  # revision identifiers, used by Alembic.
14
14
  revision = "4c308bcaea2b"
15
15
  down_revision = "50a13d6138fd"
@@ -5,10 +5,10 @@ Revises: efa89c30e0a4
5
5
  Create Date: 2024-01-16 13:57:47.891931
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
11
-
12
12
  # revision identifiers, used by Alembic.
13
13
  revision = "4cedeb448a53"
14
14
  down_revision = "efa89c30e0a4"
@@ -5,6 +5,7 @@ Revises: 5bf02391cfef
5
5
  Create Date: 2024-09-09 14:15:34.415926
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
@@ -36,8 +37,8 @@ def upgrade() -> None:
36
37
  # NOTE: in sqlite, the `drop_index` command fails if the existing table
37
38
  # has zero rows, while it succeeds if there are already some rows
38
39
  if op.get_bind().dialect.name == "sqlite":
39
- import sqlite3
40
40
  import logging
41
+ import sqlite3
41
42
 
42
43
  logger = logging.getLogger("alembic.runtime.migration")
43
44
  logger.warning(
@@ -5,11 +5,11 @@ Revises:
5
5
  Create Date: 2023-05-29 12:14:56.670243
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  import sqlmodel
10
11
  from alembic import op
11
12
 
12
-
13
13
  # revision identifiers, used by Alembic.
14
14
  revision = "50a13d6138fd"
15
15
  down_revision = None
@@ -37,9 +37,7 @@ def upgrade() -> None:
37
37
  "task",
38
38
  sa.Column("default_args", sa.JSON(), nullable=True),
39
39
  sa.Column("meta", sa.JSON(), nullable=True),
40
- sa.Column(
41
- "source", sqlmodel.sql.sqltypes.AutoString(), nullable=False
42
- ),
40
+ sa.Column("source", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
43
41
  sa.Column("id", sa.Integer(), nullable=False),
44
42
  sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
45
43
  sa.Column(
@@ -52,9 +50,7 @@ def upgrade() -> None:
52
50
  "output_type", sqlmodel.sql.sqltypes.AutoString(), nullable=False
53
51
  ),
54
52
  sa.Column("owner", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
55
- sa.Column(
56
- "version", sqlmodel.sql.sqltypes.AutoString(), nullable=True
57
- ),
53
+ sa.Column("version", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
58
54
  sa.PrimaryKeyConstraint("id"),
59
55
  sa.UniqueConstraint("source"),
60
56
  )
@@ -163,9 +159,7 @@ def upgrade() -> None:
163
159
  )
164
160
  op.create_table(
165
161
  "applyworkflow",
166
- sa.Column(
167
- "start_timestamp", sa.DateTime(timezone=True), nullable=True
168
- ),
162
+ sa.Column("start_timestamp", sa.DateTime(timezone=True), nullable=True),
169
163
  sa.Column("end_timestamp", sa.DateTime(timezone=True), nullable=True),
170
164
  sa.Column(
171
165
  "worker_init", sqlmodel.sql.sqltypes.AutoString(), nullable=True
@@ -183,9 +177,7 @@ def upgrade() -> None:
183
177
  sqlmodel.sql.sqltypes.AutoString(),
184
178
  nullable=True,
185
179
  ),
186
- sa.Column(
187
- "status", sqlmodel.sql.sqltypes.AutoString(), nullable=False
188
- ),
180
+ sa.Column("status", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
189
181
  sa.Column("log", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
190
182
  sa.ForeignKeyConstraint(
191
183
  ["input_dataset_id"],
@@ -243,12 +235,8 @@ def downgrade() -> None:
243
235
  op.drop_table("resource")
244
236
  op.drop_table("applyworkflow")
245
237
  op.drop_table("workflow")
246
- op.drop_index(
247
- op.f("ix_oauthaccount_oauth_name"), table_name="oauthaccount"
248
- )
249
- op.drop_index(
250
- op.f("ix_oauthaccount_account_id"), table_name="oauthaccount"
251
- )
238
+ op.drop_index(op.f("ix_oauthaccount_oauth_name"), table_name="oauthaccount")
239
+ op.drop_index(op.f("ix_oauthaccount_account_id"), table_name="oauthaccount")
252
240
  op.drop_table("oauthaccount")
253
241
  op.drop_table("linkuserproject")
254
242
  op.drop_table("dataset")