siliconcompiler 0.34.1__py3-none-any.whl → 0.34.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/__init__.py +23 -4
- siliconcompiler/__main__.py +1 -7
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/_common.py +104 -23
- siliconcompiler/apps/sc.py +4 -8
- siliconcompiler/apps/sc_dashboard.py +6 -4
- siliconcompiler/apps/sc_install.py +10 -6
- siliconcompiler/apps/sc_issue.py +7 -5
- siliconcompiler/apps/sc_remote.py +1 -1
- siliconcompiler/apps/sc_server.py +9 -14
- siliconcompiler/apps/sc_show.py +7 -6
- siliconcompiler/apps/smake.py +130 -94
- siliconcompiler/apps/utils/replay.py +4 -7
- siliconcompiler/apps/utils/summarize.py +3 -5
- siliconcompiler/asic.py +420 -0
- siliconcompiler/checklist.py +25 -2
- siliconcompiler/cmdlineschema.py +534 -0
- siliconcompiler/constraints/__init__.py +17 -0
- siliconcompiler/constraints/asic_component.py +378 -0
- siliconcompiler/constraints/asic_floorplan.py +449 -0
- siliconcompiler/constraints/asic_pins.py +489 -0
- siliconcompiler/constraints/asic_timing.py +517 -0
- siliconcompiler/core.py +10 -35
- siliconcompiler/data/templates/tcl/manifest.tcl.j2 +8 -0
- siliconcompiler/dependencyschema.py +96 -202
- siliconcompiler/design.py +327 -241
- siliconcompiler/filesetschema.py +250 -0
- siliconcompiler/flowgraph.py +298 -106
- siliconcompiler/fpga.py +124 -1
- siliconcompiler/library.py +331 -0
- siliconcompiler/metric.py +327 -92
- siliconcompiler/metrics/__init__.py +7 -0
- siliconcompiler/metrics/asic.py +245 -0
- siliconcompiler/metrics/fpga.py +220 -0
- siliconcompiler/package/__init__.py +391 -67
- siliconcompiler/package/git.py +92 -16
- siliconcompiler/package/github.py +114 -22
- siliconcompiler/package/https.py +79 -16
- siliconcompiler/packageschema.py +341 -16
- siliconcompiler/pathschema.py +255 -0
- siliconcompiler/pdk.py +566 -1
- siliconcompiler/project.py +1460 -0
- siliconcompiler/record.py +38 -1
- siliconcompiler/remote/__init__.py +5 -2
- siliconcompiler/remote/client.py +11 -6
- siliconcompiler/remote/schema.py +5 -23
- siliconcompiler/remote/server.py +41 -54
- siliconcompiler/report/__init__.py +3 -3
- siliconcompiler/report/dashboard/__init__.py +48 -14
- siliconcompiler/report/dashboard/cli/__init__.py +99 -21
- siliconcompiler/report/dashboard/cli/board.py +364 -179
- siliconcompiler/report/dashboard/web/__init__.py +90 -12
- siliconcompiler/report/dashboard/web/components/__init__.py +219 -240
- siliconcompiler/report/dashboard/web/components/flowgraph.py +49 -26
- siliconcompiler/report/dashboard/web/components/graph.py +139 -100
- siliconcompiler/report/dashboard/web/layouts/__init__.py +29 -1
- siliconcompiler/report/dashboard/web/layouts/_common.py +38 -2
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph.py +39 -26
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_node_tab.py +50 -50
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_sac_tabs.py +49 -46
- siliconcompiler/report/dashboard/web/state.py +141 -14
- siliconcompiler/report/dashboard/web/utils/__init__.py +79 -16
- siliconcompiler/report/dashboard/web/utils/file_utils.py +74 -11
- siliconcompiler/report/dashboard/web/viewer.py +25 -1
- siliconcompiler/report/report.py +5 -2
- siliconcompiler/report/summary_image.py +29 -11
- siliconcompiler/scheduler/__init__.py +9 -1
- siliconcompiler/scheduler/docker.py +81 -4
- siliconcompiler/scheduler/run_node.py +37 -20
- siliconcompiler/scheduler/scheduler.py +211 -36
- siliconcompiler/scheduler/schedulernode.py +394 -60
- siliconcompiler/scheduler/send_messages.py +77 -29
- siliconcompiler/scheduler/slurm.py +76 -12
- siliconcompiler/scheduler/taskscheduler.py +142 -21
- siliconcompiler/schema/__init__.py +0 -4
- siliconcompiler/schema/baseschema.py +338 -59
- siliconcompiler/schema/editableschema.py +14 -6
- siliconcompiler/schema/journal.py +28 -17
- siliconcompiler/schema/namedschema.py +22 -14
- siliconcompiler/schema/parameter.py +89 -28
- siliconcompiler/schema/parametertype.py +2 -0
- siliconcompiler/schema/parametervalue.py +258 -15
- siliconcompiler/schema/safeschema.py +25 -2
- siliconcompiler/schema/schema_cfg.py +23 -19
- siliconcompiler/schema/utils.py +2 -2
- siliconcompiler/schema_obj.py +24 -5
- siliconcompiler/tool.py +1131 -265
- siliconcompiler/tools/bambu/__init__.py +41 -0
- siliconcompiler/tools/builtin/concatenate.py +2 -2
- siliconcompiler/tools/builtin/minimum.py +2 -1
- siliconcompiler/tools/builtin/mux.py +2 -1
- siliconcompiler/tools/builtin/nop.py +2 -1
- siliconcompiler/tools/builtin/verify.py +2 -1
- siliconcompiler/tools/klayout/__init__.py +95 -0
- siliconcompiler/tools/openroad/__init__.py +289 -0
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +3 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +7 -2
- siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +8 -4
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +9 -5
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +5 -1
- siliconcompiler/tools/slang/__init__.py +1 -1
- siliconcompiler/tools/slang/elaborate.py +2 -1
- siliconcompiler/tools/vivado/scripts/sc_run.tcl +1 -1
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +8 -1
- siliconcompiler/tools/vivado/syn_fpga.py +6 -0
- siliconcompiler/tools/vivado/vivado.py +35 -2
- siliconcompiler/tools/vpr/__init__.py +150 -0
- siliconcompiler/tools/yosys/__init__.py +369 -1
- siliconcompiler/tools/yosys/scripts/procs.tcl +0 -1
- siliconcompiler/toolscripts/_tools.json +5 -10
- siliconcompiler/utils/__init__.py +66 -0
- siliconcompiler/utils/flowgraph.py +2 -2
- siliconcompiler/utils/issue.py +2 -1
- siliconcompiler/utils/logging.py +14 -0
- siliconcompiler/utils/multiprocessing.py +256 -0
- siliconcompiler/utils/showtools.py +10 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/METADATA +6 -6
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/RECORD +122 -115
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/entry_points.txt +3 -0
- siliconcompiler/schema/cmdlineschema.py +0 -250
- siliconcompiler/schema/packageschema.py +0 -101
- siliconcompiler/toolscripts/rhel8/install-slang.sh +0 -40
- siliconcompiler/toolscripts/rhel9/install-slang.sh +0 -40
- siliconcompiler/toolscripts/ubuntu20/install-slang.sh +0 -47
- siliconcompiler/toolscripts/ubuntu22/install-slang.sh +0 -37
- siliconcompiler/toolscripts/ubuntu24/install-slang.sh +0 -37
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/top_level.txt +0 -0
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
from .parameter import Parameter
|
|
8
8
|
from .baseschema import BaseSchema
|
|
9
9
|
|
|
10
|
+
from typing import Union, Tuple
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
class EditableSchema:
|
|
12
14
|
'''
|
|
@@ -17,11 +19,15 @@ class EditableSchema:
|
|
|
17
19
|
schema (:class:`BaseSchema`): schema to modify
|
|
18
20
|
'''
|
|
19
21
|
|
|
20
|
-
def __init__(self, schema):
|
|
22
|
+
def __init__(self, schema: BaseSchema):
|
|
21
23
|
# Grab manifest from base class
|
|
22
24
|
self.__schema = schema
|
|
23
25
|
|
|
24
|
-
def __insert(self,
|
|
26
|
+
def __insert(self,
|
|
27
|
+
keypath: Tuple[str],
|
|
28
|
+
value: Union[BaseSchema, Parameter],
|
|
29
|
+
fullkey: Tuple[str],
|
|
30
|
+
clobber: bool) -> None:
|
|
25
31
|
key = keypath[0]
|
|
26
32
|
keypath = keypath[1:]
|
|
27
33
|
|
|
@@ -31,6 +37,7 @@ class EditableSchema:
|
|
|
31
37
|
|
|
32
38
|
if isinstance(value, BaseSchema):
|
|
33
39
|
value._BaseSchema__parent = self.__schema
|
|
40
|
+
value._BaseSchema__key = key
|
|
34
41
|
|
|
35
42
|
if key == "default":
|
|
36
43
|
self.__schema._BaseSchema__default = value
|
|
@@ -47,9 +54,10 @@ class EditableSchema:
|
|
|
47
54
|
self.__schema._BaseSchema__default = new_schema
|
|
48
55
|
else:
|
|
49
56
|
new_schema = self.__schema._BaseSchema__manifest.setdefault(key, new_schema)
|
|
57
|
+
new_schema._BaseSchema__key = key
|
|
50
58
|
EditableSchema(new_schema).__insert(keypath, value, fullkey, clobber)
|
|
51
59
|
|
|
52
|
-
def __remove(self, keypath, fullkey):
|
|
60
|
+
def __remove(self, keypath: Tuple[str], fullkey: Tuple[str]) -> None:
|
|
53
61
|
key = keypath[0]
|
|
54
62
|
keypath = keypath[1:]
|
|
55
63
|
|
|
@@ -69,7 +77,7 @@ class EditableSchema:
|
|
|
69
77
|
else:
|
|
70
78
|
EditableSchema(next_param).__remove(keypath, fullkey)
|
|
71
79
|
|
|
72
|
-
def insert(self, *args, clobber=False):
|
|
80
|
+
def insert(self, *args, clobber: bool = False) -> None:
|
|
73
81
|
'''
|
|
74
82
|
Inserts a :class:`Parameter` or a :class:`BaseSchema` to the schema,
|
|
75
83
|
based on the keypath and value provided in the ``*args``.
|
|
@@ -98,7 +106,7 @@ class EditableSchema:
|
|
|
98
106
|
|
|
99
107
|
self.__insert(keypath, value, keypath, clobber=clobber)
|
|
100
108
|
|
|
101
|
-
def remove(self, *keypath):
|
|
109
|
+
def remove(self, *keypath: str) -> None:
|
|
102
110
|
'''
|
|
103
111
|
Removes a keypath from the schema.
|
|
104
112
|
|
|
@@ -118,7 +126,7 @@ class EditableSchema:
|
|
|
118
126
|
|
|
119
127
|
self.__remove(keypath, keypath)
|
|
120
128
|
|
|
121
|
-
def search(self, *keypath):
|
|
129
|
+
def search(self, *keypath: str) -> Union[BaseSchema, Parameter]:
|
|
122
130
|
'''
|
|
123
131
|
Finds an item in the schema. This will raise a KeyError if
|
|
124
132
|
the path is not found.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
|
+
from typing import Tuple, Set, Dict, List
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
class Journal:
|
|
6
8
|
"""
|
|
@@ -12,7 +14,7 @@ class Journal:
|
|
|
12
14
|
keyprefix (list of str): keypath to prefix on to recorded path
|
|
13
15
|
"""
|
|
14
16
|
|
|
15
|
-
def __init__(self, keyprefix=None):
|
|
17
|
+
def __init__(self, keyprefix: Tuple[str] = None):
|
|
16
18
|
if not keyprefix:
|
|
17
19
|
self.__keyprefix = tuple()
|
|
18
20
|
else:
|
|
@@ -24,14 +26,14 @@ class Journal:
|
|
|
24
26
|
self.stop()
|
|
25
27
|
|
|
26
28
|
@property
|
|
27
|
-
def keypath(self):
|
|
29
|
+
def keypath(self) -> Tuple[str]:
|
|
28
30
|
'''
|
|
29
31
|
Returns the reference key path for this journal
|
|
30
32
|
'''
|
|
31
33
|
|
|
32
34
|
return self.__keyprefix
|
|
33
35
|
|
|
34
|
-
def get_child(self, *keypath):
|
|
36
|
+
def get_child(self, *keypath: Tuple[str]):
|
|
35
37
|
'''
|
|
36
38
|
Get a child journal based on a new keypath
|
|
37
39
|
|
|
@@ -43,7 +45,7 @@ class Journal:
|
|
|
43
45
|
child.__parent = self.__parent
|
|
44
46
|
return child
|
|
45
47
|
|
|
46
|
-
def from_dict(self, manifest):
|
|
48
|
+
def from_dict(self, manifest: Dict):
|
|
47
49
|
'''
|
|
48
50
|
Import a journal from a manifest dictionary
|
|
49
51
|
|
|
@@ -53,33 +55,33 @@ class Journal:
|
|
|
53
55
|
|
|
54
56
|
self.__journal = manifest
|
|
55
57
|
|
|
56
|
-
def get(self):
|
|
58
|
+
def get(self) -> List[Dict]:
|
|
57
59
|
"""
|
|
58
60
|
Returns a copy of the current journal
|
|
59
61
|
"""
|
|
60
62
|
|
|
61
63
|
return copy.deepcopy(self.__parent.__journal)
|
|
62
64
|
|
|
63
|
-
def has_journaling(self):
|
|
65
|
+
def has_journaling(self) -> bool:
|
|
64
66
|
"""
|
|
65
67
|
Returns true if the schema is currently setup and is the root of the journal and has data
|
|
66
68
|
"""
|
|
67
69
|
return self is self.__parent and bool(self.__journal)
|
|
68
70
|
|
|
69
|
-
def is_journaling(self):
|
|
71
|
+
def is_journaling(self) -> bool:
|
|
70
72
|
"""
|
|
71
73
|
Returns true if the schema is currently setup for journaling
|
|
72
74
|
"""
|
|
73
75
|
return self.__parent.__journal is not None
|
|
74
76
|
|
|
75
|
-
def get_types(self):
|
|
77
|
+
def get_types(self) -> Set[str]:
|
|
76
78
|
"""
|
|
77
79
|
Returns the current schema accesses that are being recorded
|
|
78
80
|
"""
|
|
79
81
|
|
|
80
82
|
return self.__parent.__record_types.copy()
|
|
81
83
|
|
|
82
|
-
def add_type(self, value):
|
|
84
|
+
def add_type(self, value: str) -> None:
|
|
83
85
|
"""
|
|
84
86
|
Adds a new access type to the journal record.
|
|
85
87
|
|
|
@@ -90,9 +92,9 @@ class Journal:
|
|
|
90
92
|
if value not in ("set", "add", "remove", "unset", "get"):
|
|
91
93
|
raise ValueError(f"{value} is not a valid type")
|
|
92
94
|
|
|
93
|
-
|
|
95
|
+
self.__parent.__record_types.add(value)
|
|
94
96
|
|
|
95
|
-
def remove_type(self, value):
|
|
97
|
+
def remove_type(self, value: str) -> None:
|
|
96
98
|
"""
|
|
97
99
|
Removes a new access type to the journal record.
|
|
98
100
|
|
|
@@ -105,7 +107,13 @@ class Journal:
|
|
|
105
107
|
except KeyError:
|
|
106
108
|
pass
|
|
107
109
|
|
|
108
|
-
def record(self,
|
|
110
|
+
def record(self,
|
|
111
|
+
record_type: str,
|
|
112
|
+
key: Tuple[str],
|
|
113
|
+
value=None,
|
|
114
|
+
field: str = None,
|
|
115
|
+
step: str = None,
|
|
116
|
+
index: str = None) -> None:
|
|
109
117
|
'''
|
|
110
118
|
Record the schema transaction
|
|
111
119
|
'''
|
|
@@ -116,6 +124,9 @@ class Journal:
|
|
|
116
124
|
if record_type not in self.__parent.__record_types:
|
|
117
125
|
return
|
|
118
126
|
|
|
127
|
+
if isinstance(value, set):
|
|
128
|
+
value = list(value)
|
|
129
|
+
|
|
119
130
|
self.__parent.__journal.append({
|
|
120
131
|
"type": record_type,
|
|
121
132
|
"key": tuple([*self.__keyprefix, *key]),
|
|
@@ -125,7 +136,7 @@ class Journal:
|
|
|
125
136
|
"index": index
|
|
126
137
|
})
|
|
127
138
|
|
|
128
|
-
def start(self):
|
|
139
|
+
def start(self) -> None:
|
|
129
140
|
'''
|
|
130
141
|
Start journaling the schema transactions
|
|
131
142
|
'''
|
|
@@ -135,7 +146,7 @@ class Journal:
|
|
|
135
146
|
self.add_type("remove")
|
|
136
147
|
self.add_type("unset")
|
|
137
148
|
|
|
138
|
-
def stop(self):
|
|
149
|
+
def stop(self) -> None:
|
|
139
150
|
'''
|
|
140
151
|
Stop journaling the schema transactions
|
|
141
152
|
'''
|
|
@@ -143,7 +154,7 @@ class Journal:
|
|
|
143
154
|
self.__parent.__record_types.clear()
|
|
144
155
|
|
|
145
156
|
@staticmethod
|
|
146
|
-
def replay_file(schema, filepath):
|
|
157
|
+
def replay_file(schema, filepath: str) -> None:
|
|
147
158
|
'''
|
|
148
159
|
Replay a journal into a schema from a manifest
|
|
149
160
|
|
|
@@ -160,7 +171,7 @@ class Journal:
|
|
|
160
171
|
journal.from_dict(data["__journal__"])
|
|
161
172
|
journal.replay(schema)
|
|
162
173
|
|
|
163
|
-
def replay(self, schema):
|
|
174
|
+
def replay(self, schema) -> None:
|
|
164
175
|
'''
|
|
165
176
|
Replay journal into a schema
|
|
166
177
|
|
|
@@ -196,7 +207,7 @@ class Journal:
|
|
|
196
207
|
raise ValueError(f'Unknown record type {record_type}')
|
|
197
208
|
|
|
198
209
|
@staticmethod
|
|
199
|
-
def access(schema):
|
|
210
|
+
def access(schema) -> "Journal":
|
|
200
211
|
'''
|
|
201
212
|
Access a journal from a schema
|
|
202
213
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
# SC dependencies outside of its directory, since it may be used by tool drivers
|
|
5
5
|
# that have isolated Python environments.
|
|
6
6
|
|
|
7
|
+
from typing import Dict, Tuple
|
|
8
|
+
|
|
7
9
|
from .baseschema import BaseSchema
|
|
8
10
|
|
|
9
11
|
|
|
@@ -15,12 +17,13 @@ class NamedSchema(BaseSchema):
|
|
|
15
17
|
name (str): name of the schema
|
|
16
18
|
'''
|
|
17
19
|
|
|
18
|
-
def __init__(self, name=None):
|
|
20
|
+
def __init__(self, name: str = None):
|
|
19
21
|
super().__init__()
|
|
20
22
|
|
|
21
|
-
self.
|
|
23
|
+
self.set_name(name)
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
@property
|
|
26
|
+
def name(self) -> str:
|
|
24
27
|
'''
|
|
25
28
|
Returns the name of the schema
|
|
26
29
|
'''
|
|
@@ -29,7 +32,7 @@ class NamedSchema(BaseSchema):
|
|
|
29
32
|
except AttributeError:
|
|
30
33
|
return None
|
|
31
34
|
|
|
32
|
-
def set_name(self, name):
|
|
35
|
+
def set_name(self, name: str) -> None:
|
|
33
36
|
"""
|
|
34
37
|
Set the name of this object
|
|
35
38
|
|
|
@@ -40,24 +43,28 @@ class NamedSchema(BaseSchema):
|
|
|
40
43
|
name (str): name for object
|
|
41
44
|
"""
|
|
42
45
|
|
|
43
|
-
if self.name
|
|
46
|
+
if self.name is not None:
|
|
44
47
|
raise RuntimeError("Cannot call set_name more than once.")
|
|
48
|
+
if name is not None and "." in name:
|
|
49
|
+
raise ValueError("Named schema object cannot contains: .")
|
|
45
50
|
self.__name = name
|
|
46
51
|
|
|
47
|
-
def
|
|
52
|
+
def type(self) -> str:
|
|
48
53
|
"""
|
|
49
|
-
|
|
54
|
+
Returns the type of this object
|
|
50
55
|
"""
|
|
51
|
-
|
|
56
|
+
raise NotImplementedError("Must be implemented by the child classes.")
|
|
52
57
|
|
|
53
|
-
|
|
58
|
+
@classmethod
|
|
59
|
+
def _getdict_type(cls) -> str:
|
|
54
60
|
"""
|
|
55
|
-
Returns the
|
|
61
|
+
Returns the meta data for getdict
|
|
56
62
|
"""
|
|
63
|
+
|
|
57
64
|
raise NotImplementedError("Must be implemented by the child classes.")
|
|
58
65
|
|
|
59
66
|
@classmethod
|
|
60
|
-
def from_manifest(cls, name, filepath=None, cfg=None):
|
|
67
|
+
def from_manifest(cls, name: str, filepath: str = None, cfg: Dict = None):
|
|
61
68
|
'''
|
|
62
69
|
Create a new schema based on the provided source files.
|
|
63
70
|
|
|
@@ -72,20 +79,21 @@ class NamedSchema(BaseSchema):
|
|
|
72
79
|
if not filepath and cfg is None:
|
|
73
80
|
raise RuntimeError("filepath or dictionary is required")
|
|
74
81
|
|
|
75
|
-
schema = cls(
|
|
82
|
+
schema = cls()
|
|
83
|
+
schema.set_name(name)
|
|
76
84
|
if filepath:
|
|
77
85
|
schema.read_manifest(filepath)
|
|
78
86
|
if cfg:
|
|
79
87
|
schema._from_dict(cfg, [])
|
|
80
88
|
return schema
|
|
81
89
|
|
|
82
|
-
def _from_dict(self, manifest, keypath, version=None):
|
|
90
|
+
def _from_dict(self, manifest: Dict, keypath: Tuple[str], version: str = None):
|
|
83
91
|
if keypath:
|
|
84
92
|
self.__name = keypath[-1]
|
|
85
93
|
|
|
86
94
|
return super()._from_dict(manifest, keypath, version=version)
|
|
87
95
|
|
|
88
|
-
def copy(self, key=None):
|
|
96
|
+
def copy(self, key: Tuple[str] = None) -> "NamedSchema":
|
|
89
97
|
copy = super().copy(key=key)
|
|
90
98
|
|
|
91
99
|
if key and key[-1] != "default":
|
|
@@ -11,7 +11,8 @@ import shlex
|
|
|
11
11
|
|
|
12
12
|
from enum import Enum
|
|
13
13
|
|
|
14
|
-
from .parametervalue import NodeValue, DirectoryNodeValue, FileNodeValue, NodeListValue
|
|
14
|
+
from .parametervalue import NodeValue, DirectoryNodeValue, FileNodeValue, NodeListValue, \
|
|
15
|
+
NodeSetValue
|
|
15
16
|
from .parametertype import NodeType, NodeEnumType
|
|
16
17
|
|
|
17
18
|
|
|
@@ -59,6 +60,7 @@ class Parameter:
|
|
|
59
60
|
example (list of str): example field
|
|
60
61
|
help (str): help field
|
|
61
62
|
pernode (:class:`.PerNode`): pernode field
|
|
63
|
+
kwargs: forwarded to default value constructor
|
|
62
64
|
'''
|
|
63
65
|
|
|
64
66
|
GLOBAL_KEY = 'global'
|
|
@@ -77,7 +79,8 @@ class Parameter:
|
|
|
77
79
|
switch=None,
|
|
78
80
|
example=None,
|
|
79
81
|
help=None,
|
|
80
|
-
pernode=PerNode.NEVER
|
|
82
|
+
pernode=PerNode.NEVER,
|
|
83
|
+
**kwargs):
|
|
81
84
|
|
|
82
85
|
self.__type = NodeType.parse(type)
|
|
83
86
|
self.__scope = Scope(scope)
|
|
@@ -108,7 +111,7 @@ class Parameter:
|
|
|
108
111
|
|
|
109
112
|
self.__pernode = PerNode(pernode)
|
|
110
113
|
|
|
111
|
-
self.__setdefvalue(defvalue)
|
|
114
|
+
self.__setdefvalue(defvalue, **kwargs)
|
|
112
115
|
|
|
113
116
|
self.__node = {}
|
|
114
117
|
|
|
@@ -123,26 +126,33 @@ class Parameter:
|
|
|
123
126
|
self.__hashalgo = str(hashalgo)
|
|
124
127
|
self.__copy = bool(copy)
|
|
125
128
|
|
|
126
|
-
def __setdefvalue(self, defvalue):
|
|
129
|
+
def __setdefvalue(self, defvalue, **kwargs):
|
|
127
130
|
if NodeType.contains(self.__type, 'file'):
|
|
128
|
-
base = FileNodeValue(defvalue)
|
|
129
131
|
if isinstance(self.__type, list):
|
|
130
|
-
self.__defvalue = NodeListValue(
|
|
132
|
+
self.__defvalue = NodeListValue(FileNodeValue(defvalue, **kwargs))
|
|
133
|
+
elif isinstance(self.__type, set):
|
|
134
|
+
self.__defvalue = NodeSetValue(FileNodeValue(defvalue, **kwargs))
|
|
131
135
|
else:
|
|
132
|
-
self.__defvalue =
|
|
136
|
+
self.__defvalue = FileNodeValue(defvalue, **kwargs)
|
|
133
137
|
elif NodeType.contains(self.__type, 'dir'):
|
|
134
|
-
base = DirectoryNodeValue(defvalue)
|
|
135
138
|
if isinstance(self.__type, list):
|
|
136
|
-
self.__defvalue = NodeListValue(
|
|
139
|
+
self.__defvalue = NodeListValue(DirectoryNodeValue(defvalue, **kwargs))
|
|
140
|
+
elif isinstance(self.__type, set):
|
|
141
|
+
self.__defvalue = NodeSetValue(DirectoryNodeValue(defvalue, **kwargs))
|
|
137
142
|
else:
|
|
138
|
-
self.__defvalue =
|
|
143
|
+
self.__defvalue = DirectoryNodeValue(defvalue, **kwargs)
|
|
139
144
|
else:
|
|
145
|
+
kwargs = {}
|
|
140
146
|
if isinstance(self.__type, list):
|
|
141
|
-
self.__defvalue = NodeListValue(NodeValue(self.__type[0]))
|
|
147
|
+
self.__defvalue = NodeListValue(NodeValue(self.__type[0], **kwargs))
|
|
148
|
+
if defvalue:
|
|
149
|
+
self.__defvalue.set(defvalue)
|
|
150
|
+
elif isinstance(self.__type, set):
|
|
151
|
+
self.__defvalue = NodeSetValue(NodeValue(list(self.__type)[0], **kwargs))
|
|
142
152
|
if defvalue:
|
|
143
153
|
self.__defvalue.set(defvalue)
|
|
144
154
|
else:
|
|
145
|
-
self.__defvalue = NodeValue(self.__type, value=defvalue)
|
|
155
|
+
self.__defvalue = NodeValue(self.__type, value=defvalue, **kwargs)
|
|
146
156
|
|
|
147
157
|
def __str__(self):
|
|
148
158
|
return str(self.getvalues())
|
|
@@ -344,7 +354,7 @@ class Parameter:
|
|
|
344
354
|
|
|
345
355
|
if field in self.__defvalue.fields:
|
|
346
356
|
if not self.is_list() and field == 'value':
|
|
347
|
-
raise ValueError("add can only be used on lists")
|
|
357
|
+
raise ValueError("add can only be used on lists or sets")
|
|
348
358
|
|
|
349
359
|
if isinstance(index, int):
|
|
350
360
|
index = str(index)
|
|
@@ -409,6 +419,12 @@ class Parameter:
|
|
|
409
419
|
|
|
410
420
|
return True
|
|
411
421
|
|
|
422
|
+
def reset(self):
|
|
423
|
+
"""
|
|
424
|
+
Resets a parameter back to its default state
|
|
425
|
+
"""
|
|
426
|
+
self.__node = {}
|
|
427
|
+
|
|
412
428
|
def getdict(self, include_default=True, values_only=False):
|
|
413
429
|
"""
|
|
414
430
|
Returns a schema dictionary.
|
|
@@ -523,15 +539,14 @@ class Parameter:
|
|
|
523
539
|
requires_set = NodeType.contains(self.__type, tuple) or NodeType.contains(self.__type, set)
|
|
524
540
|
|
|
525
541
|
try:
|
|
526
|
-
defvalue = manifest["node"]["default"]["default"]
|
|
542
|
+
defvalue = manifest["node"]["default"]["default"]
|
|
527
543
|
del manifest["node"]["default"]
|
|
528
544
|
except KeyError:
|
|
529
545
|
defvalue = None
|
|
530
546
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
self.__setdefvalue(defvalue)
|
|
547
|
+
self.__setdefvalue(None)
|
|
548
|
+
if defvalue:
|
|
549
|
+
self.__defvalue._from_dict(defvalue, keypath, version)
|
|
535
550
|
|
|
536
551
|
for step, indexdata in manifest["node"].items():
|
|
537
552
|
self.__node[step] = {}
|
|
@@ -559,14 +574,27 @@ class Parameter:
|
|
|
559
574
|
|
|
560
575
|
if self.__pernode == PerNode.REQUIRED and (step is None or index is None):
|
|
561
576
|
return None
|
|
562
|
-
if not self.__pernode.is_never():
|
|
563
|
-
value = self.get(step=step, index=index)
|
|
564
|
-
else:
|
|
565
|
-
value = self.get()
|
|
566
577
|
|
|
567
|
-
|
|
578
|
+
if isinstance(index, int):
|
|
579
|
+
index = str(index)
|
|
580
|
+
|
|
581
|
+
try:
|
|
582
|
+
return self.__node[step][index].gettcl()
|
|
583
|
+
except KeyError:
|
|
584
|
+
if self.__pernode == PerNode.REQUIRED:
|
|
585
|
+
return self.__defvalue.gettcl()
|
|
586
|
+
|
|
587
|
+
try:
|
|
588
|
+
return self.__node[step][Parameter.GLOBAL_KEY].gettcl()
|
|
589
|
+
except KeyError:
|
|
590
|
+
pass
|
|
591
|
+
|
|
592
|
+
try:
|
|
593
|
+
return self.__node[Parameter.GLOBAL_KEY][Parameter.GLOBAL_KEY].gettcl()
|
|
594
|
+
except KeyError:
|
|
595
|
+
return self.__defvalue.gettcl()
|
|
568
596
|
|
|
569
|
-
def getvalues(self, return_defvalue=True):
|
|
597
|
+
def getvalues(self, return_defvalue=True, return_values=True):
|
|
570
598
|
"""
|
|
571
599
|
Returns all values (global and pernode) associated with a particular parameter.
|
|
572
600
|
|
|
@@ -584,10 +612,16 @@ class Parameter:
|
|
|
584
612
|
index_arg = None if index == Parameter.GLOBAL_KEY else index
|
|
585
613
|
if step_arg is None and index_arg is None:
|
|
586
614
|
has_global = True
|
|
587
|
-
|
|
615
|
+
if return_values:
|
|
616
|
+
vals.append((self.__node[step][index].get(), step_arg, index_arg))
|
|
617
|
+
else:
|
|
618
|
+
vals.append((self.__node[step][index], step_arg, index_arg))
|
|
588
619
|
|
|
589
|
-
if
|
|
590
|
-
|
|
620
|
+
if self.__pernode != PerNode.REQUIRED and not has_global and return_defvalue:
|
|
621
|
+
if return_values:
|
|
622
|
+
vals.append((self.__defvalue.get(), None, None))
|
|
623
|
+
else:
|
|
624
|
+
vals.append((self.__defvalue, None, None))
|
|
591
625
|
|
|
592
626
|
return vals
|
|
593
627
|
|
|
@@ -607,7 +641,7 @@ class Parameter:
|
|
|
607
641
|
Returns true is this parameter is a list type
|
|
608
642
|
"""
|
|
609
643
|
|
|
610
|
-
return isinstance(self.__type, list)
|
|
644
|
+
return isinstance(self.__type, (list, set))
|
|
611
645
|
|
|
612
646
|
def is_empty(self):
|
|
613
647
|
'''
|
|
@@ -641,6 +675,33 @@ class Parameter:
|
|
|
641
675
|
index in self.__node[step] and \
|
|
642
676
|
self.__node[step][index]
|
|
643
677
|
|
|
678
|
+
def has_value(self, step=None, index=None) -> bool:
|
|
679
|
+
'''
|
|
680
|
+
Returns whether the parameter as a value.
|
|
681
|
+
|
|
682
|
+
A value counts as set if a user has set a global value OR a value for
|
|
683
|
+
the provided step/index.
|
|
684
|
+
'''
|
|
685
|
+
|
|
686
|
+
if isinstance(index, int):
|
|
687
|
+
index = str(index)
|
|
688
|
+
|
|
689
|
+
try:
|
|
690
|
+
return self.__node[step][index].has_value
|
|
691
|
+
except KeyError:
|
|
692
|
+
if self.__pernode == PerNode.REQUIRED:
|
|
693
|
+
return self.__defvalue.has_value
|
|
694
|
+
|
|
695
|
+
try:
|
|
696
|
+
return self.__node[step][Parameter.GLOBAL_KEY].has_value
|
|
697
|
+
except KeyError:
|
|
698
|
+
pass
|
|
699
|
+
|
|
700
|
+
try:
|
|
701
|
+
return self.__node[Parameter.GLOBAL_KEY][Parameter.GLOBAL_KEY].has_value
|
|
702
|
+
except KeyError:
|
|
703
|
+
return self.__defvalue.has_value
|
|
704
|
+
|
|
644
705
|
@property
|
|
645
706
|
def default(self):
|
|
646
707
|
"""
|
|
@@ -100,6 +100,8 @@ class NodeType:
|
|
|
100
100
|
return True
|
|
101
101
|
if isinstance(value, list):
|
|
102
102
|
return NodeType.contains(value[0], check)
|
|
103
|
+
if isinstance(value, set):
|
|
104
|
+
return NodeType.contains(list(value)[0], check)
|
|
103
105
|
if isinstance(value, tuple):
|
|
104
106
|
return any([NodeType.contains(v, check) for v in value])
|
|
105
107
|
return value == check
|