siliconcompiler 0.35.2__py3-none-any.whl → 0.35.3__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.
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/smake.py +106 -100
- siliconcompiler/flowgraph.py +418 -129
- siliconcompiler/library.py +5 -4
- siliconcompiler/package/https.py +10 -5
- siliconcompiler/project.py +83 -32
- siliconcompiler/remote/client.py +17 -6
- siliconcompiler/scheduler/scheduler.py +204 -55
- siliconcompiler/scheduler/schedulernode.py +63 -70
- siliconcompiler/schema/__init__.py +3 -2
- siliconcompiler/schema/_metadata.py +1 -1
- siliconcompiler/schema/baseschema.py +205 -93
- siliconcompiler/schema/namedschema.py +21 -13
- siliconcompiler/schema/safeschema.py +18 -7
- siliconcompiler/schema_support/dependencyschema.py +4 -3
- siliconcompiler/schema_support/pathschema.py +7 -2
- siliconcompiler/schema_support/record.py +5 -4
- siliconcompiler/targets/asap7_demo.py +4 -1
- siliconcompiler/tool.py +9 -4
- siliconcompiler/tools/builtin/__init__.py +2 -0
- siliconcompiler/tools/builtin/filter.py +8 -1
- siliconcompiler/tools/builtin/importfiles.py +2 -0
- siliconcompiler/tools/klayout/scripts/klayout_show.py +1 -1
- siliconcompiler/tools/klayout/show.py +17 -5
- siliconcompiler/tools/yosys/prepareLib.py +7 -2
- siliconcompiler/tools/yosys/syn_asic.py +20 -2
- siliconcompiler/toolscripts/_tools.json +4 -4
- {siliconcompiler-0.35.2.dist-info → siliconcompiler-0.35.3.dist-info}/METADATA +2 -2
- {siliconcompiler-0.35.2.dist-info → siliconcompiler-0.35.3.dist-info}/RECORD +33 -33
- {siliconcompiler-0.35.2.dist-info → siliconcompiler-0.35.3.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.35.2.dist-info → siliconcompiler-0.35.3.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.35.2.dist-info → siliconcompiler-0.35.3.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.35.2.dist-info → siliconcompiler-0.35.3.dist-info}/top_level.txt +0 -0
|
@@ -24,14 +24,42 @@ except ModuleNotFoundError:
|
|
|
24
24
|
|
|
25
25
|
import os.path
|
|
26
26
|
|
|
27
|
+
from enum import Enum, auto
|
|
27
28
|
from functools import cache
|
|
28
|
-
from typing import Dict, Type, Tuple, Union, Set, Callable, List, Optional, TextIO, Iterable
|
|
29
|
+
from typing import Dict, Type, Tuple, Union, Set, Callable, List, Optional, TextIO, Iterable, Any
|
|
29
30
|
|
|
30
31
|
from .parameter import Parameter, NodeValue
|
|
31
32
|
from .journal import Journal
|
|
32
33
|
from ._metadata import version
|
|
33
34
|
|
|
34
35
|
|
|
36
|
+
class LazyLoad(Enum):
|
|
37
|
+
"""
|
|
38
|
+
Controls manifest loading
|
|
39
|
+
"""
|
|
40
|
+
OFF = auto() # load entire schema immediately
|
|
41
|
+
ON = auto() # store schema but do not load it
|
|
42
|
+
FORWARD = auto() # load the current section but do not load children
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def next(self) -> "LazyLoad":
|
|
46
|
+
"""
|
|
47
|
+
Returns the next state for lazy loading
|
|
48
|
+
"""
|
|
49
|
+
if self == LazyLoad.ON:
|
|
50
|
+
return LazyLoad.ON
|
|
51
|
+
if self == LazyLoad.FORWARD:
|
|
52
|
+
return LazyLoad.ON
|
|
53
|
+
return LazyLoad.OFF
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def is_enforced(self) -> bool:
|
|
57
|
+
"""
|
|
58
|
+
Returns true when the current section should not be loaded.
|
|
59
|
+
"""
|
|
60
|
+
return self == LazyLoad.ON
|
|
61
|
+
|
|
62
|
+
|
|
35
63
|
class BaseSchema:
|
|
36
64
|
'''
|
|
37
65
|
This class maintains the access and file IO operations for the schema.
|
|
@@ -42,21 +70,38 @@ class BaseSchema:
|
|
|
42
70
|
__version = tuple([int(v) for v in version.split('.')])
|
|
43
71
|
|
|
44
72
|
def __init__(self):
|
|
45
|
-
self.__manifest = {}
|
|
46
|
-
self.__default = None
|
|
47
|
-
self.__journal = Journal()
|
|
48
|
-
self.__parent =
|
|
49
|
-
self.__active = None
|
|
50
|
-
self.__key = None
|
|
73
|
+
self.__manifest: Dict[str, Union["BaseSchema", Parameter]] = {}
|
|
74
|
+
self.__default: Optional[Union["BaseSchema", Parameter]] = None
|
|
75
|
+
self.__journal: Journal = Journal()
|
|
76
|
+
self.__parent: Optional["BaseSchema"] = None
|
|
77
|
+
self.__active: Optional[Dict] = None
|
|
78
|
+
self.__key: Optional[str] = None
|
|
79
|
+
self.__lazy: Optional[Tuple[Optional[Tuple[int, ...]], Dict]] = None
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def __is_root(self) -> bool:
|
|
83
|
+
'''
|
|
84
|
+
Returns true if the object is the root of the schema
|
|
85
|
+
'''
|
|
86
|
+
try:
|
|
87
|
+
return self.__parent is None
|
|
88
|
+
except AttributeError:
|
|
89
|
+
return True
|
|
51
90
|
|
|
52
91
|
@property
|
|
53
92
|
def _keypath(self) -> Tuple[str, ...]:
|
|
54
93
|
'''
|
|
55
94
|
Returns the key to the current section of the schema
|
|
56
95
|
'''
|
|
57
|
-
if self.
|
|
96
|
+
if self.__is_root:
|
|
97
|
+
return tuple()
|
|
98
|
+
try:
|
|
99
|
+
parentpath = self.__parent._keypath
|
|
100
|
+
key = self.__key
|
|
101
|
+
except AttributeError:
|
|
102
|
+
# Guard against partially setup parents during serialization
|
|
58
103
|
return tuple()
|
|
59
|
-
return tuple([*
|
|
104
|
+
return tuple([*parentpath, key])
|
|
60
105
|
|
|
61
106
|
@staticmethod
|
|
62
107
|
@cache
|
|
@@ -146,13 +191,25 @@ class BaseSchema:
|
|
|
146
191
|
def __extractversion(manifest: Dict) -> Optional[Tuple[int, ...]]:
|
|
147
192
|
schema_version = manifest.get(BaseSchema._version_key, None)
|
|
148
193
|
if schema_version:
|
|
149
|
-
param = Parameter.from_dict(schema_version,
|
|
194
|
+
param = Parameter.from_dict(schema_version,
|
|
195
|
+
tuple([BaseSchema._version_key]),
|
|
196
|
+
None)
|
|
150
197
|
return tuple([int(v) for v in param.get().split('.')])
|
|
151
198
|
return None
|
|
152
199
|
|
|
200
|
+
def __ensure_lazy_elab(self):
|
|
201
|
+
if not self.__lazy:
|
|
202
|
+
return
|
|
203
|
+
|
|
204
|
+
version, manifest = self.__lazy
|
|
205
|
+
self.__lazy = None
|
|
206
|
+
|
|
207
|
+
self._from_dict(manifest, self._keypath, version=version, lazyload=LazyLoad.FORWARD)
|
|
208
|
+
|
|
153
209
|
def _from_dict(self, manifest: Dict,
|
|
154
210
|
keypath: Union[List[str], Tuple[str, ...]],
|
|
155
|
-
version: Optional[Tuple[int, ...]] = None
|
|
211
|
+
version: Optional[Tuple[int, ...]] = None,
|
|
212
|
+
lazyload: LazyLoad = LazyLoad.ON) \
|
|
156
213
|
-> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
|
|
157
214
|
'''
|
|
158
215
|
Decodes a dictionary into a schema object
|
|
@@ -174,26 +231,35 @@ class BaseSchema:
|
|
|
174
231
|
|
|
175
232
|
if "__journal__" in manifest:
|
|
176
233
|
self.__journal.from_dict(manifest["__journal__"])
|
|
177
|
-
|
|
234
|
+
if lazyload != LazyLoad.ON:
|
|
235
|
+
del manifest["__journal__"]
|
|
236
|
+
|
|
237
|
+
if lazyload == LazyLoad.ON:
|
|
238
|
+
self.__lazy = (version, manifest)
|
|
239
|
+
return set(), set()
|
|
178
240
|
|
|
179
241
|
if "__meta__" in manifest:
|
|
180
242
|
del manifest["__meta__"]
|
|
181
243
|
|
|
182
244
|
if self.__default:
|
|
183
|
-
data = manifest.
|
|
245
|
+
data = manifest.pop("default", None)
|
|
184
246
|
if data:
|
|
185
|
-
|
|
186
|
-
|
|
247
|
+
if isinstance(self.__default, BaseSchema):
|
|
248
|
+
self.__default._from_dict(data, tuple([*keypath, "default"]), version=version,
|
|
249
|
+
lazyload=lazyload.next)
|
|
250
|
+
else:
|
|
251
|
+
self.__default._from_dict(data, tuple([*keypath, "default"]), version=version)
|
|
187
252
|
handled.add("default")
|
|
188
253
|
|
|
189
254
|
for key, data in manifest.items():
|
|
255
|
+
data_keypath = tuple([*keypath, key])
|
|
190
256
|
obj = self.__manifest.get(key, None)
|
|
191
257
|
if not obj and isinstance(data, dict) and "__meta__" in data:
|
|
192
258
|
# Lookup object, use class first, then type
|
|
193
259
|
cls = BaseSchema.__process_meta_section(data["__meta__"])
|
|
194
260
|
if cls is BaseSchema and self.__default:
|
|
195
261
|
# Use default when BaseSchema is the class
|
|
196
|
-
obj = self.__default.copy(key=
|
|
262
|
+
obj = self.__default.copy(key=data_keypath)
|
|
197
263
|
self.__manifest[key] = obj
|
|
198
264
|
elif cls:
|
|
199
265
|
# Create object and connect to schema
|
|
@@ -204,11 +270,14 @@ class BaseSchema:
|
|
|
204
270
|
|
|
205
271
|
# Use default if it is available
|
|
206
272
|
if not obj and self.__default:
|
|
207
|
-
obj = self.__default.copy(key=
|
|
273
|
+
obj = self.__default.copy(key=data_keypath)
|
|
208
274
|
self.__manifest[key] = obj
|
|
209
275
|
|
|
210
276
|
if obj:
|
|
211
|
-
|
|
277
|
+
if isinstance(obj, BaseSchema):
|
|
278
|
+
obj._from_dict(data, data_keypath, version=version, lazyload=lazyload.next)
|
|
279
|
+
else:
|
|
280
|
+
obj._from_dict(data, data_keypath, version=version)
|
|
212
281
|
handled.add(key)
|
|
213
282
|
else:
|
|
214
283
|
missing.add(key)
|
|
@@ -219,7 +288,8 @@ class BaseSchema:
|
|
|
219
288
|
@classmethod
|
|
220
289
|
def from_manifest(cls,
|
|
221
290
|
filepath: Union[None, str] = None,
|
|
222
|
-
cfg: Union[None, Dict] = None
|
|
291
|
+
cfg: Union[None, Dict] = None,
|
|
292
|
+
lazyload: bool = True) -> "BaseSchema":
|
|
223
293
|
'''
|
|
224
294
|
Create a new schema based on the provided source files.
|
|
225
295
|
|
|
@@ -245,7 +315,12 @@ class BaseSchema:
|
|
|
245
315
|
else:
|
|
246
316
|
schema = cls()
|
|
247
317
|
|
|
248
|
-
|
|
318
|
+
if lazyload:
|
|
319
|
+
do_lazyload = LazyLoad.ON
|
|
320
|
+
else:
|
|
321
|
+
do_lazyload = LazyLoad.OFF
|
|
322
|
+
|
|
323
|
+
schema._from_dict(cfg, tuple(), lazyload=do_lazyload)
|
|
249
324
|
|
|
250
325
|
return schema
|
|
251
326
|
|
|
@@ -321,13 +396,19 @@ class BaseSchema:
|
|
|
321
396
|
insert_defaults: bool = False,
|
|
322
397
|
use_default: bool = False,
|
|
323
398
|
require_leaf: bool = True,
|
|
324
|
-
complete_path: Optional[List[str]] = None
|
|
399
|
+
complete_path: Optional[List[str]] = None,
|
|
400
|
+
elaborate_leaf: bool = True) -> Union["BaseSchema", Parameter]:
|
|
401
|
+
|
|
325
402
|
if len(keypath) == 0:
|
|
326
403
|
if require_leaf:
|
|
327
404
|
raise KeyError
|
|
328
405
|
else:
|
|
406
|
+
if elaborate_leaf:
|
|
407
|
+
self.__ensure_lazy_elab()
|
|
329
408
|
return self
|
|
330
409
|
|
|
410
|
+
self.__ensure_lazy_elab()
|
|
411
|
+
|
|
331
412
|
if complete_path is None:
|
|
332
413
|
complete_path = []
|
|
333
414
|
complete_path.append(keypath[0])
|
|
@@ -351,6 +432,8 @@ class BaseSchema:
|
|
|
351
432
|
if require_leaf:
|
|
352
433
|
raise KeyError
|
|
353
434
|
else:
|
|
435
|
+
if elaborate_leaf:
|
|
436
|
+
key_param.__ensure_lazy_elab()
|
|
354
437
|
return key_param
|
|
355
438
|
return key_param.__search(*keypath[1:],
|
|
356
439
|
insert_defaults=insert_defaults,
|
|
@@ -637,16 +720,13 @@ class BaseSchema:
|
|
|
637
720
|
>>> keylist = schema.getkeys('pdk')
|
|
638
721
|
Returns all keys for the [pdk] keypath.
|
|
639
722
|
"""
|
|
723
|
+
try:
|
|
724
|
+
key_param = self.__search(*keypath, require_leaf=False)
|
|
725
|
+
except KeyError:
|
|
726
|
+
raise KeyError(f"{self.__format_key(*keypath)} is not a valid keypath")
|
|
640
727
|
|
|
641
|
-
if
|
|
642
|
-
|
|
643
|
-
key_param = self.__search(*keypath, require_leaf=False)
|
|
644
|
-
except KeyError:
|
|
645
|
-
raise KeyError(f"{self.__format_key(*keypath)} is not a valid keypath")
|
|
646
|
-
if isinstance(key_param, Parameter):
|
|
647
|
-
return tuple()
|
|
648
|
-
else:
|
|
649
|
-
key_param = self
|
|
728
|
+
if isinstance(key_param, Parameter):
|
|
729
|
+
return tuple()
|
|
650
730
|
|
|
651
731
|
return tuple(sorted(key_param.__manifest.keys()))
|
|
652
732
|
|
|
@@ -658,14 +738,17 @@ class BaseSchema:
|
|
|
658
738
|
keypath (list of str): Keypath prefix to search under. The
|
|
659
739
|
returned keypaths do not include the prefix.
|
|
660
740
|
'''
|
|
741
|
+
try:
|
|
742
|
+
key_param = self.__search(*keypath, require_leaf=False)
|
|
743
|
+
except KeyError:
|
|
744
|
+
return set()
|
|
661
745
|
|
|
662
|
-
if
|
|
663
|
-
|
|
664
|
-
if not key_param or isinstance(key_param, Parameter):
|
|
665
|
-
return set()
|
|
666
|
-
return key_param.allkeys(*keypath[1:], include_default=include_default)
|
|
746
|
+
if isinstance(key_param, Parameter):
|
|
747
|
+
return set()
|
|
667
748
|
|
|
668
|
-
def add(keys,
|
|
749
|
+
def add(keys: List[Tuple[str, ...]],
|
|
750
|
+
key: str,
|
|
751
|
+
item: Union["BaseSchema", Parameter]) -> None:
|
|
669
752
|
if isinstance(item, Parameter):
|
|
670
753
|
keys.append((key,))
|
|
671
754
|
else:
|
|
@@ -673,9 +756,9 @@ class BaseSchema:
|
|
|
673
756
|
keys.append((key, *subkeypath))
|
|
674
757
|
|
|
675
758
|
keys = []
|
|
676
|
-
if include_default and
|
|
677
|
-
add(keys, "default",
|
|
678
|
-
for key, item in
|
|
759
|
+
if include_default and key_param.__default:
|
|
760
|
+
add(keys, "default", key_param.__default)
|
|
761
|
+
for key, item in key_param.__manifest.items():
|
|
679
762
|
add(keys, key, item)
|
|
680
763
|
return set(keys)
|
|
681
764
|
|
|
@@ -714,42 +797,52 @@ class BaseSchema:
|
|
|
714
797
|
>>> pdk = schema.getdict('pdk')
|
|
715
798
|
Returns the complete dictionary found for the keypath [pdk]
|
|
716
799
|
"""
|
|
800
|
+
try:
|
|
801
|
+
if not values_only and include_default:
|
|
802
|
+
key_param = self.__search(*keypath, require_leaf=False, elaborate_leaf=False)
|
|
717
803
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
804
|
+
if isinstance(key_param, Parameter):
|
|
805
|
+
return key_param.getdict(include_default=include_default,
|
|
806
|
+
values_only=values_only)
|
|
807
|
+
|
|
808
|
+
if key_param.__lazy:
|
|
809
|
+
return key_param.__lazy[1]
|
|
810
|
+
else:
|
|
811
|
+
key_param = self.__search(*keypath, require_leaf=False)
|
|
812
|
+
except KeyError:
|
|
813
|
+
return {}
|
|
814
|
+
|
|
815
|
+
if isinstance(key_param, Parameter):
|
|
816
|
+
return key_param.getdict(include_default=include_default, values_only=values_only)
|
|
725
817
|
|
|
726
818
|
manifest = {}
|
|
727
|
-
if include_default and
|
|
728
|
-
manifest_dict =
|
|
729
|
-
|
|
819
|
+
if include_default and key_param.__default:
|
|
820
|
+
manifest_dict = key_param.__default.getdict(include_default=include_default,
|
|
821
|
+
values_only=values_only)
|
|
730
822
|
if manifest_dict or not values_only:
|
|
731
823
|
manifest["default"] = manifest_dict
|
|
732
|
-
for key, item in
|
|
824
|
+
for key, item in key_param.__manifest.items():
|
|
733
825
|
manifest_dict = item.getdict(include_default=include_default,
|
|
734
826
|
values_only=values_only)
|
|
735
827
|
if manifest_dict or not values_only:
|
|
736
828
|
manifest[key] = manifest_dict
|
|
737
829
|
|
|
738
|
-
if not values_only and
|
|
739
|
-
manifest["__journal__"] =
|
|
830
|
+
if not values_only and key_param.__journal.has_journaling():
|
|
831
|
+
manifest["__journal__"] = key_param.__journal.get()
|
|
740
832
|
|
|
741
|
-
if not values_only and
|
|
833
|
+
if not values_only and key_param.__class__ is not BaseSchema:
|
|
742
834
|
manifest["__meta__"] = {}
|
|
743
835
|
|
|
744
836
|
try:
|
|
745
|
-
cls_meta =
|
|
837
|
+
cls_meta = key_param._getdict_meta()
|
|
746
838
|
manifest["__meta__"].update(cls_meta)
|
|
747
839
|
except NotImplementedError:
|
|
748
840
|
pass
|
|
749
841
|
|
|
750
|
-
manifest["__meta__"]["class"] =
|
|
842
|
+
manifest["__meta__"]["class"] = \
|
|
843
|
+
f"{key_param.__class__.__module__}/{key_param.__class__.__name__}"
|
|
751
844
|
try:
|
|
752
|
-
manifest["__meta__"]["sctype"] =
|
|
845
|
+
manifest["__meta__"]["sctype"] = key_param._getdict_type()
|
|
753
846
|
except NotImplementedError:
|
|
754
847
|
pass
|
|
755
848
|
|
|
@@ -768,11 +861,7 @@ class BaseSchema:
|
|
|
768
861
|
self.__parent = None
|
|
769
862
|
schema_copy = copy.deepcopy(self)
|
|
770
863
|
self.__parent = parent
|
|
771
|
-
|
|
772
|
-
if self is not self.__parent:
|
|
773
|
-
schema_copy.__parent = self.__parent
|
|
774
|
-
else:
|
|
775
|
-
schema_copy.__parent = schema_copy
|
|
864
|
+
schema_copy.__parent = self.__parent
|
|
776
865
|
|
|
777
866
|
if key:
|
|
778
867
|
schema_copy.__key = key[-1]
|
|
@@ -792,16 +881,20 @@ class BaseSchema:
|
|
|
792
881
|
"""
|
|
793
882
|
return []
|
|
794
883
|
|
|
795
|
-
def _find_files_dataroot_resolvers(self
|
|
884
|
+
def _find_files_dataroot_resolvers(self, resolvers: bool = False) \
|
|
885
|
+
-> Dict[str, Union[str, Callable]]:
|
|
796
886
|
"""
|
|
797
887
|
Returns a dictionary of path resolvers data directory handling for find_files
|
|
798
888
|
|
|
889
|
+
Args:
|
|
890
|
+
resolvers (bool, optional): Returns the resolvers instead of callables
|
|
891
|
+
|
|
799
892
|
Returns:
|
|
800
893
|
dictionary of str to resolver mapping
|
|
801
894
|
"""
|
|
802
|
-
if self.
|
|
895
|
+
if self.__is_root:
|
|
803
896
|
return {}
|
|
804
|
-
return self.__parent._find_files_dataroot_resolvers()
|
|
897
|
+
return self.__parent._find_files_dataroot_resolvers(resolvers=resolvers)
|
|
805
898
|
|
|
806
899
|
def _find_files(self, *keypath: str, missing_ok: bool = False,
|
|
807
900
|
step: Optional[str] = None, index: Optional[Union[int, str]] = None,
|
|
@@ -927,6 +1020,7 @@ class BaseSchema:
|
|
|
927
1020
|
search_paths = root_search_paths.copy()
|
|
928
1021
|
|
|
929
1022
|
dataroot: Optional[str] = path.get(field="dataroot")
|
|
1023
|
+
dataroot_except: Optional[Exception] = None
|
|
930
1024
|
if dataroot:
|
|
931
1025
|
if dataroot not in dataroots:
|
|
932
1026
|
raise ValueError(f"Resolver for {dataroot} not provided: "
|
|
@@ -935,7 +1029,10 @@ class BaseSchema:
|
|
|
935
1029
|
if isinstance(dataroot_path, str):
|
|
936
1030
|
search_paths.append(os.path.abspath(dataroot_path))
|
|
937
1031
|
elif callable(dataroot_path):
|
|
938
|
-
|
|
1032
|
+
try:
|
|
1033
|
+
search_paths.append(dataroot_path())
|
|
1034
|
+
except Exception as e:
|
|
1035
|
+
dataroot_except = e
|
|
939
1036
|
else:
|
|
940
1037
|
raise TypeError(f"Resolver for {dataroot} is not a recognized type: "
|
|
941
1038
|
f"{self.__format_key(*keypath)}")
|
|
@@ -956,6 +1053,10 @@ class BaseSchema:
|
|
|
956
1053
|
if not missing_ok:
|
|
957
1054
|
report_paths = ", ".join(search_paths)
|
|
958
1055
|
if dataroot:
|
|
1056
|
+
if dataroot_except:
|
|
1057
|
+
raise FileNotFoundError(
|
|
1058
|
+
f"Dataroot {dataroot} not found: {dataroot_except}") \
|
|
1059
|
+
from dataroot_except
|
|
959
1060
|
raise FileNotFoundError(
|
|
960
1061
|
f'Could not find "{path.get()}" in {dataroot} '
|
|
961
1062
|
f'{self.__format_key(*keypath)}: {report_paths}')
|
|
@@ -1036,7 +1137,7 @@ class BaseSchema:
|
|
|
1036
1137
|
node_indicator = f" ({step}/{index})"
|
|
1037
1138
|
|
|
1038
1139
|
name = ""
|
|
1039
|
-
if
|
|
1140
|
+
if hasattr(self, "name"):
|
|
1040
1141
|
name = f"({self.name}) "
|
|
1041
1142
|
|
|
1042
1143
|
logger.error(f"Parameter {name}"
|
|
@@ -1101,10 +1202,11 @@ class BaseSchema:
|
|
|
1101
1202
|
Args:
|
|
1102
1203
|
root (bool): if true, returns the root of the schemas.
|
|
1103
1204
|
'''
|
|
1205
|
+
if self.__is_root:
|
|
1206
|
+
return self
|
|
1207
|
+
|
|
1104
1208
|
if not root:
|
|
1105
1209
|
return self.__parent
|
|
1106
|
-
if self.__parent is self:
|
|
1107
|
-
return self
|
|
1108
1210
|
return self.__parent._parent(root=root)
|
|
1109
1211
|
|
|
1110
1212
|
@contextlib.contextmanager
|
|
@@ -1122,30 +1224,18 @@ class BaseSchema:
|
|
|
1122
1224
|
Sets the file to top.v and associates lambdalib as the dataroot.
|
|
1123
1225
|
'''
|
|
1124
1226
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
for key in subkeys:
|
|
1133
|
-
subschemas.add(self.get(*key, field="schema"))
|
|
1134
|
-
|
|
1135
|
-
orig_active = {}
|
|
1136
|
-
for schema in subschemas:
|
|
1137
|
-
if schema.__active:
|
|
1138
|
-
orig_active[schema] = schema.__active.copy()
|
|
1139
|
-
else:
|
|
1140
|
-
orig_active[schema] = None
|
|
1141
|
-
schema.__active = {}
|
|
1142
|
-
schema.__active.update(kwargs)
|
|
1227
|
+
if self.__active is None:
|
|
1228
|
+
orig_active = None
|
|
1229
|
+
self.__active = {}
|
|
1230
|
+
else:
|
|
1231
|
+
orig_active = self.__active.copy()
|
|
1232
|
+
|
|
1233
|
+
self.__active.update(kwargs)
|
|
1143
1234
|
|
|
1144
1235
|
try:
|
|
1145
1236
|
yield
|
|
1146
1237
|
finally:
|
|
1147
|
-
|
|
1148
|
-
schema.__active = orig
|
|
1238
|
+
self.__active = orig_active
|
|
1149
1239
|
|
|
1150
1240
|
def _get_active(self, field: str, defvalue=None):
|
|
1151
1241
|
'''
|
|
@@ -1156,20 +1246,42 @@ class BaseSchema:
|
|
|
1156
1246
|
otherwise the value, if the field is not present, defvalue is returned.
|
|
1157
1247
|
defvalue (any): value to return if the field is not present.
|
|
1158
1248
|
'''
|
|
1159
|
-
|
|
1249
|
+
actives = self.__get_active()
|
|
1250
|
+
if actives is None:
|
|
1160
1251
|
return defvalue
|
|
1161
1252
|
|
|
1162
1253
|
if field is None:
|
|
1163
|
-
return
|
|
1254
|
+
return actives
|
|
1255
|
+
|
|
1256
|
+
return actives.get(field, defvalue)
|
|
1257
|
+
|
|
1258
|
+
def __get_active(self) -> Optional[Dict[str, Any]]:
|
|
1259
|
+
'''
|
|
1260
|
+
Get the actives this point in the schema
|
|
1261
|
+
'''
|
|
1262
|
+
schemas: List["BaseSchema"] = [self]
|
|
1263
|
+
|
|
1264
|
+
root = self._parent(root=True)
|
|
1265
|
+
curr = schemas[-1]
|
|
1266
|
+
while curr is not root:
|
|
1267
|
+
schemas.append(curr._parent())
|
|
1268
|
+
curr = schemas[-1]
|
|
1164
1269
|
|
|
1165
|
-
|
|
1270
|
+
active = {}
|
|
1271
|
+
for schema in reversed(schemas):
|
|
1272
|
+
if schema.__active:
|
|
1273
|
+
active.update(schema.__active)
|
|
1274
|
+
if not active:
|
|
1275
|
+
return None
|
|
1276
|
+
return active
|
|
1166
1277
|
|
|
1167
1278
|
def __process_active(self, param: Parameter,
|
|
1168
1279
|
nodevalues: Optional[Union[List[NodeValue],
|
|
1169
1280
|
Set[NodeValue],
|
|
1170
1281
|
Tuple[NodeValue, ...],
|
|
1171
1282
|
NodeValue]]) -> None:
|
|
1172
|
-
|
|
1283
|
+
actives = self.__get_active()
|
|
1284
|
+
if actives is None:
|
|
1173
1285
|
return
|
|
1174
1286
|
|
|
1175
1287
|
if not isinstance(nodevalues, (list, set, tuple)):
|
|
@@ -1184,7 +1296,7 @@ class BaseSchema:
|
|
|
1184
1296
|
|
|
1185
1297
|
key_fields = ("copy", "lock")
|
|
1186
1298
|
|
|
1187
|
-
for field, value in
|
|
1299
|
+
for field, value in actives.items():
|
|
1188
1300
|
if field in key_fields:
|
|
1189
1301
|
param.set(value, field=field)
|
|
1190
1302
|
continue
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
from typing import Dict, Tuple, Optional, Set, Union, List
|
|
8
8
|
|
|
9
|
-
from .baseschema import BaseSchema
|
|
9
|
+
from .baseschema import BaseSchema, LazyLoad
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class NamedSchema(BaseSchema):
|
|
@@ -71,10 +71,17 @@ class NamedSchema(BaseSchema):
|
|
|
71
71
|
info["name"] = self.name
|
|
72
72
|
return info
|
|
73
73
|
|
|
74
|
+
@staticmethod
|
|
75
|
+
def __get_meta_name(cfg: Optional[Dict]) -> Optional[str]:
|
|
76
|
+
if not cfg:
|
|
77
|
+
return None
|
|
78
|
+
return cfg.get("__meta__", {}).get("name", None)
|
|
79
|
+
|
|
74
80
|
@classmethod
|
|
75
81
|
def from_manifest(cls,
|
|
76
82
|
filepath: Union[None, str] = None,
|
|
77
83
|
cfg: Union[None, Dict] = None,
|
|
84
|
+
lazyload: bool = True,
|
|
78
85
|
name: Optional[str] = None):
|
|
79
86
|
'''
|
|
80
87
|
Create a new schema based on the provided source files.
|
|
@@ -86,28 +93,29 @@ class NamedSchema(BaseSchema):
|
|
|
86
93
|
cfg (dict): Initial configuration dictionary.
|
|
87
94
|
name (str): name of the schema.
|
|
88
95
|
'''
|
|
96
|
+
if filepath and not cfg:
|
|
97
|
+
cfg = BaseSchema._read_manifest(filepath)
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
meta_name = NamedSchema.__get_meta_name(cfg)
|
|
100
|
+
schema = super().from_manifest(filepath=None, cfg=cfg, lazyload=lazyload)
|
|
101
|
+
if name:
|
|
102
|
+
schema.__name = name
|
|
103
|
+
elif meta_name:
|
|
104
|
+
schema.__name = meta_name
|
|
92
105
|
|
|
93
|
-
schema = cls()
|
|
94
|
-
schema.set_name(name)
|
|
95
|
-
if filepath:
|
|
96
|
-
schema.read_manifest(filepath)
|
|
97
|
-
if cfg:
|
|
98
|
-
schema._from_dict(cfg, tuple())
|
|
99
106
|
return schema
|
|
100
107
|
|
|
101
108
|
def _from_dict(self, manifest: Dict,
|
|
102
109
|
keypath: Union[List[str], Tuple[str, ...]],
|
|
103
|
-
version: Optional[Tuple[int, ...]] = None
|
|
110
|
+
version: Optional[Tuple[int, ...]] = None,
|
|
111
|
+
lazyload: LazyLoad = LazyLoad.ON) \
|
|
104
112
|
-> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
|
|
105
113
|
if keypath:
|
|
106
114
|
self.__name = keypath[-1]
|
|
107
|
-
elif not self.__name
|
|
108
|
-
self.__name = manifest
|
|
115
|
+
elif not self.__name:
|
|
116
|
+
self.__name = NamedSchema.__get_meta_name(manifest)
|
|
109
117
|
|
|
110
|
-
return super()._from_dict(manifest, keypath, version=version)
|
|
118
|
+
return super()._from_dict(manifest, keypath, version=version, lazyload=lazyload)
|
|
111
119
|
|
|
112
120
|
def copy(self, key: Optional[Tuple[str, ...]] = None) -> "NamedSchema":
|
|
113
121
|
copy: NamedSchema = super().copy(key=key)
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
from typing import Dict, Tuple, Optional, Union, List, Set
|
|
8
8
|
|
|
9
9
|
from .parameter import Parameter
|
|
10
|
-
from .baseschema import BaseSchema
|
|
10
|
+
from .baseschema import BaseSchema, LazyLoad
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class SafeSchema(BaseSchema):
|
|
@@ -35,7 +35,8 @@ class SafeSchema(BaseSchema):
|
|
|
35
35
|
|
|
36
36
|
def _from_dict(self, manifest: Dict,
|
|
37
37
|
keypath: Union[List[str], Tuple[str, ...]],
|
|
38
|
-
version: Optional[Tuple[int, ...]] = None
|
|
38
|
+
version: Optional[Tuple[int, ...]] = None,
|
|
39
|
+
lazyload: LazyLoad = LazyLoad.OFF) \
|
|
39
40
|
-> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
|
|
40
41
|
if not isinstance(manifest, dict):
|
|
41
42
|
return set(), set()
|
|
@@ -43,11 +44,13 @@ class SafeSchema(BaseSchema):
|
|
|
43
44
|
if "__meta__" in manifest:
|
|
44
45
|
del manifest["__meta__"]
|
|
45
46
|
|
|
47
|
+
lazyload = LazyLoad.OFF
|
|
48
|
+
|
|
46
49
|
for key, data in manifest.items():
|
|
47
50
|
obj = SafeSchema.__is_dict_leaf(data, list(keypath) + [key], version)
|
|
48
51
|
if not obj:
|
|
49
52
|
obj = SafeSchema()
|
|
50
|
-
obj._from_dict(data, list(keypath) + [key], version)
|
|
53
|
+
obj._from_dict(data, list(keypath) + [key], version=version, lazyload=lazyload)
|
|
51
54
|
|
|
52
55
|
if key == "default":
|
|
53
56
|
self._BaseSchema__default = obj
|
|
@@ -59,11 +62,19 @@ class SafeSchema(BaseSchema):
|
|
|
59
62
|
@classmethod
|
|
60
63
|
def from_manifest(cls,
|
|
61
64
|
filepath: Union[None, str] = None,
|
|
62
|
-
cfg: Union[None, Dict] = None
|
|
65
|
+
cfg: Union[None, Dict] = None,
|
|
66
|
+
lazyload: bool = False) -> "SafeSchema":
|
|
63
67
|
if filepath:
|
|
64
68
|
cfg = BaseSchema._read_manifest(filepath)
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
70
|
+
def rm_meta(manifest):
|
|
71
|
+
if not isinstance(manifest, dict):
|
|
72
|
+
return
|
|
73
|
+
if manifest and "__meta__" in manifest:
|
|
74
|
+
del manifest["__meta__"]
|
|
75
|
+
for section in manifest.values():
|
|
76
|
+
rm_meta(section)
|
|
77
|
+
|
|
78
|
+
rm_meta(cfg)
|
|
68
79
|
|
|
69
|
-
return super().from_manifest(filepath=None, cfg=cfg)
|
|
80
|
+
return super().from_manifest(filepath=None, cfg=cfg, lazyload=False)
|