fractal-server 2.13.1__py3-none-any.whl → 2.14.0a1__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 (60) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/app/history/__init__.py +4 -0
  3. fractal_server/app/history/image_updates.py +142 -0
  4. fractal_server/app/history/status_enum.py +16 -0
  5. fractal_server/app/models/v2/__init__.py +5 -1
  6. fractal_server/app/models/v2/history.py +53 -0
  7. fractal_server/app/routes/api/v2/__init__.py +2 -2
  8. fractal_server/app/routes/api/v2/_aux_functions.py +78 -0
  9. fractal_server/app/routes/api/v2/dataset.py +12 -9
  10. fractal_server/app/routes/api/v2/history.py +247 -0
  11. fractal_server/app/routes/api/v2/project.py +25 -0
  12. fractal_server/app/routes/api/v2/workflow.py +18 -3
  13. fractal_server/app/routes/api/v2/workflowtask.py +22 -0
  14. fractal_server/app/runner/executors/base_runner.py +114 -0
  15. fractal_server/app/runner/{v2/_local → executors/local}/_local_config.py +3 -3
  16. fractal_server/app/runner/executors/local/_submit_setup.py +54 -0
  17. fractal_server/app/runner/executors/local/runner.py +200 -0
  18. fractal_server/app/runner/executors/{slurm → slurm_common}/_batching.py +1 -1
  19. fractal_server/app/runner/executors/{slurm → slurm_common}/_slurm_config.py +3 -3
  20. fractal_server/app/runner/{v2/_slurm_ssh → executors/slurm_common}/_submit_setup.py +13 -12
  21. fractal_server/app/runner/{v2/_slurm_common → executors/slurm_common}/get_slurm_config.py +9 -15
  22. fractal_server/app/runner/executors/{slurm/ssh → slurm_ssh}/_executor_wait_thread.py +1 -1
  23. fractal_server/app/runner/executors/{slurm/ssh → slurm_ssh}/_slurm_job.py +1 -1
  24. fractal_server/app/runner/executors/{slurm/ssh → slurm_ssh}/executor.py +13 -14
  25. fractal_server/app/runner/executors/{slurm/sudo → slurm_sudo}/_check_jobs_status.py +11 -9
  26. fractal_server/app/runner/executors/{slurm/sudo → slurm_sudo}/_executor_wait_thread.py +3 -3
  27. fractal_server/app/runner/executors/{slurm/sudo → slurm_sudo}/_subprocess_run_as_user.py +2 -68
  28. fractal_server/app/runner/executors/slurm_sudo/runner.py +632 -0
  29. fractal_server/app/runner/task_files.py +70 -96
  30. fractal_server/app/runner/v2/__init__.py +5 -19
  31. fractal_server/app/runner/v2/_local.py +84 -0
  32. fractal_server/app/runner/v2/{_slurm_ssh/__init__.py → _slurm_ssh.py} +10 -13
  33. fractal_server/app/runner/v2/{_slurm_sudo/__init__.py → _slurm_sudo.py} +10 -12
  34. fractal_server/app/runner/v2/runner.py +93 -28
  35. fractal_server/app/runner/v2/runner_functions.py +85 -62
  36. fractal_server/app/runner/v2/runner_functions_low_level.py +20 -20
  37. fractal_server/app/schemas/v2/dataset.py +0 -17
  38. fractal_server/app/schemas/v2/history.py +23 -0
  39. fractal_server/config.py +2 -2
  40. fractal_server/migrations/versions/8223fcef886c_image_status.py +63 -0
  41. fractal_server/migrations/versions/87cd72a537a2_add_historyitem_table.py +68 -0
  42. {fractal_server-2.13.1.dist-info → fractal_server-2.14.0a1.dist-info}/METADATA +1 -1
  43. {fractal_server-2.13.1.dist-info → fractal_server-2.14.0a1.dist-info}/RECORD +53 -47
  44. fractal_server/app/routes/api/v2/status.py +0 -168
  45. fractal_server/app/runner/executors/slurm/sudo/executor.py +0 -1281
  46. fractal_server/app/runner/v2/_local/__init__.py +0 -132
  47. fractal_server/app/runner/v2/_local/_submit_setup.py +0 -52
  48. fractal_server/app/runner/v2/_local/executor.py +0 -100
  49. fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -83
  50. fractal_server/app/runner/v2/handle_failed_job.py +0 -59
  51. /fractal_server/app/runner/executors/{slurm → local}/__init__.py +0 -0
  52. /fractal_server/app/runner/executors/{slurm/ssh → slurm_common}/__init__.py +0 -0
  53. /fractal_server/app/runner/executors/{_job_states.py → slurm_common/_job_states.py} +0 -0
  54. /fractal_server/app/runner/executors/{slurm → slurm_common}/remote.py +0 -0
  55. /fractal_server/app/runner/executors/{slurm → slurm_common}/utils_executors.py +0 -0
  56. /fractal_server/app/runner/executors/{slurm/sudo → slurm_ssh}/__init__.py +0 -0
  57. /fractal_server/app/runner/{v2/_slurm_common → executors/slurm_sudo}/__init__.py +0 -0
  58. {fractal_server-2.13.1.dist-info → fractal_server-2.14.0a1.dist-info}/LICENSE +0 -0
  59. {fractal_server-2.13.1.dist-info → fractal_server-2.14.0a1.dist-info}/WHEEL +0 -0
  60. {fractal_server-2.13.1.dist-info → fractal_server-2.14.0a1.dist-info}/entry_points.txt +0 -0
@@ -15,22 +15,21 @@ from typing import Sequence
15
15
 
16
16
  import cloudpickle
17
17
 
18
- from ....filenames import SHUTDOWN_FILENAME
19
- from ....task_files import get_task_file_paths
20
- from ....task_files import TaskFiles
21
- from ....versions import get_versions
22
- from ..._job_states import STATES_FINISHED
23
- from ...slurm._slurm_config import SlurmConfig
24
- from .._batching import heuristics
25
- from ..utils_executors import get_pickle_file_path
26
- from ..utils_executors import get_slurm_file_path
27
- from ..utils_executors import get_slurm_script_file_path
18
+ from ...filenames import SHUTDOWN_FILENAME
19
+ from ...task_files import TaskFiles
20
+ from ...versions import get_versions
21
+ from ..slurm_common._batching import heuristics
22
+ from ..slurm_common._job_states import STATES_FINISHED
23
+ from ..slurm_common._slurm_config import SlurmConfig
24
+ from ..slurm_common.utils_executors import get_pickle_file_path
25
+ from ..slurm_common.utils_executors import get_slurm_file_path
26
+ from ..slurm_common.utils_executors import get_slurm_script_file_path
28
27
  from ._executor_wait_thread import FractalSlurmSSHWaitThread
29
28
  from fractal_server.app.runner.components import _COMPONENT_KEY_
30
29
  from fractal_server.app.runner.compress_folder import compress_folder
31
30
  from fractal_server.app.runner.exceptions import JobExecutionError
32
31
  from fractal_server.app.runner.exceptions import TaskExecutionError
33
- from fractal_server.app.runner.executors.slurm.ssh._slurm_job import SlurmJob
32
+ from fractal_server.app.runner.executors.slurm_ssh._slurm_job import SlurmJob
34
33
  from fractal_server.app.runner.extract_archive import extract_archive
35
34
  from fractal_server.config import get_settings
36
35
  from fractal_server.logger import set_logger
@@ -533,9 +532,9 @@ class FractalSlurmSSHExecutor(Executor):
533
532
  except AttributeError:
534
533
  actual_component = str(component)
535
534
 
536
- _task_file_paths = get_task_file_paths(
537
- workflow_dir_local=task_files.workflow_dir_local,
538
- workflow_dir_remote=task_files.workflow_dir_remote,
535
+ _task_file_paths = TaskFiles(
536
+ root_dir_local=task_files.workflow_dir_local,
537
+ root_dir_remote=task_files.workflow_dir_remote,
539
538
  task_name=task_files.task_name,
540
539
  task_order=task_files.task_order,
541
540
  component=actual_component,
@@ -1,18 +1,20 @@
1
- from subprocess import run # nosec
1
+ import subprocess # nosec
2
2
 
3
- from ......logger import set_logger
4
- from ..._job_states import STATES_FINISHED
3
+ from fractal_server.app.runner.executors.slurm_common._job_states import (
4
+ STATES_FINISHED,
5
+ )
6
+ from fractal_server.logger import set_logger
5
7
 
6
8
 
7
9
  logger = set_logger(__name__)
8
10
 
9
11
 
10
- def run_squeue(job_ids):
11
- res = run( # nosec
12
+ def run_squeue(job_ids: list[str]) -> subprocess.CompletedProcess:
13
+ res = subprocess.run( # nosec
12
14
  [
13
15
  "squeue",
14
16
  "--noheader",
15
- "--format=%i %T",
17
+ "--format='%i %T'",
16
18
  "--jobs",
17
19
  ",".join([str(j) for j in job_ids]),
18
20
  "--states=all",
@@ -23,14 +25,14 @@ def run_squeue(job_ids):
23
25
  )
24
26
  if res.returncode != 0:
25
27
  logger.warning(
26
- f"squeue command with {job_ids}"
27
- f" failed with:\n{res.stderr=}\n{res.stdout=}"
28
+ f"squeue command with {job_ids} failed with:"
29
+ f"\n{res.stderr=}\n{res.stdout=}"
28
30
  )
29
31
 
30
32
  return res
31
33
 
32
34
 
33
- def _jobs_finished(job_ids) -> set[str]:
35
+ def get_finished_jobs(job_ids: list[str]) -> set[str]:
34
36
  """
35
37
  Check which ones of the given Slurm jobs already finished
36
38
 
@@ -5,9 +5,9 @@ import traceback
5
5
  from itertools import count
6
6
  from typing import Optional
7
7
 
8
- from ......logger import set_logger
9
- from ._check_jobs_status import _jobs_finished
8
+ from ._check_jobs_status import get_finished_jobs
10
9
  from fractal_server.app.runner.exceptions import JobExecutionError
10
+ from fractal_server.logger import set_logger
11
11
 
12
12
  logger = set_logger(__name__)
13
13
 
@@ -115,7 +115,7 @@ class FractalSlurmSudoWaitThread(threading.Thread):
115
115
  self.check_shutdown(i)
116
116
  if i % (self.slurm_poll_interval // self.interval) == 0:
117
117
  try:
118
- finished_jobs = _jobs_finished(self.waiting.values())
118
+ finished_jobs = get_finished_jobs(self.waiting.values())
119
119
  except Exception:
120
120
  # Don't abandon completion checking if jobs_finished errors
121
121
  traceback.print_exc()
@@ -19,7 +19,7 @@ import shlex
19
19
  import subprocess # nosec
20
20
  from typing import Optional
21
21
 
22
- from ......logger import set_logger
22
+ from fractal_server.logger import set_logger
23
23
  from fractal_server.string_tools import validate_cmd
24
24
 
25
25
  logger = set_logger(__name__)
@@ -65,10 +65,7 @@ def _run_command_as_user(
65
65
 
66
66
  if check and not res.returncode == 0:
67
67
  raise RuntimeError(
68
- f"{cmd=}\n\n"
69
- f"{res.returncode=}\n\n"
70
- f"{res.stdout=}\n\n"
71
- f"{res.stderr=}\n"
68
+ f"{cmd=}\n\n{res.returncode=}\n\n{res.stdout=}\n\n{res.stderr=}\n"
72
69
  )
73
70
 
74
71
  return res
@@ -93,69 +90,6 @@ def _mkdir_as_user(*, folder: str, user: str) -> None:
93
90
  _run_command_as_user(cmd=cmd, user=user, check=True)
94
91
 
95
92
 
96
- def _glob_as_user(
97
- *, folder: str, user: str, startswith: Optional[str] = None
98
- ) -> list[str]:
99
- """
100
- Run `ls` in a folder (as a user) and filter results
101
-
102
- Execute `ls` on a folder (impersonating a user, if `user` is not `None`)
103
- and select results that start with `startswith` (if not `None`).
104
-
105
- Arguments:
106
- folder: Absolute path to the folder
107
- user: If not `None`, the user to be impersonated via `sudo -u`
108
- startswith: If not `None`, this is used to filter output of `ls`.
109
- """
110
-
111
- res = _run_command_as_user(cmd=f"ls {folder}", user=user, check=True)
112
- output = res.stdout.split()
113
- if startswith:
114
- output = [f for f in output if f.startswith(startswith)]
115
- return output
116
-
117
-
118
- def _glob_as_user_strict(
119
- *,
120
- folder: str,
121
- user: str,
122
- startswith: str,
123
- ) -> list[str]:
124
- """
125
- Run `ls` in a folder (as a user) and filter results
126
-
127
- Execute `ls` on a folder (impersonating a user, if `user` is not `None`)
128
- and select results that comply with a set of rules. They all start with
129
- `startswith` (if not `None`), and they match one of the known filename
130
- patterns. See details in
131
- https://github.com/fractal-analytics-platform/fractal-server/issues/1240
132
-
133
-
134
- Arguments:
135
- folder: Absolute path to the folder
136
- user: If not `None`, the user to be impersonated via `sudo -u`
137
- startswith: If not `None`, this is used to filter output of `ls`.
138
- """
139
-
140
- res = _run_command_as_user(cmd=f"ls {folder}", user=user, check=True)
141
- output = res.stdout.split()
142
-
143
- new_output = []
144
- known_filenames = [
145
- f"{startswith}{suffix}"
146
- for suffix in [".args.json", ".metadiff.json", ".err", ".out", ".log"]
147
- ]
148
- for filename in output:
149
- if filename in known_filenames:
150
- new_output.append(filename)
151
- elif filename.startswith(f"{startswith}_out_") and filename.endswith(
152
- ".pickle"
153
- ):
154
- new_output.append(filename)
155
-
156
- return new_output
157
-
158
-
159
93
  def _path_exists_as_user(*, path: str, user: Optional[str] = None) -> bool:
160
94
  """
161
95
  Impersonate a user and check if `path` exists via `ls`