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.
- fractal_task_tools/__init__.py +1 -1
- fractal_task_tools/_cli.py +13 -2
- fractal_task_tools/_cli_tools.py +86 -0
- fractal_task_tools/_create_manifest.py +2 -73
- fractal_task_tools/_deepdiff.py +68 -0
- {fractal_task_tools-0.0.6.dist-info → fractal_task_tools-0.0.7.dist-info}/METADATA +1 -1
- {fractal_task_tools-0.0.6.dist-info → fractal_task_tools-0.0.7.dist-info}/RECORD +11 -9
- {fractal_task_tools-0.0.6.dist-info → fractal_task_tools-0.0.7.dist-info}/WHEEL +1 -1
- {fractal_task_tools-0.0.6.dist-info → fractal_task_tools-0.0.7.dist-info}/LICENSE +0 -0
- {fractal_task_tools-0.0.6.dist-info → fractal_task_tools-0.0.7.dist-info}/entry_points.txt +0 -0
- {fractal_task_tools-0.0.6.dist-info → fractal_task_tools-0.0.7.dist-info}/top_level.txt +0 -0
fractal_task_tools/__init__.py
CHANGED
fractal_task_tools/_cli.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import argparse as ap
|
|
2
2
|
import sys
|
|
3
3
|
|
|
4
|
-
from fractal_task_tools.
|
|
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
|
-
|
|
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,7 +1,9 @@
|
|
|
1
|
-
fractal_task_tools/__init__.py,sha256=
|
|
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=
|
|
4
|
-
fractal_task_tools/
|
|
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.
|
|
14
|
-
fractal_task_tools-0.0.
|
|
15
|
-
fractal_task_tools-0.0.
|
|
16
|
-
fractal_task_tools-0.0.
|
|
17
|
-
fractal_task_tools-0.0.
|
|
18
|
-
fractal_task_tools-0.0.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|