fractal-server 2.15.5__py3-none-any.whl → 2.15.7__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.
@@ -1 +1 @@
1
- __VERSION__ = "2.15.5"
1
+ __VERSION__ = "2.15.7"
@@ -102,8 +102,9 @@ async def _verify_workflow_and_dataset_access(
102
102
  Verify user access to a dataset/workflow pair.
103
103
 
104
104
  Args:
105
+ project_id:
106
+ workflow_id:
105
107
  dataset_id:
106
- workflow_task_id:
107
108
  user_id:
108
109
  db:
109
110
  """
@@ -148,7 +149,7 @@ async def get_wftask_check_owner(
148
149
  Args:
149
150
  project_id:
150
151
  dataset_id:
151
- workflow_task_id:
152
+ workflowtask_id:
152
153
  user_id:
153
154
  db:
154
155
  """
@@ -231,11 +231,14 @@ async def _get_collection_task_group_activity_status_message(
231
231
  )
232
232
  task_group_activity_list = res.scalars().all()
233
233
  if len(task_group_activity_list) > 1:
234
- msg = (
235
- "\nWarning: "
234
+ msg_short = (
236
235
  "Expected only one TaskGroupActivityV2 associated to TaskGroup "
237
236
  f"{task_group_id}, found {len(task_group_activity_list)} "
238
237
  f"(IDs: {[tga.id for tga in task_group_activity_list]})."
238
+ )
239
+ logger.error(f"UnreachableBranchError: {msg_short}")
240
+ msg = (
241
+ f"\nWarning: {msg_short}\n"
239
242
  "Warning: this should have not happened, please contact an admin."
240
243
  )
241
244
  elif len(task_group_activity_list) == 1:
@@ -268,13 +271,16 @@ async def _verify_non_duplication_user_constraint(
268
271
  if duplicate:
269
272
  user = await db.get(UserOAuth, user_id)
270
273
  if len(duplicate) > 1:
274
+ error_msg = (
275
+ f"User '{user.email}' already owns {len(duplicate)} task "
276
+ f"groups with name='{pkg_name}' and {version=} "
277
+ f"(IDs: {[group.id for group in duplicate]})."
278
+ )
279
+ logger.error(f"UnreachableBranchError: {error_msg}")
271
280
  raise HTTPException(
272
281
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
273
282
  detail=(
274
- "Invalid state:\n"
275
- f"User '{user.email}' already owns {len(duplicate)} task "
276
- f"groups with name='{pkg_name}' and {version=} "
277
- f"(IDs: {[group.id for group in duplicate]}).\n"
283
+ f"Invalid state: {error_msg}\n"
278
284
  "This should have not happened: please contact an admin."
279
285
  ),
280
286
  )
@@ -310,13 +316,16 @@ async def _verify_non_duplication_group_constraint(
310
316
  if duplicate:
311
317
  user_group = await db.get(UserGroup, user_group_id)
312
318
  if len(duplicate) > 1:
319
+ error_msg = (
320
+ f"UserGroup '{user_group.name}' already owns "
321
+ f"{len(duplicate)} task groups with name='{pkg_name}' and "
322
+ f"{version=} (IDs: {[group.id for group in duplicate]}).\n"
323
+ )
324
+ logger.error(error_msg)
313
325
  raise HTTPException(
314
326
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
315
327
  detail=(
316
- "Invalid state:\n"
317
- f"UserGroup '{user_group.name}' already owns "
318
- f"{len(duplicate)} task groups with name='{pkg_name}' and "
319
- f"{version=} (IDs: {[group.id for group in duplicate]}).\n"
328
+ f"Invalid state:\n{error_msg}"
320
329
  "This should have not happened: please contact an admin."
321
330
  ),
322
331
  )
@@ -1,6 +1,3 @@
1
- import os
2
-
3
-
4
1
  class TaskExecutionError(RuntimeError):
5
2
  """
6
3
  Forwards errors occurred during the execution of a task
@@ -42,86 +39,27 @@ class TaskOutputValidationError(ValueError):
42
39
 
43
40
  class JobExecutionError(RuntimeError):
44
41
  """
45
- Forwards errors in the execution of a task that are due to external factors
46
-
47
- This error wraps and forwards errors occurred during the execution of
48
- tasks, but related to external factors like an error on the executor side.
49
-
50
- This error also adds information that is useful to track down and debug the
51
- failing task within a workflow.
42
+ JobExecutionError
52
43
 
53
44
  Attributes:
54
45
  info:
55
46
  A free field for additional information
56
- cmd_file:
57
- Path to the file of the command that was executed (e.g. a SLURM
58
- submission script).
59
- stdout_file:
60
- Path to the file with the command stdout
61
- stderr_file:
62
- Path to the file with the command stderr
63
47
  """
64
48
 
65
- cmd_file: str | None = None
66
- stdout_file: str | None = None
67
- stderr_file: str | None = None
68
49
  info: str | None = None
69
50
 
70
51
  def __init__(
71
52
  self,
72
53
  *args,
73
- cmd_file: str | None = None,
74
- stdout_file: str | None = None,
75
- stderr_file: str | None = None,
76
54
  info: str | None = None,
77
55
  ):
78
56
  super().__init__(*args)
79
- self.cmd_file = cmd_file
80
- self.stdout_file = stdout_file
81
- self.stderr_file = stderr_file
82
57
  self.info = info
83
58
 
84
- def _read_file(self, filepath: str) -> str:
85
- """
86
- Return the content of a text file, and handle the cases where it is
87
- empty or missing
88
- """
89
- if os.path.exists(filepath):
90
- with open(filepath) as f:
91
- content = f.read()
92
- if content:
93
- return f"Content of {filepath}:\n{content}"
94
- else:
95
- return f"File {filepath} is empty\n"
96
- else:
97
- return f"File {filepath} is missing\n"
98
-
99
59
  def assemble_error(self) -> str:
100
- """
101
- Read the files that are specified in attributes, and combine them in an
102
- error message.
103
- """
104
- if self.cmd_file:
105
- content = self._read_file(self.cmd_file)
106
- cmd_content = f"COMMAND:\n{content}\n\n"
107
- else:
108
- cmd_content = ""
109
- if self.stdout_file:
110
- content = self._read_file(self.stdout_file)
111
- out_content = f"STDOUT:\n{content}\n\n"
112
- else:
113
- out_content = ""
114
- if self.stderr_file:
115
- content = self._read_file(self.stderr_file)
116
- err_content = f"STDERR:\n{content}\n\n"
117
- else:
118
- err_content = ""
119
-
120
- content = f"{cmd_content}{out_content}{err_content}"
121
60
  if self.info:
122
- content = f"{content}ADDITIONAL INFO:\n{self.info}\n\n"
123
-
124
- if not content:
61
+ content = f"\n{self.info}\n\n"
62
+ else:
125
63
  content = str(self)
126
- message = f"JobExecutionError\n\n{content}"
64
+ message = f"JobExecutionError\n{content}"
127
65
  return message
@@ -91,14 +91,15 @@ class BaseRunner:
91
91
  workflow_task_order:
92
92
  workflow_task_id:
93
93
  task_name:
94
- parameters:
95
- Dictionary of parameters. Must include `zarr_urls` key.
94
+ list_parameters:
95
+ List of dictionaries of parameters (each one must include
96
+ `zarr_urls` key).
96
97
  history_unit_ids:
97
98
  Database IDs of the corresponding `HistoryUnit` entries.
99
+ list_task_files: `TaskFiles` objects.
98
100
  task_type: Task type.
99
- task_files: `TaskFiles` object.
100
101
  config: Runner-specific parameters.
101
- user_id
102
+ user_id:
102
103
  """
103
104
  raise NotImplementedError()
104
105
 
@@ -213,7 +213,7 @@ class SlurmConfig(BaseModel):
213
213
  `SlurmConfig` attributes (e.g. `mem_per_task_MB`), which are not meant to
214
214
  be part of the `FRACTAL_SLURM_CONFIG_FILE` JSON file (details on the
215
215
  expected file content are defined in
216
- [`SlurmConfigFile`](./#fractal_server.app.runner._slurm._slurm_config.SlurmConfigFile)).
216
+ [`SlurmConfigFile`](#fractal_server.app.runner._slurm._slurm_config.SlurmConfigFile)).
217
217
 
218
218
  Part of the attributes map directly to some of the SLURM attributes (see
219
219
  https://slurm.schedmd.com/sbatch.html), e.g. `partition`. Other attributes
@@ -8,6 +8,7 @@ from ._slurm_config import logger
8
8
  from ._slurm_config import SlurmConfig
9
9
  from ._slurm_config import SlurmConfigError
10
10
  from fractal_server.app.models.v2 import WorkflowTaskV2
11
+ from fractal_server.string_tools import interpret_as_bool
11
12
 
12
13
 
13
14
  def get_slurm_config_internal(
@@ -86,7 +87,7 @@ def get_slurm_config_internal(
86
87
  # 2. This block of definitions has lower priority than whatever comes next
87
88
  # (i.e. from WorkflowTask.meta_parallel).
88
89
  if wftask_meta is not None:
89
- needs_gpu = wftask_meta.get("needs_gpu", False)
90
+ needs_gpu = interpret_as_bool(wftask_meta.get("needs_gpu", False))
90
91
  else:
91
92
  needs_gpu = False
92
93
  logger.debug(f"[get_slurm_config] {needs_gpu=}")
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
  def get_tar_compression_cmd(
8
8
  subfolder_path: Path,
9
9
  filelist_path: Path | None,
10
- ) -> tuple[str, str]:
10
+ ) -> str:
11
11
  """
12
12
  Prepare command to compress e.g. `/path/dir` into `/path/dir.tar.gz`.
13
13
 
@@ -17,7 +17,6 @@ def get_tar_compression_cmd(
17
17
  Args:
18
18
  subfolder_path: Absolute path to the folder to compress.
19
19
  filelist_path: If set, to be used in the `--files-from` option.
20
- expected_tarfile: If set, it should match to the returned one.
21
20
 
22
21
  Returns:
23
22
  tar command
@@ -32,6 +32,7 @@ from fractal_server.app.runner.v2.task_interface import (
32
32
  )
33
33
  from fractal_server.app.schemas.v2 import HistoryUnitStatus
34
34
  from fractal_server.app.schemas.v2 import TaskType
35
+ from fractal_server.exceptions import UnreachableBranchError
35
36
  from fractal_server.logger import set_logger
36
37
 
37
38
  __all__ = [
@@ -349,11 +350,11 @@ def run_v2_task_parallel(
349
350
  for ind in range(len(list_function_kwargs)):
350
351
  if ind not in results.keys() and ind not in exceptions.keys():
351
352
  error_msg = (
352
- f"Invalid branch: {ind=} is not in `results.keys()` "
353
+ f"UnreachableBranchError: {ind=} is not in `results.keys()` "
353
354
  "nor in `exceptions.keys()`."
354
355
  )
355
356
  logger.error(error_msg)
356
- raise RuntimeError(error_msg)
357
+ raise UnreachableBranchError(error_msg)
357
358
  outcome[ind] = _process_task_output(
358
359
  result=results.get(ind, None),
359
360
  exception=exceptions.get(ind, None),
@@ -567,13 +568,12 @@ def run_v2_task_compound(
567
568
  failure = False
568
569
  for ind in range(len(list_function_kwargs)):
569
570
  if ind not in results.keys() and ind not in exceptions.keys():
570
- # NOTE: see issue 2484
571
571
  error_msg = (
572
- f"Invalid branch: {ind=} is not in `results.keys()` "
572
+ f"UnreachableBranchError: {ind=} is not in `results.keys()` "
573
573
  "nor in `exceptions.keys()`."
574
574
  )
575
575
  logger.error(error_msg)
576
- raise RuntimeError(error_msg)
576
+ raise UnreachableBranchError(error_msg)
577
577
  compute_outcomes[ind] = _process_task_output(
578
578
  result=results.get(ind, None),
579
579
  exception=exceptions.get(ind, None),
@@ -25,7 +25,6 @@ from ...models.v2 import JobV2
25
25
  from ...models.v2 import WorkflowV2
26
26
  from ...schemas.v2 import JobStatusTypeV2
27
27
  from ..exceptions import JobExecutionError
28
- from ..exceptions import TaskExecutionError
29
28
  from ..filenames import WORKFLOW_LOG_FILENAME
30
29
  from ._local import process_workflow as local_process_workflow
31
30
  from ._slurm_ssh import process_workflow as slurm_ssh_process_workflow
@@ -311,19 +310,6 @@ def submit_workflow(
311
310
  db_sync.merge(job)
312
311
  db_sync.commit()
313
312
 
314
- except TaskExecutionError as e:
315
- logger.debug(f'FAILED workflow "{workflow.name}", TaskExecutionError.')
316
- logger.info(f'Workflow "{workflow.name}" failed (TaskExecutionError).')
317
-
318
- exception_args_string = "\n".join(e.args)
319
- log_msg = (
320
- f"TASK ERROR: "
321
- f"Task name: {e.task_name}, "
322
- f"position in Workflow: {e.workflow_task_order}\n"
323
- f"TRACEBACK:\n{exception_args_string}"
324
- )
325
- fail_job(db=db_sync, job=job, log_msg=log_msg, logger_name=logger_name)
326
-
327
313
  except JobExecutionError as e:
328
314
  logger.debug(f'FAILED workflow "{workflow.name}", JobExecutionError.')
329
315
  logger.info(f'Workflow "{workflow.name}" failed (JobExecutionError).')
@@ -49,7 +49,9 @@ class TaskCollectPipV2(BaseModel):
49
49
  package: NonEmptyStr | None = None
50
50
  package_version: NonEmptyStr | None = None
51
51
  package_extras: NonEmptyStr | None = None
52
- python_version: Literal["3.9", "3.10", "3.11", "3.12"] | None = None
52
+ python_version: Literal[
53
+ "3.9", "3.10", "3.11", "3.12", "3.13"
54
+ ] | None = None
53
55
  pinned_package_versions: DictStrStr | None = None
54
56
 
55
57
  @field_validator(
fractal_server/config.py CHANGED
@@ -405,7 +405,7 @@ class Settings(BaseSettings):
405
405
  """
406
406
 
407
407
  FRACTAL_TASKS_PYTHON_DEFAULT_VERSION: None | (
408
- Literal["3.9", "3.10", "3.11", "3.12"]
408
+ Literal["3.9", "3.10", "3.11", "3.12", "3.13"]
409
409
  ) = None
410
410
  """
411
411
  Default Python version to be used for task collection. Defaults to the
@@ -437,6 +437,11 @@ class Settings(BaseSettings):
437
437
  Same as `FRACTAL_TASKS_PYTHON_3_9`, for Python 3.12.
438
438
  """
439
439
 
440
+ FRACTAL_TASKS_PYTHON_3_13: str | None = None
441
+ """
442
+ Same as `FRACTAL_TASKS_PYTHON_3_9`, for Python 3.13.
443
+ """
444
+
440
445
  @model_validator(mode="before")
441
446
  @classmethod
442
447
  def check_tasks_python(cls, values):
@@ -450,7 +455,7 @@ class Settings(BaseSettings):
450
455
  `FRACTAL_TASKS_PYTHON_X_Y` (and unset all others).
451
456
  """
452
457
  # `FRACTAL_TASKS_PYTHON_X_Y` variables can only be absolute paths
453
- for version in ["3_9", "3_10", "3_11", "3_12"]:
458
+ for version in ["3_9", "3_10", "3_11", "3_12", "3_13"]:
454
459
  key = f"FRACTAL_TASKS_PYTHON_{version}"
455
460
  value = values.get(key)
456
461
  if value is not None and not Path(value).is_absolute():
@@ -490,7 +495,7 @@ class Settings(BaseSettings):
490
495
  )
491
496
 
492
497
  # Unset all existing interpreters variable
493
- for _version in ["3_9", "3_10", "3_11", "3_12"]:
498
+ for _version in ["3_9", "3_10", "3_11", "3_12", "3_13"]:
494
499
  key = f"FRACTAL_TASKS_PYTHON_{_version}"
495
500
  if _version == current_version:
496
501
  values[key] = sys.executable
@@ -60,3 +60,26 @@ def validate_cmd(
60
60
  f"'{forbidden}'\n"
61
61
  f"Provided {attribute_name.lower()}: '{command}'."
62
62
  )
63
+
64
+
65
+ def interpret_as_bool(value: bool | str) -> bool:
66
+ """
67
+ Interpret a boolean or a string representation of a boolean as a boolean
68
+ value.
69
+
70
+ Accepts either a boolean (`True` or `False`) or a case-insensitive string
71
+ representation of a boolean ("true" or "false").
72
+ Returns the corresponding boolean value.
73
+ """
74
+ if isinstance(value, bool):
75
+ return value
76
+ elif isinstance(value, str):
77
+ value_lower = value.lower()
78
+ if value_lower == "true":
79
+ return True
80
+ elif value_lower == "false":
81
+ return False
82
+ else:
83
+ raise ValueError("String must be 'true' or 'false'.")
84
+ else:
85
+ raise TypeError(f"Expected bool or str, got {type(value)}: '{value}'.")
@@ -26,6 +26,7 @@ def _customize_and_run_template(
26
26
  fractal_ssh: FractalSSH,
27
27
  script_dir_remote: str,
28
28
  logger_name: str,
29
+ login_shell: bool = False,
29
30
  ) -> str:
30
31
  """
31
32
  Customize one of the template bash scripts, transfer it to the remote host
@@ -38,6 +39,7 @@ def _customize_and_run_template(
38
39
  prefix: Prefix for the script filename.
39
40
  fractal_ssh: FractalSSH object
40
41
  script_dir_remote: Remote scripts directory
42
+ login_shell: If `True`, use `bash --login` for remote script execution.
41
43
  """
42
44
  logger = get_logger(logger_name=logger_name)
43
45
  logger.debug(f"_customize_and_run_template {template_filename} - START")
@@ -67,7 +69,8 @@ def _customize_and_run_template(
67
69
  )
68
70
 
69
71
  # Execute script remotely
70
- cmd = f"bash {script_path_remote}"
72
+ bash = "bash --login" if login_shell else "bash"
73
+ cmd = f"{bash} {script_path_remote}"
71
74
  logger.debug(f"Now run '{cmd}' over SSH.")
72
75
  stdout = fractal_ssh.run_command(cmd=cmd)
73
76
 
@@ -204,6 +204,7 @@ def collect_ssh_pixi(
204
204
  stdout = _customize_and_run_template(
205
205
  template_filename="pixi_2_install.sh",
206
206
  replacements=replacements,
207
+ login_shell=True,
207
208
  **common_args,
208
209
  )
209
210
  logger.debug(f"STDOUT: {stdout}")
@@ -190,6 +190,7 @@ def reactivate_ssh_pixi(
190
190
  stdout = _customize_and_run_template(
191
191
  template_filename="pixi_2_install.sh",
192
192
  replacements=replacements,
193
+ login_shell=True,
193
194
  **common_args,
194
195
  )
195
196
  logger.debug(f"STDOUT: {stdout}")
@@ -56,8 +56,8 @@ def simplify_pyproject_toml(
56
56
 
57
57
  Args:
58
58
  original_toml_string: Original `pyproject.toml` contents
59
- environment: Name of the pixi environment to use (e.g. `default`).
60
- target_platform: Name of the platform (e.g. `linux-64`)
59
+ pixi_environment: Name of the pixi environment to use (e.g. `default`).
60
+ pixi_platform: Name of the platform (e.g. `linux-64`)
61
61
 
62
62
  Returns:
63
63
  New `pyproject.toml` contents
@@ -78,6 +78,10 @@ def simplify_pyproject_toml(
78
78
  pixi_data["workspace"]["platforms"] = [pixi_platform]
79
79
  except KeyError:
80
80
  logger.info("KeyError for workspace/platforms - skip.")
81
+ try:
82
+ pixi_data["project"]["platforms"] = [pixi_platform]
83
+ except KeyError:
84
+ logger.info("KeyError for project/platforms - skip.")
81
85
 
82
86
  # Keep a single environment (or skip, if not set)
83
87
  try:
@@ -21,7 +21,7 @@ def get_python_interpreter_v2(
21
21
  interpreter: string representing the python executable or its path
22
22
  """
23
23
 
24
- if python_version not in ["3.9", "3.10", "3.11", "3.12"]:
24
+ if python_version not in ["3.9", "3.10", "3.11", "3.12", "3.13"]:
25
25
  raise ValueError(f"Invalid {python_version=}.")
26
26
 
27
27
  settings = Inject(get_settings)
@@ -1,19 +1,20 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fractal-server
3
- Version: 2.15.5
3
+ Version: 2.15.7
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License: BSD-3-Clause
6
6
  Author: Tommaso Comparin
7
7
  Author-email: tommaso.comparin@exact-lab.it
8
- Requires-Python: >=3.11,<3.13
8
+ Requires-Python: >=3.11,<3.14
9
9
  Classifier: License :: OSI Approved :: BSD License
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
13
14
  Requires-Dist: alembic (>=1.13.1,<2.0.0)
14
15
  Requires-Dist: cryptography (>=45.0.3,<45.1.0)
15
16
  Requires-Dist: fabric (>=3.2.2,<3.3.0)
16
- Requires-Dist: fastapi (>=0.115.0,<0.116.0)
17
+ Requires-Dist: fastapi (>=0.116.0,<0.117.0)
17
18
  Requires-Dist: fastapi-users[oauth] (>=14,<15)
18
19
  Requires-Dist: gunicorn (>=23.0,<24.0)
19
20
  Requires-Dist: packaging (>=25.0.0,<26.0.0)
@@ -1,4 +1,4 @@
1
- fractal_server/__init__.py,sha256=ov_g1jTxonHhycaNsA6l6SCH-LJTAVhUlTjOOgQa4Tc,23
1
+ fractal_server/__init__.py,sha256=SIpD8yvbZydQsQo0H2fClLPf0pyYpjeHjRBmNRTNLKk,23
2
2
  fractal_server/__main__.py,sha256=rkM8xjY1KeS3l63irB8yCrlVobR-73uDapC4wvrIlxI,6957
3
3
  fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
4
4
  fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -31,10 +31,10 @@ fractal_server/app/routes/admin/v2/task_group_lifecycle.py,sha256=2J3M9VXWD_0j9j
31
31
  fractal_server/app/routes/api/__init__.py,sha256=B8l6PSAhR10iZqHEiyTat-_0tkeKdrCigIE6DJGP5b8,638
32
32
  fractal_server/app/routes/api/v2/__init__.py,sha256=D3sRRsqkmZO6kBxUjg40q0aRDsnuXI4sOOfn0xF9JsM,2820
33
33
  fractal_server/app/routes/api/v2/_aux_functions.py,sha256=tfnxqbufKqd5dbFUzOFlRPc9EgURhpNa5V2V4agzndg,14259
34
- fractal_server/app/routes/api/v2/_aux_functions_history.py,sha256=Z23xwvBaVEEQ5B-JsWZJpjj4_QqoXqHYONztnbAH6gw,4425
34
+ fractal_server/app/routes/api/v2/_aux_functions_history.py,sha256=ykTyiY3H-nGSgGfcVkb2xQqJd65YOY2aWVK9sfqTdIY,4439
35
35
  fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py,sha256=GpKfw9yj01LmOAuNMTOreU1PFkCKpjK5oCt7_wp35-A,6741
36
36
  fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py,sha256=WLDOYCnb6fnS5avKflyx6yN24Vo1n5kJk5ZyiKbzb8Y,1175
37
- fractal_server/app/routes/api/v2/_aux_functions_tasks.py,sha256=-KTPouwPQga5SGe2n0diWm-Fev31DPAfXKMo6PijBSI,12207
37
+ fractal_server/app/routes/api/v2/_aux_functions_tasks.py,sha256=sjlhv6LliDvhttVTjC2xhIFO-Vj3roE3bEv7_TZ1h0A,12494
38
38
  fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py,sha256=8x1_q9FyCzItnPmdSdLQuwUTy4B9xCsXscp97_lJcpM,4635
39
39
  fractal_server/app/routes/api/v2/dataset.py,sha256=6u4MFqJ3YZ0Zq6Xx8CRMrTPKW55ZaR63Uno21DqFr4Q,8889
40
40
  fractal_server/app/routes/api/v2/history.py,sha256=03QPe08pyy-NWEe21NVKprsLgqxljQO4gMZ8plt9wys,17112
@@ -70,9 +70,9 @@ fractal_server/app/routes/aux/validate_user_settings.py,sha256=FLVi__8YFcm_6c_K5
70
70
  fractal_server/app/routes/pagination.py,sha256=IGy8Ll5lYr6ENYE18h3huH5s0GMX1DCs5VdCi6j1cdk,1174
71
71
  fractal_server/app/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  fractal_server/app/runner/components.py,sha256=-Ii5l8d_V6f5DFOd-Zsr8VYmOsyqw0Hox9fEFQiuqxY,66
73
- fractal_server/app/runner/exceptions.py,sha256=tJxs7WCQ86kjezunFm4o_VAiUAyD70l3GiH6ht0waWA,3958
73
+ fractal_server/app/runner/exceptions.py,sha256=lzYefT6IpA2ajcQUzm9kT9pTxRl5UGIJKyLs6v1JczA,1731
74
74
  fractal_server/app/runner/executors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
- fractal_server/app/runner/executors/base_runner.py,sha256=7ujN6gN92X9sWAlDwkc07G3FA4Z_Zwew_uBYh2qv0uI,5978
75
+ fractal_server/app/runner/executors/base_runner.py,sha256=5Y0VACW3YZtXwLH-ll963miWWYsNJ1ZD0V2S5-N8vGI,6026
76
76
  fractal_server/app/runner/executors/call_command_wrapper.py,sha256=1BHl-zbXoX2oGUWGAFprVZMmg5QjutPH0-VZJSIC0II,1419
77
77
  fractal_server/app/runner/executors/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
78
  fractal_server/app/runner/executors/local/get_local_config.py,sha256=KBYOkcuwpSYl-ZIAwPBxpn59QSyFF8eJ-fLKVIhwwzA,3594
@@ -80,15 +80,15 @@ fractal_server/app/runner/executors/local/runner.py,sha256=syJcUYkdKeGYbD33VzuX9
80
80
  fractal_server/app/runner/executors/slurm_common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
81
  fractal_server/app/runner/executors/slurm_common/_batching.py,sha256=gbHZIxt90GjUwhB9_UInwVqpX-KdxRQMDeXzUagdL3U,8816
82
82
  fractal_server/app/runner/executors/slurm_common/_job_states.py,sha256=nuV-Zba38kDrRESOVB3gaGbrSPZc4q7YGichQaeqTW0,238
83
- fractal_server/app/runner/executors/slurm_common/_slurm_config.py,sha256=U9BONnnwn8eDqDevwUtFSBcvIsxvNgDHirhcQGJ9t9E,15947
83
+ fractal_server/app/runner/executors/slurm_common/_slurm_config.py,sha256=7L80pH2lOe6qAH-8VzmcUOMgA9KJoQLTPDpkonKwhH8,15945
84
84
  fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py,sha256=1Sh56lb7NERVtsBMvVs4K7nVHhMy_KDbwquPl1ub8vE,37937
85
- fractal_server/app/runner/executors/slurm_common/get_slurm_config.py,sha256=jhoFHauWJm55bIC_v7pFylbK8WgcRJemGu2OjUiRbpQ,7377
85
+ fractal_server/app/runner/executors/slurm_common/get_slurm_config.py,sha256=KhQQJrGQZLX5u8fsMcIx7FN8jUKSGEeG68yO7Ay_LXg,7454
86
86
  fractal_server/app/runner/executors/slurm_common/remote.py,sha256=LHK2Ram8X8q6jNSCxnnwKUwmSJMsyQyRem_VjH53qdw,3811
87
87
  fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py,sha256=K4SdJOKsUWzDlnkb8Ug_UmTx6nBMsTqn9_oKqwE4XDI,3520
88
88
  fractal_server/app/runner/executors/slurm_ssh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
89
  fractal_server/app/runner/executors/slurm_ssh/run_subprocess.py,sha256=SyW6t4egvbiARph2YkFjc88Hj94fCamZVi50L7ph8VM,996
90
90
  fractal_server/app/runner/executors/slurm_ssh/runner.py,sha256=Hzq01rLgOEzS6UPMzW59d4Ox-wwHlxyPF1KiKcGQvIM,7993
91
- fractal_server/app/runner/executors/slurm_ssh/tar_commands.py,sha256=g173siyv7qtjov5i-CjTVRT8d19ibK8re3RVWbsdHYA,1845
91
+ fractal_server/app/runner/executors/slurm_ssh/tar_commands.py,sha256=yqBjWTLmh_FzhCllt_KfbuCUGvRhsHLVWlPOZlRWLzY,1762
92
92
  fractal_server/app/runner/executors/slurm_sudo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
93
  fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py,sha256=W-FxnVcHxMGpv4zGgJVttVQoweyGgR4uBxO22QIZkp0,2576
94
94
  fractal_server/app/runner/executors/slurm_sudo/runner.py,sha256=TGH6B1eRHgHjYjqN86F1V-WNAB_kp-nPo5TJ0FHwigY,5859
@@ -104,8 +104,8 @@ fractal_server/app/runner/v2/db_tools.py,sha256=ozp4RFLB3LNI0rM0q0udi6ja8-5vooH_
104
104
  fractal_server/app/runner/v2/deduplicate_list.py,sha256=IVTE4abBU1bUprFTkxrTfYKnvkNTanWQ-KWh_etiT08,645
105
105
  fractal_server/app/runner/v2/merge_outputs.py,sha256=YOTKbGOM9s-uqY4KN2onoIxuHNm-v3hr5zv6Aa1KEtA,905
106
106
  fractal_server/app/runner/v2/runner.py,sha256=IsQhSxASVI-yPBO2G2uuVvZkRIoAlSY6Ev7gcSYmDOw,18989
107
- fractal_server/app/runner/v2/runner_functions.py,sha256=aEwEDzI2l-QvgfJSj-M2LGvqA89nOiJYIFVryKEq_3M,18988
108
- fractal_server/app/runner/v2/submit_workflow.py,sha256=AMnXdozwIGlXD55ch0_SNAG-ntKBO-QRhkbInrvsShU,13140
107
+ fractal_server/app/runner/v2/runner_functions.py,sha256=xteoDSXKxStl3ABEXyjrggPiXdXAPy9sJPfT3B8CQ3Y,19050
108
+ fractal_server/app/runner/v2/submit_workflow.py,sha256=L6WqQC3Vm-tLe_CJXHIMbYLAeulAN2no_4HZD4cbhR0,12554
109
109
  fractal_server/app/runner/v2/task_interface.py,sha256=BRSKpitGproY48JQdCbfrghbDonA-EqPP1yIopohpPo,2525
110
110
  fractal_server/app/runner/versions.py,sha256=4BW-8Et8RVgILgpFoUJLWkEnZz53pv8hv_2ucG480ns,398
111
111
  fractal_server/app/schemas/__init__.py,sha256=stURAU_t3AOBaH0HSUbV-GKhlPKngnnIMoqWc3orFyI,135
@@ -122,14 +122,14 @@ fractal_server/app/schemas/v2/manifest.py,sha256=QUpXMDB8WkB1F4UK-yYmm3O8bXoHwDG
122
122
  fractal_server/app/schemas/v2/project.py,sha256=7UC0aZLgtmkaAiPykeUj-9OZXhMkoyi3V-475UW_EQs,654
123
123
  fractal_server/app/schemas/v2/status_legacy.py,sha256=eQT1zGxbkzSwd0EqclsOdZ60n1x6J3DB1CZ3m4LYyxc,955
124
124
  fractal_server/app/schemas/v2/task.py,sha256=IJv8loB4kx9FBkaIHoiMsswQyq02FxvyAnHK1u074fU,4364
125
- fractal_server/app/schemas/v2/task_collection.py,sha256=EPGe4bTRka-Y3S3_h6Wfmstq1889Cn-5cZ9ODdnsKG8,4154
125
+ fractal_server/app/schemas/v2/task_collection.py,sha256=1sz2fJEUgRVVjwGGXFyRsr4L6RnNvTKQJsRXbMjNmps,4176
126
126
  fractal_server/app/schemas/v2/task_group.py,sha256=NwU3FRPzPtoEhunE7dcF3su20dxaL_4YJQw4fPnTcgo,3231
127
127
  fractal_server/app/schemas/v2/workflow.py,sha256=L-dW6SzCH_VNoH6ENip44lTgGGqVYHHBk_3PtM-Ooy8,1772
128
128
  fractal_server/app/schemas/v2/workflowtask.py,sha256=6eweAMyziwaoMT-7R1fVJYunIeZKzT0-7fAVgPO_FEc,3639
129
129
  fractal_server/app/security/__init__.py,sha256=oJ8RVglpOvWPQY4RokiE2YA72Nqo42dZEjywWTt8xr8,14032
130
130
  fractal_server/app/security/signup_email.py,sha256=Xd6QYxcdmg0PHpDwmUE8XQmPcOj3Xjy5oROcIMhmltM,1472
131
131
  fractal_server/app/user_settings.py,sha256=OP1yiYKtPadxwM51_Q0hdPk3z90TCN4z1BLpQsXyWiU,1316
132
- fractal_server/config.py,sha256=oVNGnbyLhvVzcFnCPS4UCCEXbAVyACZR_u4fDsBa534,28337
132
+ fractal_server/config.py,sha256=NQ4wHfxzbd3nlCLbuATimq-5L7OQ2-4Y9MnyX1DEup0,28484
133
133
  fractal_server/data_migrations/2_14_10.py,sha256=jzMg2c1zNO8C_Nho_9_EZJD6kR1-gkFNpNrMR5Hr8hM,1598
134
134
  fractal_server/data_migrations/README.md,sha256=_3AEFvDg9YkybDqCLlFPdDmGJvr6Tw7HRI14aZ3LOIw,398
135
135
  fractal_server/data_migrations/tools.py,sha256=LeMeASwYGtEqd-3wOLle6WARdTGAimoyMmRbbJl-hAM,572
@@ -186,7 +186,7 @@ fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py,sha256=TDWC
186
186
  fractal_server/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
187
187
  fractal_server/ssh/__init__.py,sha256=sVUmzxf7_DuXG1xoLQ1_00fo5NPhi2LJipSmU5EAkPs,124
188
188
  fractal_server/ssh/_fabric.py,sha256=7fCxTYqkAOaTTm67trfYdYQenOsI4EfrRQoG6x3M5kk,25188
189
- fractal_server/string_tools.py,sha256=qLB5u6-4QxXPiZrUeWn_cEo47axj4OXFzDd47kNTIWw,1847
189
+ fractal_server/string_tools.py,sha256=UJFi8rhlI6QXxX5twycLjsvOQ6x4uG7L3JdxEVDhC5A,2592
190
190
  fractal_server/syringe.py,sha256=3YJeIALH-wibuJ9R5VMNYUWh7x1-MkWT0SqGcWG5MY8,2795
191
191
  fractal_server/tasks/__init__.py,sha256=kadmVUoIghl8s190_Tt-8f-WBqMi8u8oU4Pvw39NHE8,23
192
192
  fractal_server/tasks/utils.py,sha256=V7dj8o2AnoHhGSTYlqJHcRFhCIpmOrMOUhtiE_DvRVA,291
@@ -200,13 +200,13 @@ fractal_server/tasks/v2/local/deactivate_pixi.py,sha256=x9YCILEP1EjCrZccAcj5C5i0
200
200
  fractal_server/tasks/v2/local/reactivate.py,sha256=Q43DOadNeFyyfgNP67lUqaXmZsS6onv67XwxH_-5ANA,5756
201
201
  fractal_server/tasks/v2/local/reactivate_pixi.py,sha256=IuxDRaj8i6Rc582TIbc9HVKQ9pOvR4IepyXSaJx2PfQ,7565
202
202
  fractal_server/tasks/v2/ssh/__init__.py,sha256=vX5aIM9Hbn2T_cIP_LrZ5ekRqJzYm_GSfp-4Iv7kqeI,300
203
- fractal_server/tasks/v2/ssh/_utils.py,sha256=jMe3eg2duad8wtGS_RD6oOIvA0LyJEg5cn--qanGuwE,4954
203
+ fractal_server/tasks/v2/ssh/_utils.py,sha256=V8ZcjEMCNSHivUyu1rnGG_V96Ylq1RRvocQDN1n6BAw,5120
204
204
  fractal_server/tasks/v2/ssh/collect.py,sha256=WesUBtNaax9ST7CtgqAD2qd-ZII4t1JFPzRzltEOuM8,14333
205
- fractal_server/tasks/v2/ssh/collect_pixi.py,sha256=PWv-5cQFLA3n4NeFsTU-zfE1xWEy8LoLvHy41gRtWW8,14169
205
+ fractal_server/tasks/v2/ssh/collect_pixi.py,sha256=unZXs3qjBoWYBIa2xWiIKz2CVMVBAhcloQ_9YJ97n5k,14211
206
206
  fractal_server/tasks/v2/ssh/deactivate.py,sha256=7gJ2mOah0wKwUnK0S9QpaXg08_WE95P0rC-oExAGhLE,12438
207
207
  fractal_server/tasks/v2/ssh/deactivate_pixi.py,sha256=K0yK_NPUqhFMj6cp6G_0Kfn0Yo7oQux4kT5dFPulnos,4748
208
208
  fractal_server/tasks/v2/ssh/reactivate.py,sha256=NJIgMNFKaXMhbvK0iZOsMwMtsms6Boj9f8N4L01X9Bo,8271
209
- fractal_server/tasks/v2/ssh/reactivate_pixi.py,sha256=JGP19nbmCCuE8Ya7sBfgrm78vORM0bF0tkt3bWakvF0,10281
209
+ fractal_server/tasks/v2/ssh/reactivate_pixi.py,sha256=UOlG01wOv-eQCtUxSwphEY-Ey7OoUm5PMCSP9J-i1rY,10323
210
210
  fractal_server/tasks/v2/templates/1_create_venv.sh,sha256=PK0jdHKtQpda1zULebBaVPORt4t6V17wa4N1ohcj5ac,548
211
211
  fractal_server/tasks/v2/templates/2_pip_install.sh,sha256=jMJPQJXHKznO6fxOOXtFXKPdCmTf1VLLWj_JL_ZdKxo,1644
212
212
  fractal_server/tasks/v2/templates/3_pip_freeze.sh,sha256=JldREScEBI4cD_qjfX4UK7V4aI-FnX9ZvVNxgpSOBFc,168
@@ -219,8 +219,8 @@ fractal_server/tasks/v2/templates/pixi_3_post_install.sh,sha256=99J8KXkNeQk9utuE
219
219
  fractal_server/tasks/v2/utils_background.py,sha256=_4wGETgZ3JdnJXLYKSI0Lns8LwokJL-NEzUOK5SxCJU,4811
220
220
  fractal_server/tasks/v2/utils_database.py,sha256=yi7793Uue32O59OBVUgomO42oUrVKdSKXoShBUNDdK0,1807
221
221
  fractal_server/tasks/v2/utils_package_names.py,sha256=RDg__xrvQs4ieeVzmVdMcEh95vGQYrv9Hfal-5EDBM8,2393
222
- fractal_server/tasks/v2/utils_pixi.py,sha256=VNcHNaHH8uceEtBvuiD-hCjkJHutAP6F4BbEVrAKfbU,3102
223
- fractal_server/tasks/v2/utils_python_interpreter.py,sha256=JOYHou_zgV83zsmNeR9tX0F2xjiYVwKvEASh9nIDGlw,956
222
+ fractal_server/tasks/v2/utils_pixi.py,sha256=tqCnxMdxs7KGWncWvk0alrdvDbX-w77P3fAot68Bqh4,3257
223
+ fractal_server/tasks/v2/utils_python_interpreter.py,sha256=kF86UClk6HxghRLDYY4rKOXwnWGUYQfrNsVNxOmOGxM,964
224
224
  fractal_server/tasks/v2/utils_templates.py,sha256=GR8z7ODkR9tLftNAI1g1NrtN7pvDGrasp2jIlfdg4cI,3518
225
225
  fractal_server/types/__init__.py,sha256=aA_8J1xXzuiLqpwO_Qf18-qzaRcYkHzevhH_T-diXWM,2026
226
226
  fractal_server/types/validators/__init__.py,sha256=5uj6KJ9MelFZgyoq3MzXLhgWCl0yiriS7XKmb0gathg,392
@@ -230,8 +230,8 @@ fractal_server/types/validators/_workflow_task_arguments_validators.py,sha256=HL
230
230
  fractal_server/urls.py,sha256=QjIKAC1a46bCdiPMu3AlpgFbcv6a4l3ABcd5xz190Og,471
231
231
  fractal_server/utils.py,sha256=Vn35lApt1T1J8nc09sAVqd10Cy0sa3dLipcljI-hkuk,2185
232
232
  fractal_server/zip_tools.py,sha256=H0w7wS5yE4ebj7hw1_77YQ959dl2c-L0WX6J_ro1TY4,4884
233
- fractal_server-2.15.5.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
234
- fractal_server-2.15.5.dist-info/METADATA,sha256=alHs8DIeP4bge-Vz4triLn_4wPoLN80jrrbbQpGqp4E,4283
235
- fractal_server-2.15.5.dist-info/WHEEL,sha256=7dDg4QLnNKTvwIDR9Ac8jJaAmBC_owJrckbC0jjThyA,88
236
- fractal_server-2.15.5.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
237
- fractal_server-2.15.5.dist-info/RECORD,,
233
+ fractal_server-2.15.7.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
234
+ fractal_server-2.15.7.dist-info/METADATA,sha256=8pzRt84EdeTR6rbYAlgbDw6cC-YErI_N_eBIeGUtvLs,4334
235
+ fractal_server-2.15.7.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
236
+ fractal_server-2.15.7.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
237
+ fractal_server-2.15.7.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any