fractal-server 2.11.0a3__py3-none-any.whl → 2.11.0a4__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.11.0a3"
1
+ __VERSION__ = "2.11.0a4"
@@ -423,7 +423,7 @@ def _parse_mem_value(raw_mem: Union[str, int]) -> int:
423
423
  )
424
424
 
425
425
  # Handle integer argument
426
- if isinstance(raw_mem, int):
426
+ if type(raw_mem) is int:
427
427
  return raw_mem
428
428
 
429
429
  # Handle string argument
@@ -15,13 +15,6 @@ def merge_outputs(task_outputs: list[TaskOutput]) -> TaskOutput:
15
15
  final_image_list_updates.extend(task_output.image_list_updates)
16
16
  final_image_list_removals.extend(task_output.image_list_removals)
17
17
 
18
- # Check that all type_filters are the same
19
- if task_output.type_filters != task_outputs[0].type_filters:
20
- raise ValueError(
21
- f"{task_output.type_filters=} "
22
- f"but {task_outputs[0].type_filters=}"
23
- )
24
-
25
18
  # Note: the ordering of `image_list_removals` is not guaranteed
26
19
  final_image_list_updates = deduplicate_list(final_image_list_updates)
27
20
  final_image_list_removals = list(set(final_image_list_removals))
@@ -29,7 +22,6 @@ def merge_outputs(task_outputs: list[TaskOutput]) -> TaskOutput:
29
22
  final_output = TaskOutput(
30
23
  image_list_updates=final_image_list_updates,
31
24
  image_list_removals=final_image_list_removals,
32
- type_filters=task_outputs[0].type_filters,
33
25
  )
34
26
 
35
27
  return final_output
@@ -11,7 +11,6 @@ from sqlalchemy.orm.attributes import flag_modified
11
11
  from ....images import SingleImage
12
12
  from ....images.tools import filter_image_list
13
13
  from ....images.tools import find_image_by_zarr_url
14
- from ....images.tools import match_filter
15
14
  from ..exceptions import JobExecutionError
16
15
  from .runner_functions import no_op_submit_setup_call
17
16
  from .runner_functions import run_v2_task_compound
@@ -24,6 +23,7 @@ from fractal_server.app.models.v2 import WorkflowTaskV2
24
23
  from fractal_server.app.schemas.v2.dataset import _DatasetHistoryItemV2
25
24
  from fractal_server.app.schemas.v2.workflowtask import WorkflowTaskStatusTypeV2
26
25
  from fractal_server.images.models import AttributeFiltersType
26
+ from fractal_server.images.tools import merge_type_filters
27
27
 
28
28
 
29
29
  def execute_tasks_v2(
@@ -49,7 +49,7 @@ def execute_tasks_v2(
49
49
  # Initialize local dataset attributes
50
50
  zarr_dir = dataset.zarr_dir
51
51
  tmp_images = deepcopy(dataset.images)
52
- tmp_type_filters = deepcopy(dataset.type_filters)
52
+ current_dataset_type_filters = deepcopy(dataset.type_filters)
53
53
 
54
54
  for wftask in wf_task_list:
55
55
  task = wftask.task
@@ -59,26 +59,18 @@ def execute_tasks_v2(
59
59
  # PRE TASK EXECUTION
60
60
 
61
61
  # Get filtered images
62
- pre_type_filters = copy(tmp_type_filters)
63
- pre_type_filters.update(wftask.type_filters)
62
+ type_filters = copy(current_dataset_type_filters)
63
+ type_filters_patch = merge_type_filters(
64
+ task_input_types=task.input_types,
65
+ wftask_type_filters=wftask.type_filters,
66
+ )
67
+ type_filters.update(type_filters_patch)
64
68
  filtered_images = filter_image_list(
65
69
  images=tmp_images,
66
- type_filters=pre_type_filters,
70
+ type_filters=type_filters,
67
71
  attribute_filters=job_attribute_filters,
68
72
  )
69
- # Verify that filtered images comply with task input_types
70
- for image in filtered_images:
71
- if not match_filter(
72
- image=image,
73
- type_filters=task.input_types,
74
- attribute_filters={},
75
- ):
76
- raise JobExecutionError(
77
- "Invalid filtered image list\n"
78
- f"Task input types: {task.input_types=}\n"
79
- f'Image zarr_url: {image["zarr_url"]}\n'
80
- f'Image types: {image["types"]}\n'
81
- )
73
+
82
74
  # First, set status SUBMITTED in dataset.history for each wftask
83
75
  with next(get_sync_db()) as db:
84
76
  db_dataset = db.get(DatasetV2, dataset.id)
@@ -262,30 +254,9 @@ def execute_tasks_v2(
262
254
  else:
263
255
  tmp_images.pop(img_search["index"])
264
256
 
265
- # Update type_filters
266
-
267
- # Assign the type filters based on different sources
268
- # (task manifest and post-execution task output)
257
+ # Update type_filters based on task-manifest output_types
269
258
  type_filters_from_task_manifest = task.output_types
270
- type_filters_from_task_output = current_task_output.type_filters
271
-
272
- # Check that key sets are disjoint
273
- keys_from_manifest = set(type_filters_from_task_manifest.keys())
274
- keys_from_task_output = set(type_filters_from_task_output.keys())
275
- if not keys_from_manifest.isdisjoint(keys_from_task_output):
276
- overlap = keys_from_manifest.intersection(keys_from_task_output)
277
- raise JobExecutionError(
278
- "Some type filters are being set twice, "
279
- f"for task '{task_name}'.\n"
280
- f"Types from task output: {type_filters_from_task_output}\n"
281
- "Types from task manifest: "
282
- f"{type_filters_from_task_manifest}\n"
283
- f"Overlapping keys: {overlap}"
284
- )
285
-
286
- # Update filters.types
287
- tmp_type_filters.update(type_filters_from_task_manifest)
288
- tmp_type_filters.update(type_filters_from_task_output)
259
+ current_dataset_type_filters.update(type_filters_from_task_manifest)
289
260
 
290
261
  # Write current dataset attributes (history, images, filters) into the
291
262
  # database. They can be used (1) to retrieve the latest state
@@ -294,7 +265,7 @@ def execute_tasks_v2(
294
265
  with next(get_sync_db()) as db:
295
266
  db_dataset = db.get(DatasetV2, dataset.id)
296
267
  db_dataset.history[-1]["status"] = WorkflowTaskStatusTypeV2.DONE
297
- db_dataset.type_filters = tmp_type_filters
268
+ db_dataset.type_filters = current_dataset_type_filters
298
269
  db_dataset.images = tmp_images
299
270
  for attribute_name in [
300
271
  "type_filters",
@@ -1,31 +1,14 @@
1
1
  from typing import Any
2
- from typing import Optional
3
2
 
4
3
  from pydantic import BaseModel
5
4
  from pydantic import Extra
6
5
  from pydantic import Field
7
- from pydantic import root_validator
8
6
  from pydantic import validator
9
7
 
10
8
  from ....images import SingleImageTaskOutput
11
- from fractal_server.app.schemas._filter_validators import validate_type_filters
12
- from fractal_server.app.schemas._validators import root_validate_dict_keys
13
9
  from fractal_server.urls import normalize_url
14
10
 
15
11
 
16
- class LegacyFilters(BaseModel, extra=Extra.forbid):
17
- """
18
- For fractal-server<2.11, task output could include both
19
- `filters["attributes"]` and `filters["types"]`. In the new version
20
- there is a single field, named `type_filters`.
21
- The current schema is only used to convert old type filters into the
22
- new form, but it will reject any attribute filters.
23
- """
24
-
25
- types: dict[str, bool] = Field(default_factory=dict)
26
- _types = validator("types", allow_reuse=True)(validate_type_filters)
27
-
28
-
29
12
  class TaskOutput(BaseModel, extra=Extra.forbid):
30
13
 
31
14
  image_list_updates: list[SingleImageTaskOutput] = Field(
@@ -33,16 +16,6 @@ class TaskOutput(BaseModel, extra=Extra.forbid):
33
16
  )
34
17
  image_list_removals: list[str] = Field(default_factory=list)
35
18
 
36
- filters: Optional[LegacyFilters] = None
37
- type_filters: dict[str, bool] = Field(default_factory=dict)
38
-
39
- _dict_keys = root_validator(pre=True, allow_reuse=True)(
40
- root_validate_dict_keys
41
- )
42
- _type_filters = validator("type_filters", allow_reuse=True)(
43
- validate_type_filters
44
- )
45
-
46
19
  def check_zarr_urls_are_unique(self) -> None:
47
20
  zarr_urls = [img.zarr_url for img in self.image_list_updates]
48
21
  zarr_urls.extend(self.image_list_removals)
@@ -62,20 +35,6 @@ class TaskOutput(BaseModel, extra=Extra.forbid):
62
35
  msg = f"{msg}\n{duplicate}"
63
36
  raise ValueError(msg)
64
37
 
65
- @root_validator()
66
- def update_legacy_filters(cls, values):
67
- if values["filters"] is not None:
68
- if values["type_filters"] != {}:
69
- raise ValueError(
70
- "Cannot set both (legacy) 'filters' and 'type_filters'."
71
- )
72
- else:
73
- # Convert legacy filters.types into new type_filters
74
- values["type_filters"] = values["filters"].types
75
- values["filters"] = None
76
-
77
- return values
78
-
79
38
  @validator("image_list_removals")
80
39
  def normalize_paths(cls, v: list[str]) -> list[str]:
81
40
  return [normalize_url(zarr_url) for zarr_url in v]
@@ -34,7 +34,7 @@ def validate_attribute_filters(
34
34
  # values is a non-empty list, and its items must all be of the
35
35
  # same scalar non-None type
36
36
  _type = type(values[0])
37
- if not all(isinstance(value, _type) for value in values):
37
+ if not all(type(value) is _type for value in values):
38
38
  raise ValueError(
39
39
  f"attribute_filters[{key}] has values with "
40
40
  f"non-homogeneous types: {values}."
@@ -65,3 +65,5 @@ def fix_db():
65
65
 
66
66
  db.commit()
67
67
  logger.info("Changes committed.")
68
+
69
+ logger.info("END execution of fix_db function")
@@ -98,3 +98,28 @@ def filter_image_list(
98
98
  )
99
99
  ]
100
100
  return filtered_images
101
+
102
+
103
+ def merge_type_filters(
104
+ *,
105
+ task_input_types: dict[str, bool],
106
+ wftask_type_filters: dict[str, bool],
107
+ ) -> dict[str, bool]:
108
+ """
109
+ Merge two type-filters sets, if they are compatible.
110
+ """
111
+ all_keys = set(task_input_types.keys()) | set(wftask_type_filters.keys())
112
+ for key in all_keys:
113
+ if (
114
+ key in task_input_types.keys()
115
+ and key in wftask_type_filters.keys()
116
+ and task_input_types[key] != wftask_type_filters[key]
117
+ ):
118
+ raise ValueError(
119
+ "Cannot merge type filters "
120
+ f"`{task_input_types}` (from task) "
121
+ f"and `{wftask_type_filters}` (from workflowtask)."
122
+ )
123
+ merged_dict = task_input_types
124
+ merged_dict.update(wftask_type_filters)
125
+ return merged_dict
fractal_server/utils.py CHANGED
@@ -107,18 +107,20 @@ def execute_command_sync(
107
107
  returncode = res.returncode
108
108
  stdout = res.stdout
109
109
  stderr = res.stderr
110
- logger.debug(f"{returncode=}")
111
- logger.debug("STDOUT:")
112
- logger.debug(stdout)
113
- logger.debug("STDERR:")
114
- logger.debug(stderr)
115
110
  if res.returncode != 0:
116
111
  logger.debug(f"ERROR in subprocess call to '{command}'")
117
112
  raise RuntimeError(
118
113
  f"Command {command} failed.\n"
119
114
  f"returncode={res.returncode}\n"
120
- f"{stdout=}\n"
121
- f"{stderr=}\n"
115
+ "STDOUT:\n"
116
+ f"{stdout}\n"
117
+ "STDERR:\n"
118
+ f"{stderr}\n"
122
119
  )
120
+ logger.debug(f"{returncode=}")
121
+ logger.debug("STDOUT:")
122
+ logger.debug(stdout)
123
+ logger.debug("STDERR:")
124
+ logger.debug(stderr)
123
125
  logger.debug(f"END subprocess call to '{command}'")
124
126
  return stdout
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fractal-server
3
- Version: 2.11.0a3
3
+ Version: 2.11.0a4
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  Home-page: https://github.com/fractal-analytics-platform/fractal-server
6
6
  License: BSD-3-Clause
@@ -1,4 +1,4 @@
1
- fractal_server/__init__.py,sha256=o_3QCs2FdlBclhmQ7GWAIcInUjrL307BrDoHMarxuSE,25
1
+ fractal_server/__init__.py,sha256=DZWnRj7O86D5FPeOgamWSQFlyHVz7jh1SwTyyBfs6GQ,25
2
2
  fractal_server/__main__.py,sha256=D2YTmSowmXNyvqOjW_HeItCZT2UliWlySl_owicaZg0,8026
3
3
  fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
4
4
  fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -81,7 +81,7 @@ fractal_server/app/runner/exceptions.py,sha256=_qZ_t8O4umAdJ1ikockiF5rDJuxnEskrG
81
81
  fractal_server/app/runner/executors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
82
  fractal_server/app/runner/executors/slurm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
83
  fractal_server/app/runner/executors/slurm/_batching.py,sha256=3mfeFuYm3UA4EXh4VWuqZTF-dcINECZgTHoPOaOszDo,8840
84
- fractal_server/app/runner/executors/slurm/_slurm_config.py,sha256=P0TDfIFf07h0hIhVNZUcY3t5vgdjptU-2T0uC_ZBEB4,15688
84
+ fractal_server/app/runner/executors/slurm/_slurm_config.py,sha256=Qa5UgcMZfYEj95dMA5GF3WgNx8zQ_XH6ufNYYmhI4rs,15684
85
85
  fractal_server/app/runner/executors/slurm/remote.py,sha256=wLziIsGdSMiO-jIXM8x77JRK82g_2hx0iBKTiMghuIo,5852
86
86
  fractal_server/app/runner/executors/slurm/ssh/__init__.py,sha256=Cjn1rYvljddi96tAwS-qqGkNfOcfPzjChdaEZEObCcM,65
87
87
  fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py,sha256=bKo5Ja0IGxJWpPWyh9dN0AG-PwzTDZzD5LyaEHB3YU4,3742
@@ -127,14 +127,14 @@ fractal_server/app/runner/v2/_slurm_sudo/__init__.py,sha256=sGc1wGMPD6yQv6-MmTTG
127
127
  fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py,sha256=a5_FDPH_yxYmrjAjMRLgh_Y4DSG3mRslCLQodGM3-t4,2838
128
128
  fractal_server/app/runner/v2/deduplicate_list.py,sha256=-imwO7OB7ATADEnqVbTElUwoY0YIJCTf_SbWJNN9OZg,639
129
129
  fractal_server/app/runner/v2/handle_failed_job.py,sha256=-zFWw4d208bQEFUF_sAdH2LdHEARyg1FC8BENr1SjhU,2045
130
- fractal_server/app/runner/v2/merge_outputs.py,sha256=DW1d-fT0UcSnJUmz8xfU-AEeI7p_G0aQ_lNpDAe9C2o,1226
131
- fractal_server/app/runner/v2/runner.py,sha256=tdEjF2SWwDKXCHXz0wFRtKTRCG2I5BSjuqY08YSjMHs,12906
130
+ fractal_server/app/runner/v2/merge_outputs.py,sha256=D1L4Taieq9i71SPQyNc1kMokgHh-sV_MqF3bv7QMDBc,907
131
+ fractal_server/app/runner/v2/runner.py,sha256=ll0-nglUytoxDnMwMRgjY2901UnFb37bkSsxWK1KLA0,11595
132
132
  fractal_server/app/runner/v2/runner_functions.py,sha256=BLREIcQaE6FSc2AEJyZuiYk6rGazEz_9gprUqUZDljs,9488
133
133
  fractal_server/app/runner/v2/runner_functions_low_level.py,sha256=1fWvQ6YZUUnDhO_mipXC5hnaT-zK-GHxg8ayoxZX82k,3648
134
- fractal_server/app/runner/v2/task_interface.py,sha256=DU0fppTqvwhVkKwjPvfWPuZt09rV7AV2U5Vpu5CRqX8,3268
134
+ fractal_server/app/runner/v2/task_interface.py,sha256=d6HPwPzrytUMVjExTU6fuCEwtvvWGRaSje0iXcRD45w,1728
135
135
  fractal_server/app/runner/versions.py,sha256=dSaPRWqmFPHjg20kTCHmi_dmGNcCETflDtDLronNanU,852
136
136
  fractal_server/app/schemas/__init__.py,sha256=stURAU_t3AOBaH0HSUbV-GKhlPKngnnIMoqWc3orFyI,135
137
- fractal_server/app/schemas/_filter_validators.py,sha256=9oGzf1yghFkIMbzluvxeRCjPei8V7dn7ot4ggQUmz8w,1731
137
+ fractal_server/app/schemas/_filter_validators.py,sha256=WcfQ3ARc-2pj2oQFB4lWA0X5wtoOPGzpD4hJq4BblXs,1727
138
138
  fractal_server/app/schemas/_validators.py,sha256=3dotVxUHWKAmUO3aeoluYDLRKrw1OS-NxcZ4Fg_HOYk,3560
139
139
  fractal_server/app/schemas/user.py,sha256=icjox9gK_invW44Nh_L4CvqfRa92qghyQhmevyg09nQ,2243
140
140
  fractal_server/app/schemas/user_group.py,sha256=t30Kd07PY43G_AqFDb8vjdInTeLeU9WvFZDx8fVLPSI,1750
@@ -165,13 +165,13 @@ fractal_server/app/security/__init__.py,sha256=qn6idYgl-p5HWea0gTVnz4JnkoxGEkmQj
165
165
  fractal_server/app/security/signup_email.py,sha256=DrL51UdTSrgjleynMD5CRZwTSOpPrZ96fasRV0fvxDE,1165
166
166
  fractal_server/app/user_settings.py,sha256=OP1yiYKtPadxwM51_Q0hdPk3z90TCN4z1BLpQsXyWiU,1316
167
167
  fractal_server/config.py,sha256=9rAzw7OO6ZeHEz-I8NJHuGoHf4xCHxfFLyRNZQD9ytY,27019
168
- fractal_server/data_migrations/2_11_0.py,sha256=PPFg1GxpfW5hElwzr_kx0_fYuEaNSyH23uCxztExO14,2411
168
+ fractal_server/data_migrations/2_11_0.py,sha256=glS3BkhumrA6SpHiE_QFBgA7Bm2cbDCUlQyY3BjEub8,2464
169
169
  fractal_server/data_migrations/README.md,sha256=_3AEFvDg9YkybDqCLlFPdDmGJvr6Tw7HRI14aZ3LOIw,398
170
170
  fractal_server/data_migrations/tools.py,sha256=LeMeASwYGtEqd-3wOLle6WARdTGAimoyMmRbbJl-hAM,572
171
171
  fractal_server/gunicorn_fractal.py,sha256=u6U01TLGlXgq1v8QmEpLih3QnsInZD7CqphgJ_GrGzc,1230
172
172
  fractal_server/images/__init__.py,sha256=-_wjoKtSX02P1KjDxDP_EXKvmbONTRmbf7iGVTsyBpM,154
173
173
  fractal_server/images/models.py,sha256=fAecChXhs4utRX4123Lgz5e_b_H0YtHrvNHCenR7tOs,3359
174
- fractal_server/images/tools.py,sha256=VFjm5pCOWjc2ms0t0s4nH6bK53ZU867JDL5oTEm4M1Q,2648
174
+ fractal_server/images/tools.py,sha256=iqFx_pp46OoHsHjXxX6GrkXJPPfTo_c1WYvRur0olaE,3455
175
175
  fractal_server/logger.py,sha256=zwg_AjIHkNP0ruciXjm5lI5UFP3n6tMHullsM9lDjz4,5039
176
176
  fractal_server/main.py,sha256=gStLT9Du5QMpc9SyvRvtKU21EKwp-dG4HL3zGHzE06A,4908
177
177
  fractal_server/migrations/env.py,sha256=9t_OeKVlhM8WRcukmTrLbWNup-imiBGP_9xNgwCbtpI,2730
@@ -239,10 +239,10 @@ fractal_server/tasks/v2/utils_package_names.py,sha256=RDg__xrvQs4ieeVzmVdMcEh95v
239
239
  fractal_server/tasks/v2/utils_python_interpreter.py,sha256=5_wrlrTqXyo1YuLZvAW9hrSoh5MyLOzdPVUlUwM7uDQ,955
240
240
  fractal_server/tasks/v2/utils_templates.py,sha256=07TZpJ0Mh_A4lXVXrrH2o1VLFFGwxeRumA6DdgMgCWk,2947
241
241
  fractal_server/urls.py,sha256=QjIKAC1a46bCdiPMu3AlpgFbcv6a4l3ABcd5xz190Og,471
242
- fractal_server/utils.py,sha256=utvmBx8K9I8hRWFquxna2pBaOqe0JifDL_NVPmihEJI,3525
242
+ fractal_server/utils.py,sha256=PMwrxWFxRTQRl1b9h-NRIbFGPKqpH_hXnkAT3NfZdpY,3571
243
243
  fractal_server/zip_tools.py,sha256=GjDgo_sf6V_DDg6wWeBlZu5zypIxycn_l257p_YVKGc,4876
244
- fractal_server-2.11.0a3.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
245
- fractal_server-2.11.0a3.dist-info/METADATA,sha256=PpEo4R-FpyRduTHTutRl1UdRHHwtb1dyFUKmLT2Zm1I,4564
246
- fractal_server-2.11.0a3.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
247
- fractal_server-2.11.0a3.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
248
- fractal_server-2.11.0a3.dist-info/RECORD,,
244
+ fractal_server-2.11.0a4.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
245
+ fractal_server-2.11.0a4.dist-info/METADATA,sha256=Y_VNqSmaDdR4YhuzzFtSRAbS4nPicovQyWytyGfKB18,4564
246
+ fractal_server-2.11.0a4.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
247
+ fractal_server-2.11.0a4.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
248
+ fractal_server-2.11.0a4.dist-info/RECORD,,