fractal-task-tools 0.0.6__py3-none-any.whl → 0.0.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.

Potentially problematic release.


This version of fractal-task-tools might be problematic. Click here for more details.

@@ -2,4 +2,4 @@ import logging
2
2
 
3
3
  logging.basicConfig(level=logging.INFO)
4
4
 
5
- __VERSION__ = "0.0.6"
5
+ __VERSION__ = "0.0.7"
@@ -1,9 +1,9 @@
1
1
  import argparse as ap
2
2
  import sys
3
3
 
4
- from fractal_task_tools._create_manifest import check_manifest
4
+ from fractal_task_tools._cli_tools import check_manifest
5
+ from fractal_task_tools._cli_tools import write_manifest_to_file
5
6
  from fractal_task_tools._create_manifest import create_manifest
6
- from fractal_task_tools._create_manifest import write_manifest_to_file
7
7
 
8
8
 
9
9
  main_parser = ap.ArgumentParser(
@@ -47,6 +47,16 @@ for subparser in (create_manifest_parser, check_manifest_parser):
47
47
  default="dev.task_list",
48
48
  required=False,
49
49
  )
50
+ check_manifest_parser.add_argument(
51
+ "--ignore-keys-order",
52
+ type=bool,
53
+ help=(
54
+ "Ignore the order of dictionary keys when comparing manifests "
55
+ "(default value: False)."
56
+ ),
57
+ default=False,
58
+ required=False,
59
+ )
50
60
 
51
61
 
52
62
  def main():
@@ -69,4 +79,5 @@ def main():
69
79
  check_manifest(
70
80
  raw_package_name=args.package,
71
81
  manifest=manifest,
82
+ ignore_keys_order=args.ignore_keys_order,
72
83
  )
@@ -0,0 +1,86 @@
1
+ import json
2
+ import logging
3
+ import os
4
+ import sys
5
+ from importlib import import_module
6
+ from pathlib import Path
7
+
8
+ from fractal_task_tools._create_manifest import MANIFEST_FILENAME
9
+ from fractal_task_tools._deepdiff import deepdiff
10
+ from fractal_task_tools._package_name_tools import normalize_package_name
11
+
12
+
13
+ def write_manifest_to_file(
14
+ *,
15
+ raw_package_name: str,
16
+ manifest: str,
17
+ ) -> None:
18
+ """
19
+ Write manifest to file.
20
+
21
+ Arguments:
22
+ raw_package_name:
23
+ manifest: The manifest object
24
+ """
25
+ logging.info("[write_manifest_to_file] START")
26
+
27
+ package_name = normalize_package_name(raw_package_name)
28
+ logging.info(f"[write_manifest_to_file] {package_name=}")
29
+
30
+ imported_package = import_module(package_name)
31
+ package_root_dir = Path(imported_package.__file__).parent
32
+ manifest_path = (package_root_dir / MANIFEST_FILENAME).as_posix()
33
+ logging.info(f"[write_manifest_to_file] {os.getcwd()=}")
34
+ logging.info(f"[write_manifest_to_file] {package_root_dir=}")
35
+ logging.info(f"[write_manifest_to_file] {manifest_path=}")
36
+
37
+ with open(manifest_path, "w") as f:
38
+ json.dump(manifest, f, indent=2)
39
+ f.write("\n")
40
+
41
+ logging.info("[write_manifest_to_file] END")
42
+
43
+
44
+ def check_manifest(
45
+ *,
46
+ raw_package_name: str,
47
+ manifest: str,
48
+ ignore_keys_order: bool,
49
+ ) -> None:
50
+ """
51
+ Write manifest to file.
52
+
53
+ Arguments:
54
+ raw_package_name:
55
+ manifest: The manifest object
56
+ ignore_keys_order: Whether to ignore keys order.
57
+ """
58
+
59
+ package_name = normalize_package_name(raw_package_name)
60
+ logging.info(f"[check_manifest] {package_name=}")
61
+
62
+ imported_package = import_module(package_name)
63
+ package_root_dir = Path(imported_package.__file__).parent
64
+ manifest_path = (package_root_dir / MANIFEST_FILENAME).as_posix()
65
+ logging.info(f"[check_manifest] {os.getcwd()=}")
66
+ logging.info(f"[check_manifest] {package_root_dir=}")
67
+ logging.info(f"[check_manifest] {manifest_path=}")
68
+
69
+ with open(manifest_path, "r") as f:
70
+ old_manifest = json.load(f)
71
+ if manifest == old_manifest:
72
+ logging.info("[check_manifest] On-disk manifest is up to date.")
73
+ else:
74
+ logging.error("[check_manifest] On-disk manifest is not up to date.")
75
+ try:
76
+ deepdiff(
77
+ old_object=old_manifest,
78
+ new_object=manifest,
79
+ path="manifest",
80
+ ignore_keys_order=ignore_keys_order,
81
+ )
82
+ except ValueError as e:
83
+ logging.error(str(e))
84
+ sys.exit("New/old manifests differ")
85
+
86
+ logging.info("[check_manifest] END")
@@ -1,12 +1,8 @@
1
1
  """
2
2
  Generate JSON schemas for task arguments and combine them into a manifest.
3
3
  """
4
- import json
5
4
  import logging
6
- import os
7
- import sys
8
5
  from importlib import import_module
9
- from pathlib import Path
10
6
  from typing import Any
11
7
 
12
8
  from ._args_schemas import create_schema_for_single_task
@@ -54,9 +50,10 @@ def create_manifest(
54
50
  # Prepare an empty manifest
55
51
  manifest = dict(
56
52
  manifest_version=MANIFEST_VERSION,
53
+ task_list=[],
57
54
  has_args_schemas=True,
58
55
  args_schema_version=ARGS_SCHEMA_VERSION,
59
- task_list=[],
56
+ authors=None,
60
57
  )
61
58
 
62
59
  # Import the task-list module
@@ -143,72 +140,4 @@ def create_manifest(
143
140
 
144
141
  # Append task
145
142
  manifest["task_list"].append(task_dict)
146
- print()
147
143
  return manifest
148
-
149
-
150
- def write_manifest_to_file(
151
- *,
152
- raw_package_name: str,
153
- manifest: str,
154
- ) -> None:
155
- """
156
- Write manifest to file.
157
-
158
- Arguments:
159
- raw_package_name:
160
- manifest: The manifest object
161
- """
162
- logging.info("[write_manifest_to_file] START")
163
-
164
- package_name = normalize_package_name(raw_package_name)
165
- logging.info(f"[write_manifest_to_file] {package_name=}")
166
-
167
- imported_package = import_module(package_name)
168
- package_root_dir = Path(imported_package.__file__).parent
169
- manifest_path = (package_root_dir / MANIFEST_FILENAME).as_posix()
170
- logging.info(f"[write_manifest_to_file] {os.getcwd()=}")
171
- logging.info(f"[write_manifest_to_file] {package_root_dir=}")
172
- logging.info(f"[write_manifest_to_file] {manifest_path=}")
173
-
174
- with open(manifest_path, "w") as f:
175
- json.dump(manifest, f, indent=2)
176
- f.write("\n")
177
-
178
- logging.info("[write_manifest_to_file] END")
179
-
180
-
181
- def check_manifest(
182
- *,
183
- raw_package_name: str,
184
- manifest: str,
185
- ) -> None:
186
- """
187
- Write manifest to file.
188
-
189
- Arguments:
190
- raw_package_name:
191
- manifest: The manifest object
192
- """
193
-
194
- package_name = normalize_package_name(raw_package_name)
195
- logging.info(f"[check_manifest] {package_name=}")
196
-
197
- imported_package = import_module(package_name)
198
- package_root_dir = Path(imported_package.__file__).parent
199
- manifest_path = (package_root_dir / MANIFEST_FILENAME).as_posix()
200
- logging.info(f"[check_manifest] {os.getcwd()=}")
201
- logging.info(f"[check_manifest] {package_root_dir=}")
202
- logging.info(f"[check_manifest] {manifest_path=}")
203
-
204
- with open(manifest_path, "r") as f:
205
- old_manifest = json.load(f)
206
- if manifest == old_manifest:
207
- logging.info("[check_manifest] On-disk manifest is up to date.")
208
- else:
209
- logging.error("[check_manifest] On-disk manifest is not up to date.")
210
- print(json.dumps(old_manifest, indent=2))
211
- print(json.dumps(manifest, indent=2))
212
- sys.exit("New/old manifests differ")
213
-
214
- logging.info("[check_manifest] END")
@@ -0,0 +1,68 @@
1
+ from typing import Union
2
+
3
+
4
+ ValidType = Union[list, dict, str, int, float, bool, None]
5
+
6
+ MAX_RECURSION_LEVEL = 20
7
+
8
+
9
+ def deepdiff(
10
+ *,
11
+ old_object: ValidType,
12
+ new_object: ValidType,
13
+ path: str,
14
+ ignore_keys_order: bool,
15
+ recursion_level: int = 1,
16
+ ):
17
+ if type(old_object) is not type(new_object):
18
+ raise ValueError(
19
+ f"[{path}] Type difference:\n"
20
+ f"\tOld: {type(old_object)}\n\tNew:{type(new_object)}"
21
+ )
22
+
23
+ if type(old_object) not in [list, dict, str, int, float, bool, type(None)]:
24
+ raise ValueError(f"[{path}] Invalid type {type(old_object)}, exit.")
25
+
26
+ if recursion_level > MAX_RECURSION_LEVEL:
27
+ raise ValueError(f"Reached {MAX_RECURSION_LEVEL=}. Exit.")
28
+
29
+ if type(old_object) is dict:
30
+ old_keys = list(old_object.keys())
31
+ new_keys = list(new_object.keys())
32
+ if ignore_keys_order:
33
+ old_keys = sorted(old_keys)
34
+ new_keys = sorted(new_keys)
35
+ if old_keys != new_keys:
36
+ raise ValueError(
37
+ f"[{path}] Dictionaries have different keys:\n"
38
+ f"\tOld: {old_keys}\n\tNew: {new_keys}"
39
+ )
40
+
41
+ for key, value_a in old_object.items():
42
+ deepdiff(
43
+ old_object=value_a,
44
+ new_object=new_object[key],
45
+ path=f"{path}['{key}']",
46
+ ignore_keys_order=ignore_keys_order,
47
+ recursion_level=recursion_level + 1,
48
+ )
49
+ elif type(old_object) is list:
50
+ if len(old_object) != len(new_object):
51
+ raise ValueError(
52
+ f"{path} Lists have different lengths:\n"
53
+ f"\tOld:{len(old_object)}\n\tNew: {len(new_object)}"
54
+ )
55
+ for ind, item_a in enumerate(old_object):
56
+ deepdiff(
57
+ old_object=item_a,
58
+ new_object=new_object[ind],
59
+ path=f"{path}[{ind}]",
60
+ ignore_keys_order=ignore_keys_order,
61
+ recursion_level=recursion_level + 1,
62
+ )
63
+ else:
64
+ if old_object != new_object:
65
+ raise ValueError(
66
+ f"{path} Values are different:\n"
67
+ f"\tOld: '{old_object}'\n\tNew:'{new_object}'"
68
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fractal-task-tools
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: Shared tools for Fractal tasks
5
5
  Author-email: Tommaso Comparin <tommaso.comparin@exact-lab.it>
6
6
  License: BSD-3-Clause
@@ -1,7 +1,9 @@
1
- fractal_task_tools/__init__.py,sha256=oGZGTQhcn6qF_IOVf03TzaT2AMmZYyMmeCQK7snnOLA,79
1
+ fractal_task_tools/__init__.py,sha256=6mDzYc6ONWs6jFCx1ww0ZebQhqb6Sjw_rNkZFsdhupE,79
2
2
  fractal_task_tools/_args_schemas.py,sha256=Ka5IAAEdC7xg03ZHMl5jFbv4Sk8JR1QKbxFl7soevlQ,7829
3
- fractal_task_tools/_cli.py,sha256=6x2wWG6cFTw0m8HsxLmeboT3AMNf7ofhAI2kWEZMkx8,1849
4
- fractal_task_tools/_create_manifest.py,sha256=DTl1gV4XvQy_ArOAOSUzKLcTHYuE_un94dBvpfdkeeI,6922
3
+ fractal_task_tools/_cli.py,sha256=OULWSnI4_ziNWYoZWAiPQu2PgeQwJJRIh3wLkX2H7wA,2134
4
+ fractal_task_tools/_cli_tools.py,sha256=6G7zXvL6o5t7n4HvVAqP6an0o7qx5fEau5KjtoDXFuc,2622
5
+ fractal_task_tools/_create_manifest.py,sha256=p5Z7ZZy8EkwWGPZHsqfNtkmLEAmHfL5QDfuvqXWwWEY,4821
6
+ fractal_task_tools/_deepdiff.py,sha256=M3YZbAhZZx6iiAFvORZpxNENBpWmdEqkG29UJ7dFAcA,2239
5
7
  fractal_task_tools/_descriptions.py,sha256=n7WcoIBQ4FEd16BI26iL-Sh6bEQ76jlU32JfJBF4U0A,7566
6
8
  fractal_task_tools/_package_name_tools.py,sha256=_UT2cThh742V6M0XT9m0_aByhj5fXRSjATKt_MIXFVg,819
7
9
  fractal_task_tools/_pydantic_generatejsonschema.py,sha256=qZuID7YUXOdAcL8OqsWjNFNumOIAgdJillc1lA2cHIY,3136
@@ -10,9 +12,9 @@ fractal_task_tools/_task_docs.py,sha256=aEXozSKf3a7weOwJMHyTVJTvHlCKgDr1qoU-AAO3
10
12
  fractal_task_tools/_titles.py,sha256=GLWn-06fgQD6qzOM75H59EV0MMCXc8jVpHqGanYzNbw,3000
11
13
  fractal_task_tools/task_models.py,sha256=kgvEv5NQD8e8I9tyaFrnvxUxbKm6vH63r-cnID1jHE8,2269
12
14
  fractal_task_tools/task_wrapper.py,sha256=dhphKgxDm4EUxZnsrAy20hJPD6bGdqx7tNg9N_QzlCo,1878
13
- fractal_task_tools-0.0.6.dist-info/LICENSE,sha256=1SGAsQ3Jm_nIU7c2TgtTZe_IOKjm9BDsrcf2r98xrdk,1584
14
- fractal_task_tools-0.0.6.dist-info/METADATA,sha256=OCA3qxgE3rb_Yn3yUQz_qHT2PiHT4GybeJEtQhqu0SU,4208
15
- fractal_task_tools-0.0.6.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
16
- fractal_task_tools-0.0.6.dist-info/entry_points.txt,sha256=zE4qv7QhuiqN6DaPkmJV18X1xyYoUi0HIJ-uAg2M6TU,66
17
- fractal_task_tools-0.0.6.dist-info/top_level.txt,sha256=2VBpiMDIBMJGOEPiHHX3njYEZGLhr4L0nu8vfkcNVzw,19
18
- fractal_task_tools-0.0.6.dist-info/RECORD,,
15
+ fractal_task_tools-0.0.7.dist-info/LICENSE,sha256=1SGAsQ3Jm_nIU7c2TgtTZe_IOKjm9BDsrcf2r98xrdk,1584
16
+ fractal_task_tools-0.0.7.dist-info/METADATA,sha256=93L2GIU-i1gVuUE4IjAh-x1vgp-iHhWuIQRol1gucmk,4208
17
+ fractal_task_tools-0.0.7.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
18
+ fractal_task_tools-0.0.7.dist-info/entry_points.txt,sha256=zE4qv7QhuiqN6DaPkmJV18X1xyYoUi0HIJ-uAg2M6TU,66
19
+ fractal_task_tools-0.0.7.dist-info/top_level.txt,sha256=2VBpiMDIBMJGOEPiHHX3njYEZGLhr4L0nu8vfkcNVzw,19
20
+ fractal_task_tools-0.0.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (76.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5