fractal-server 2.14.5__py3-none-any.whl → 2.14.6__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 (108) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/app/db/__init__.py +2 -2
  3. fractal_server/app/models/security.py +8 -8
  4. fractal_server/app/models/user_settings.py +8 -10
  5. fractal_server/app/models/v2/accounting.py +2 -3
  6. fractal_server/app/models/v2/dataset.py +1 -2
  7. fractal_server/app/models/v2/history.py +3 -4
  8. fractal_server/app/models/v2/job.py +10 -11
  9. fractal_server/app/models/v2/project.py +1 -2
  10. fractal_server/app/models/v2/task.py +13 -14
  11. fractal_server/app/models/v2/task_group.py +15 -16
  12. fractal_server/app/models/v2/workflow.py +1 -2
  13. fractal_server/app/models/v2/workflowtask.py +6 -7
  14. fractal_server/app/routes/admin/v2/accounting.py +3 -4
  15. fractal_server/app/routes/admin/v2/job.py +13 -14
  16. fractal_server/app/routes/admin/v2/project.py +2 -4
  17. fractal_server/app/routes/admin/v2/task.py +11 -13
  18. fractal_server/app/routes/admin/v2/task_group.py +15 -17
  19. fractal_server/app/routes/admin/v2/task_group_lifecycle.py +5 -8
  20. fractal_server/app/routes/api/v2/__init__.py +2 -0
  21. fractal_server/app/routes/api/v2/_aux_functions.py +7 -9
  22. fractal_server/app/routes/api/v2/_aux_functions_history.py +1 -1
  23. fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +1 -3
  24. fractal_server/app/routes/api/v2/_aux_functions_tasks.py +5 -6
  25. fractal_server/app/routes/api/v2/dataset.py +6 -8
  26. fractal_server/app/routes/api/v2/history.py +5 -8
  27. fractal_server/app/routes/api/v2/images.py +2 -3
  28. fractal_server/app/routes/api/v2/job.py +5 -6
  29. fractal_server/app/routes/api/v2/pre_submission_checks.py +1 -3
  30. fractal_server/app/routes/api/v2/project.py +2 -4
  31. fractal_server/app/routes/api/v2/status_legacy.py +2 -4
  32. fractal_server/app/routes/api/v2/submit.py +3 -4
  33. fractal_server/app/routes/api/v2/task.py +6 -7
  34. fractal_server/app/routes/api/v2/task_collection.py +11 -13
  35. fractal_server/app/routes/api/v2/task_collection_custom.py +4 -4
  36. fractal_server/app/routes/api/v2/task_group.py +6 -8
  37. fractal_server/app/routes/api/v2/task_group_lifecycle.py +6 -9
  38. fractal_server/app/routes/api/v2/task_version_update.py +270 -0
  39. fractal_server/app/routes/api/v2/workflow.py +5 -6
  40. fractal_server/app/routes/api/v2/workflow_import.py +3 -5
  41. fractal_server/app/routes/api/v2/workflowtask.py +2 -114
  42. fractal_server/app/routes/auth/current_user.py +2 -2
  43. fractal_server/app/routes/pagination.py +2 -3
  44. fractal_server/app/runner/exceptions.py +15 -16
  45. fractal_server/app/runner/executors/base_runner.py +3 -3
  46. fractal_server/app/runner/executors/call_command_wrapper.py +1 -1
  47. fractal_server/app/runner/executors/local/get_local_config.py +2 -3
  48. fractal_server/app/runner/executors/local/runner.py +1 -1
  49. fractal_server/app/runner/executors/slurm_common/_batching.py +2 -3
  50. fractal_server/app/runner/executors/slurm_common/_slurm_config.py +27 -29
  51. fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +11 -14
  52. fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +2 -3
  53. fractal_server/app/runner/executors/slurm_common/remote.py +2 -2
  54. fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +2 -3
  55. fractal_server/app/runner/executors/slurm_ssh/run_subprocess.py +2 -3
  56. fractal_server/app/runner/executors/slurm_ssh/runner.py +3 -4
  57. fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +1 -2
  58. fractal_server/app/runner/executors/slurm_sudo/runner.py +6 -7
  59. fractal_server/app/runner/set_start_and_last_task_index.py +2 -5
  60. fractal_server/app/runner/shutdown.py +5 -11
  61. fractal_server/app/runner/task_files.py +3 -5
  62. fractal_server/app/runner/v2/_local.py +3 -4
  63. fractal_server/app/runner/v2/_slurm_ssh.py +4 -5
  64. fractal_server/app/runner/v2/_slurm_sudo.py +7 -8
  65. fractal_server/app/runner/v2/runner.py +4 -5
  66. fractal_server/app/runner/v2/runner_functions.py +4 -5
  67. fractal_server/app/runner/v2/submit_workflow.py +7 -10
  68. fractal_server/app/runner/v2/task_interface.py +2 -3
  69. fractal_server/app/runner/versions.py +1 -2
  70. fractal_server/app/schemas/user.py +2 -4
  71. fractal_server/app/schemas/user_group.py +1 -2
  72. fractal_server/app/schemas/user_settings.py +19 -21
  73. fractal_server/app/schemas/v2/dataset.py +2 -3
  74. fractal_server/app/schemas/v2/dumps.py +13 -15
  75. fractal_server/app/schemas/v2/history.py +6 -7
  76. fractal_server/app/schemas/v2/job.py +17 -18
  77. fractal_server/app/schemas/v2/manifest.py +12 -13
  78. fractal_server/app/schemas/v2/status_legacy.py +2 -2
  79. fractal_server/app/schemas/v2/task.py +29 -30
  80. fractal_server/app/schemas/v2/task_collection.py +8 -9
  81. fractal_server/app/schemas/v2/task_group.py +22 -23
  82. fractal_server/app/schemas/v2/workflow.py +1 -2
  83. fractal_server/app/schemas/v2/workflowtask.py +27 -29
  84. fractal_server/app/security/__init__.py +10 -12
  85. fractal_server/config.py +32 -33
  86. fractal_server/images/models.py +2 -4
  87. fractal_server/images/tools.py +4 -7
  88. fractal_server/logger.py +3 -5
  89. fractal_server/ssh/_fabric.py +37 -12
  90. fractal_server/string_tools.py +2 -2
  91. fractal_server/syringe.py +1 -1
  92. fractal_server/tasks/v2/local/collect.py +2 -3
  93. fractal_server/tasks/v2/local/deactivate.py +1 -1
  94. fractal_server/tasks/v2/local/reactivate.py +1 -1
  95. fractal_server/tasks/v2/ssh/collect.py +256 -245
  96. fractal_server/tasks/v2/ssh/deactivate.py +210 -187
  97. fractal_server/tasks/v2/ssh/reactivate.py +154 -146
  98. fractal_server/tasks/v2/utils_background.py +2 -3
  99. fractal_server/types/__init__.py +1 -2
  100. fractal_server/types/validators/_filter_validators.py +1 -2
  101. fractal_server/utils.py +4 -5
  102. fractal_server/zip_tools.py +1 -1
  103. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/METADATA +2 -3
  104. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/RECORD +107 -107
  105. fractal_server/app/history/__init__.py +0 -0
  106. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/LICENSE +0 -0
  107. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/WHEEL +0 -0
  108. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/entry_points.txt +0 -0
@@ -1,18 +1,18 @@
1
1
  import json
2
2
  import logging
3
3
  import time
4
+ from collections.abc import Generator
4
5
  from contextlib import contextmanager
5
6
  from pathlib import Path
6
7
  from threading import Lock
7
8
  from typing import Any
8
- from typing import Generator
9
9
  from typing import Literal
10
- from typing import Optional
11
10
 
12
11
  import paramiko.sftp_client
13
12
  from fabric import Connection
14
13
  from invoke import UnexpectedExit
15
14
  from paramiko.ssh_exception import NoValidConnectionsError
15
+ from pydantic import BaseModel
16
16
 
17
17
  from ..logger import get_logger
18
18
  from ..logger import set_logger
@@ -35,6 +35,12 @@ class FractalSSHUnknownError(RuntimeError):
35
35
  pass
36
36
 
37
37
 
38
+ class SSHConfig(BaseModel):
39
+ host: str
40
+ user: str
41
+ key_path: str
42
+
43
+
38
44
  logger = set_logger(__name__)
39
45
 
40
46
 
@@ -75,7 +81,7 @@ def _acquire_lock_with_timeout(
75
81
  logger.info(f"Lock for '{label}' was released.")
76
82
 
77
83
 
78
- class FractalSSH(object):
84
+ class FractalSSH:
79
85
  """
80
86
  Wrapper of `fabric.Connection` object, enriched with locks.
81
87
 
@@ -159,7 +165,7 @@ class FractalSSH(object):
159
165
  raise e
160
166
 
161
167
  def _run(
162
- self, *args, label: str, lock_timeout: Optional[float] = None, **kwargs
168
+ self, *args, label: str, lock_timeout: float | None = None, **kwargs
163
169
  ) -> Any:
164
170
  actual_lock_timeout = self.default_lock_timeout
165
171
  if lock_timeout is not None:
@@ -275,10 +281,10 @@ class FractalSSH(object):
275
281
  self,
276
282
  *,
277
283
  cmd: str,
278
- allow_char: Optional[str] = None,
279
- max_attempts: Optional[int] = None,
280
- base_interval: Optional[float] = None,
281
- lock_timeout: Optional[int] = None,
284
+ allow_char: str | None = None,
285
+ max_attempts: int | None = None,
286
+ base_interval: float | None = None,
287
+ lock_timeout: int | None = None,
282
288
  ) -> str:
283
289
  """
284
290
  Run a command within an open SSH connection.
@@ -375,7 +381,7 @@ class FractalSSH(object):
375
381
  *,
376
382
  local: str,
377
383
  remote: str,
378
- lock_timeout: Optional[float] = None,
384
+ lock_timeout: float | None = None,
379
385
  ) -> None:
380
386
  """
381
387
  Transfer a file via SSH
@@ -415,7 +421,7 @@ class FractalSSH(object):
415
421
  *,
416
422
  local: str,
417
423
  remote: str,
418
- lock_timeout: Optional[float] = None,
424
+ lock_timeout: float | None = None,
419
425
  ) -> None:
420
426
  """
421
427
  Transfer a file via SSH
@@ -506,7 +512,7 @@ class FractalSSH(object):
506
512
  *,
507
513
  path: str,
508
514
  content: str,
509
- lock_timeout: Optional[float] = None,
515
+ lock_timeout: float | None = None,
510
516
  ) -> None:
511
517
  """
512
518
  Open a remote file via SFTP and write it.
@@ -560,7 +566,7 @@ class FractalSSH(object):
560
566
  )
561
567
 
562
568
 
563
- class FractalSSHList(object):
569
+ class FractalSSHList:
564
570
  """
565
571
  Collection of `FractalSSH` objects
566
572
 
@@ -714,3 +720,22 @@ class FractalSSHList(object):
714
720
  f"({fractal_ssh_obj.is_connected=})."
715
721
  )
716
722
  fractal_ssh_obj.close()
723
+
724
+
725
+ @contextmanager
726
+ def SingleUseFractalSSH(
727
+ *,
728
+ ssh_config: SSHConfig,
729
+ logger_name: str,
730
+ ) -> Generator[FractalSSH, Any, None]:
731
+ """
732
+ Get a new FractalSSH object (with a fresh connection).
733
+
734
+ Args:
735
+ ssh_config:
736
+ logger_name:
737
+ """
738
+ _fractal_ssh_list = FractalSSHList(logger_name=logger_name)
739
+ _fractal_ssh = _fractal_ssh_list.get(**ssh_config.model_dump())
740
+ yield _fractal_ssh
741
+ _fractal_ssh.close()
@@ -1,5 +1,5 @@
1
1
  import string
2
- from typing import Optional
2
+
3
3
 
4
4
  __SPECIAL_CHARACTERS__ = f"{string.punctuation}{string.whitespace}"
5
5
 
@@ -36,7 +36,7 @@ def sanitize_string(value: str) -> str:
36
36
  def validate_cmd(
37
37
  command: str,
38
38
  *,
39
- allow_char: Optional[str] = None,
39
+ allow_char: str | None = None,
40
40
  attribute_name: str = "Command",
41
41
  ):
42
42
  """
fractal_server/syringe.py CHANGED
@@ -34,8 +34,8 @@ or popped from the directory.
34
34
  >>> bar()
35
35
  42
36
36
  """
37
+ from collections.abc import Callable
37
38
  from typing import Any
38
- from typing import Callable
39
39
  from typing import TypeVar
40
40
 
41
41
 
@@ -4,7 +4,6 @@ import shutil
4
4
  import time
5
5
  from pathlib import Path
6
6
  from tempfile import TemporaryDirectory
7
- from typing import Optional
8
7
 
9
8
  from ..utils_database import create_db_tasks_and_update_task_group_sync
10
9
  from ._utils import _customize_and_run_template
@@ -39,7 +38,7 @@ def collect_local(
39
38
  *,
40
39
  task_group_activity_id: int,
41
40
  task_group_id: int,
42
- wheel_file: Optional[WheelFile] = None,
41
+ wheel_file: WheelFile | None = None,
43
42
  ) -> None:
44
43
  """
45
44
  Collect a task package.
@@ -132,7 +131,7 @@ def collect_local(
132
131
  ).as_posix(),
133
132
  prefix=(
134
133
  f"{int(time.time())}_"
135
- f"{TaskGroupActivityActionV2.COLLECT.value}_"
134
+ f"{TaskGroupActivityActionV2.COLLECT}_"
136
135
  ),
137
136
  logger_name=LOGGER_NAME,
138
137
  )
@@ -107,7 +107,7 @@ def deactivate_local(
107
107
  ).as_posix(),
108
108
  prefix=(
109
109
  f"{int(time.time())}_"
110
- f"{TaskGroupActivityActionV2.DEACTIVATE.value}_"
110
+ f"{TaskGroupActivityActionV2.DEACTIVATE}_"
111
111
  ),
112
112
  logger_name=LOGGER_NAME,
113
113
  )
@@ -107,7 +107,7 @@ def reactivate_local(
107
107
  ).as_posix(),
108
108
  prefix=(
109
109
  f"{int(time.time())}_"
110
- f"{TaskGroupActivityActionV2.REACTIVATE.value}_"
110
+ f"{TaskGroupActivityActionV2.REACTIVATE}_"
111
111
  ),
112
112
  logger_name=LOGGER_NAME,
113
113
  )