siliconcompiler 0.32.3__py3-none-any.whl → 0.33.1__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.
Files changed (280) hide show
  1. siliconcompiler/__init__.py +19 -2
  2. siliconcompiler/_common.py +5 -0
  3. siliconcompiler/_metadata.py +1 -1
  4. siliconcompiler/apps/sc.py +2 -2
  5. siliconcompiler/apps/sc_install.py +10 -3
  6. siliconcompiler/apps/sc_issue.py +1 -1
  7. siliconcompiler/apps/sc_remote.py +10 -5
  8. siliconcompiler/apps/sc_show.py +2 -2
  9. siliconcompiler/apps/utils/replay.py +5 -3
  10. siliconcompiler/asic.py +120 -0
  11. siliconcompiler/checklist.py +150 -0
  12. siliconcompiler/core.py +299 -299
  13. siliconcompiler/flowgraph.py +803 -515
  14. siliconcompiler/fpga.py +84 -0
  15. siliconcompiler/metric.py +479 -0
  16. siliconcompiler/optimizer/vizier.py +2 -3
  17. siliconcompiler/package/__init__.py +29 -6
  18. siliconcompiler/pdk.py +415 -0
  19. siliconcompiler/record.py +453 -0
  20. siliconcompiler/remote/client.py +15 -5
  21. siliconcompiler/remote/schema.py +116 -112
  22. siliconcompiler/remote/server.py +9 -6
  23. siliconcompiler/report/dashboard/cli/__init__.py +14 -721
  24. siliconcompiler/report/dashboard/cli/board.py +899 -0
  25. siliconcompiler/report/dashboard/web/__init__.py +10 -10
  26. siliconcompiler/report/dashboard/web/components/__init__.py +5 -4
  27. siliconcompiler/report/dashboard/web/components/flowgraph.py +3 -3
  28. siliconcompiler/report/dashboard/web/components/graph.py +6 -3
  29. siliconcompiler/report/dashboard/web/state.py +1 -1
  30. siliconcompiler/report/dashboard/web/utils/__init__.py +4 -3
  31. siliconcompiler/report/html_report.py +2 -3
  32. siliconcompiler/report/report.py +22 -11
  33. siliconcompiler/report/summary_image.py +1 -1
  34. siliconcompiler/report/summary_table.py +3 -3
  35. siliconcompiler/report/utils.py +21 -14
  36. siliconcompiler/scheduler/__init__.py +234 -1206
  37. siliconcompiler/scheduler/run_node.py +2 -1
  38. siliconcompiler/scheduler/send_messages.py +11 -5
  39. siliconcompiler/scheduler/slurm.py +11 -44
  40. siliconcompiler/scheduler/taskscheduler.py +320 -0
  41. siliconcompiler/schema/__init__.py +19 -2
  42. siliconcompiler/schema/baseschema.py +493 -0
  43. siliconcompiler/schema/cmdlineschema.py +250 -0
  44. siliconcompiler/{sphinx_ext → schema/docs}/__init__.py +3 -1
  45. siliconcompiler/{sphinx_ext → schema/docs}/dynamicgen.py +63 -81
  46. siliconcompiler/{sphinx_ext → schema/docs}/schemagen.py +73 -85
  47. siliconcompiler/{sphinx_ext → schema/docs}/utils.py +12 -13
  48. siliconcompiler/schema/editableschema.py +136 -0
  49. siliconcompiler/schema/journalingschema.py +238 -0
  50. siliconcompiler/schema/namedschema.py +41 -0
  51. siliconcompiler/schema/packageschema.py +101 -0
  52. siliconcompiler/schema/parameter.py +791 -0
  53. siliconcompiler/schema/parametertype.py +323 -0
  54. siliconcompiler/schema/parametervalue.py +736 -0
  55. siliconcompiler/schema/safeschema.py +37 -0
  56. siliconcompiler/schema/schema_cfg.py +109 -1789
  57. siliconcompiler/schema/utils.py +5 -68
  58. siliconcompiler/schema_obj.py +119 -0
  59. siliconcompiler/tool.py +1416 -0
  60. siliconcompiler/tools/_common/__init__.py +6 -10
  61. siliconcompiler/tools/_common/asic.py +5 -5
  62. siliconcompiler/tools/_common/sdc/sc_constraints.sdc +1 -1
  63. siliconcompiler/tools/bluespec/convert.py +9 -8
  64. siliconcompiler/tools/builtin/_common.py +9 -2
  65. siliconcompiler/tools/builtin/concatenate.py +7 -3
  66. siliconcompiler/tools/builtin/minimum.py +7 -2
  67. siliconcompiler/tools/builtin/mux.py +8 -2
  68. siliconcompiler/tools/builtin/nop.py +7 -2
  69. siliconcompiler/tools/builtin/verify.py +11 -5
  70. siliconcompiler/tools/chisel/convert.py +10 -10
  71. siliconcompiler/tools/genfasm/bitstream.py +3 -3
  72. siliconcompiler/tools/ghdl/convert.py +1 -1
  73. siliconcompiler/tools/icarus/compile.py +4 -4
  74. siliconcompiler/tools/icepack/bitstream.py +6 -1
  75. siliconcompiler/tools/klayout/convert_drc_db.py +5 -0
  76. siliconcompiler/tools/klayout/drc.py +2 -2
  77. siliconcompiler/tools/klayout/klayout_export.py +0 -1
  78. siliconcompiler/tools/klayout/klayout_show.py +6 -6
  79. siliconcompiler/tools/klayout/klayout_utils.py +15 -22
  80. siliconcompiler/tools/netgen/count_lvs.py +2 -2
  81. siliconcompiler/tools/netgen/lvs.py +1 -1
  82. siliconcompiler/tools/nextpnr/apr.py +6 -1
  83. siliconcompiler/tools/nextpnr/nextpnr.py +4 -4
  84. siliconcompiler/tools/openroad/_apr.py +15 -2
  85. siliconcompiler/tools/openroad/rdlroute.py +3 -3
  86. siliconcompiler/tools/openroad/scripts/apr/postamble.tcl +1 -1
  87. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +5 -5
  88. siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +2 -2
  89. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +2 -2
  90. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +2 -2
  91. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +2 -2
  92. siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +2 -2
  93. siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +2 -2
  94. siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +2 -2
  95. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +2 -2
  96. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +2 -2
  97. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +3 -9
  98. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +3 -3
  99. siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +2 -2
  100. siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +2 -2
  101. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +2 -2
  102. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +2 -2
  103. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +2 -2
  104. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +2 -2
  105. siliconcompiler/tools/openroad/scripts/common/procs.tcl +75 -1
  106. siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -7
  107. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +2 -2
  108. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +28 -3
  109. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +1 -1
  110. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -3
  111. siliconcompiler/tools/openroad/scripts/sc_show.tcl +6 -6
  112. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +10 -0
  113. siliconcompiler/tools/opensta/timing.py +11 -0
  114. siliconcompiler/tools/slang/__init__.py +13 -13
  115. siliconcompiler/tools/slang/elaborate.py +6 -6
  116. siliconcompiler/tools/slang/lint.py +1 -3
  117. siliconcompiler/tools/surelog/parse.py +4 -4
  118. siliconcompiler/tools/sv2v/convert.py +20 -3
  119. siliconcompiler/tools/verilator/compile.py +2 -2
  120. siliconcompiler/tools/verilator/verilator.py +3 -3
  121. siliconcompiler/tools/vpr/_xml_constraint.py +8 -8
  122. siliconcompiler/tools/vpr/place.py +1 -1
  123. siliconcompiler/tools/vpr/route.py +4 -4
  124. siliconcompiler/tools/vpr/screenshot.py +1 -1
  125. siliconcompiler/tools/vpr/show.py +5 -5
  126. siliconcompiler/tools/vpr/vpr.py +24 -24
  127. siliconcompiler/tools/xdm/convert.py +2 -2
  128. siliconcompiler/tools/xyce/simulate.py +1 -1
  129. siliconcompiler/tools/yosys/prepareLib.py +2 -2
  130. siliconcompiler/tools/yosys/sc_synth_asic.tcl +111 -63
  131. siliconcompiler/tools/yosys/screenshot.py +1 -1
  132. siliconcompiler/tools/yosys/syn_asic.py +7 -7
  133. siliconcompiler/toolscripts/_tools.json +12 -10
  134. siliconcompiler/toolscripts/rhel8/install-chisel.sh +9 -2
  135. siliconcompiler/toolscripts/rhel8/install-icarus.sh +10 -3
  136. siliconcompiler/toolscripts/rhel8/install-klayout.sh +8 -1
  137. siliconcompiler/toolscripts/rhel8/install-magic.sh +9 -2
  138. siliconcompiler/toolscripts/rhel8/install-montage.sh +1 -1
  139. siliconcompiler/toolscripts/rhel8/install-netgen.sh +9 -2
  140. siliconcompiler/toolscripts/rhel8/install-slang.sh +11 -4
  141. siliconcompiler/toolscripts/rhel8/install-surelog.sh +9 -2
  142. siliconcompiler/toolscripts/rhel8/install-sv2v.sh +11 -4
  143. siliconcompiler/toolscripts/rhel8/install-verible.sh +11 -3
  144. siliconcompiler/toolscripts/rhel8/install-verilator.sh +10 -3
  145. siliconcompiler/toolscripts/rhel8/install-xyce.sh +15 -10
  146. siliconcompiler/toolscripts/rhel9/install-chisel.sh +9 -2
  147. siliconcompiler/toolscripts/rhel9/install-ghdl.sh +9 -2
  148. siliconcompiler/toolscripts/rhel9/install-gtkwave.sh +10 -3
  149. siliconcompiler/toolscripts/rhel9/install-icarus.sh +10 -3
  150. siliconcompiler/toolscripts/rhel9/install-klayout.sh +8 -1
  151. siliconcompiler/toolscripts/rhel9/install-magic.sh +9 -2
  152. siliconcompiler/toolscripts/rhel9/install-montage.sh +1 -1
  153. siliconcompiler/toolscripts/rhel9/install-netgen.sh +9 -2
  154. siliconcompiler/toolscripts/rhel9/install-openroad.sh +16 -3
  155. siliconcompiler/toolscripts/rhel9/install-opensta.sh +17 -5
  156. siliconcompiler/toolscripts/rhel9/install-slang.sh +11 -4
  157. siliconcompiler/toolscripts/rhel9/install-surelog.sh +9 -2
  158. siliconcompiler/toolscripts/rhel9/install-sv2v.sh +11 -4
  159. siliconcompiler/toolscripts/rhel9/install-verible.sh +11 -3
  160. siliconcompiler/toolscripts/rhel9/install-verilator.sh +10 -3
  161. siliconcompiler/toolscripts/rhel9/install-vpr.sh +9 -2
  162. siliconcompiler/toolscripts/rhel9/install-xdm.sh +10 -2
  163. siliconcompiler/toolscripts/rhel9/install-xyce.sh +15 -10
  164. siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +9 -2
  165. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +10 -3
  166. siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +10 -2
  167. siliconcompiler/toolscripts/rhel9/install-yosys.sh +9 -2
  168. siliconcompiler/toolscripts/ubuntu20/install-bambu.sh +10 -2
  169. siliconcompiler/toolscripts/ubuntu20/install-bluespec.sh +10 -3
  170. siliconcompiler/toolscripts/ubuntu20/install-chisel.sh +9 -2
  171. siliconcompiler/toolscripts/ubuntu20/install-ghdl.sh +9 -2
  172. siliconcompiler/toolscripts/ubuntu20/install-gtkwave.sh +9 -2
  173. siliconcompiler/toolscripts/ubuntu20/install-icarus.sh +9 -2
  174. siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +9 -2
  175. siliconcompiler/toolscripts/ubuntu20/install-klayout.sh +8 -1
  176. siliconcompiler/toolscripts/ubuntu20/install-magic.sh +9 -2
  177. siliconcompiler/toolscripts/ubuntu20/install-montage.sh +1 -1
  178. siliconcompiler/toolscripts/ubuntu20/install-netgen.sh +9 -2
  179. siliconcompiler/toolscripts/ubuntu20/install-nextpnr.sh +9 -2
  180. siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +16 -3
  181. siliconcompiler/toolscripts/ubuntu20/install-opensta.sh +16 -5
  182. siliconcompiler/toolscripts/ubuntu20/install-slang.sh +11 -4
  183. siliconcompiler/toolscripts/ubuntu20/install-slurm.sh +9 -2
  184. siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +10 -2
  185. siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +11 -4
  186. siliconcompiler/toolscripts/ubuntu20/install-verible.sh +11 -3
  187. siliconcompiler/toolscripts/ubuntu20/install-verilator.sh +9 -2
  188. siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +10 -2
  189. siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +13 -8
  190. siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +9 -2
  191. siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +9 -2
  192. siliconcompiler/toolscripts/ubuntu22/install-bambu.sh +10 -2
  193. siliconcompiler/toolscripts/ubuntu22/install-bluespec.sh +10 -3
  194. siliconcompiler/toolscripts/ubuntu22/install-chisel.sh +9 -2
  195. siliconcompiler/toolscripts/ubuntu22/install-ghdl.sh +9 -2
  196. siliconcompiler/toolscripts/ubuntu22/install-gtkwave.sh +9 -2
  197. siliconcompiler/toolscripts/ubuntu22/install-icarus.sh +9 -2
  198. siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +9 -2
  199. siliconcompiler/toolscripts/ubuntu22/install-klayout.sh +8 -1
  200. siliconcompiler/toolscripts/ubuntu22/install-magic.sh +9 -2
  201. siliconcompiler/toolscripts/ubuntu22/install-montage.sh +1 -1
  202. siliconcompiler/toolscripts/ubuntu22/install-netgen.sh +9 -2
  203. siliconcompiler/toolscripts/ubuntu22/install-nextpnr.sh +9 -2
  204. siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +16 -3
  205. siliconcompiler/toolscripts/ubuntu22/install-opensta.sh +17 -5
  206. siliconcompiler/toolscripts/ubuntu22/install-slang.sh +11 -4
  207. siliconcompiler/toolscripts/ubuntu22/install-slurm.sh +9 -2
  208. siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +10 -2
  209. siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +11 -4
  210. siliconcompiler/toolscripts/ubuntu22/install-verible.sh +11 -3
  211. siliconcompiler/toolscripts/ubuntu22/install-verilator.sh +9 -2
  212. siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +9 -4
  213. siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +10 -2
  214. siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +13 -8
  215. siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +9 -2
  216. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +10 -3
  217. siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +10 -2
  218. siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +9 -2
  219. siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +12 -4
  220. siliconcompiler/toolscripts/ubuntu24/install-bluespec.sh +10 -3
  221. siliconcompiler/toolscripts/ubuntu24/install-chisel.sh +9 -2
  222. siliconcompiler/toolscripts/ubuntu24/install-ghdl.sh +9 -2
  223. siliconcompiler/toolscripts/ubuntu24/install-gtkwave.sh +9 -2
  224. siliconcompiler/toolscripts/ubuntu24/install-icarus.sh +9 -2
  225. siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +9 -2
  226. siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +8 -1
  227. siliconcompiler/toolscripts/ubuntu24/install-magic.sh +9 -2
  228. siliconcompiler/toolscripts/ubuntu24/install-montage.sh +1 -1
  229. siliconcompiler/toolscripts/ubuntu24/install-netgen.sh +9 -2
  230. siliconcompiler/toolscripts/ubuntu24/install-nextpnr.sh +9 -2
  231. siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +16 -3
  232. siliconcompiler/toolscripts/ubuntu24/install-opensta.sh +17 -5
  233. siliconcompiler/toolscripts/ubuntu24/install-slang.sh +11 -4
  234. siliconcompiler/toolscripts/ubuntu24/install-slurm.sh +9 -2
  235. siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +10 -2
  236. siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +11 -4
  237. siliconcompiler/toolscripts/ubuntu24/install-verible.sh +11 -3
  238. siliconcompiler/toolscripts/ubuntu24/install-verilator.sh +9 -2
  239. siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +9 -4
  240. siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +10 -2
  241. siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +13 -8
  242. siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +9 -2
  243. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +10 -3
  244. siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +10 -2
  245. siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +9 -2
  246. siliconcompiler/utils/__init__.py +19 -112
  247. siliconcompiler/utils/flowgraph.py +244 -0
  248. siliconcompiler/{issue.py → utils/issue.py} +18 -25
  249. siliconcompiler/utils/logging.py +3 -4
  250. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/METADATA +9 -8
  251. siliconcompiler-0.33.1.dist-info/RECORD +488 -0
  252. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/WHEEL +1 -1
  253. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/entry_points.txt +8 -8
  254. siliconcompiler/schema/schema_obj.py +0 -1936
  255. siliconcompiler/toolscripts/ubuntu20/install-vpr.sh +0 -29
  256. siliconcompiler/toolscripts/ubuntu20/install-yosys-parmys.sh +0 -61
  257. siliconcompiler-0.32.3.dist-info/RECORD +0 -470
  258. /siliconcompiler/{templates → data/templates}/__init__.py +0 -0
  259. /siliconcompiler/{templates → data/templates}/email/__init__.py +0 -0
  260. /siliconcompiler/{templates → data/templates}/email/general.j2 +0 -0
  261. /siliconcompiler/{templates → data/templates}/email/summary.j2 +0 -0
  262. /siliconcompiler/{templates → data/templates}/issue/README.txt +0 -0
  263. /siliconcompiler/{templates → data/templates}/issue/__init__.py +0 -0
  264. /siliconcompiler/{templates → data/templates}/issue/run.sh +0 -0
  265. /siliconcompiler/{templates → data/templates}/replay/replay.py.j2 +0 -0
  266. /siliconcompiler/{templates → data/templates}/replay/replay.sh.j2 +0 -0
  267. /siliconcompiler/{templates → data/templates}/replay/requirements.txt +0 -0
  268. /siliconcompiler/{templates → data/templates}/replay/setup.sh +0 -0
  269. /siliconcompiler/{templates → data/templates}/report/__init__.py +0 -0
  270. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.css +0 -0
  271. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.js +0 -0
  272. /siliconcompiler/{templates → data/templates}/report/bootstrap_LICENSE.md +0 -0
  273. /siliconcompiler/{templates → data/templates}/report/sc_report.j2 +0 -0
  274. /siliconcompiler/{templates → data/templates}/slurm/__init__.py +0 -0
  275. /siliconcompiler/{templates → data/templates}/slurm/run.sh +0 -0
  276. /siliconcompiler/{templates → data/templates}/tcl/__init__.py +0 -0
  277. /siliconcompiler/{templates → data/templates}/tcl/manifest.tcl.j2 +0 -0
  278. /siliconcompiler/{units.py → utils/units.py} +0 -0
  279. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/licenses/LICENSE +0 -0
  280. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,323 @@
1
+ import re
2
+ from collections.abc import Iterable
3
+ from pathlib import Path, PureWindowsPath
4
+
5
+
6
+ class NodeType:
7
+ """
8
+ Schema type decoding and encoding class.
9
+
10
+ Args:
11
+ sctype (str or :class:`NodeType`): schema type
12
+ """
13
+ __list = re.compile(r"^\[(.*)\]$")
14
+ __tuple = re.compile(r"^\((.*)\)$")
15
+ __set = re.compile(r"^\{(.*)\}$")
16
+ __enum = re.compile(r"^<(.*)>$")
17
+ __basetypes = re.compile(r"^(<(.*)>|int|float|str|bool|file|dir)$")
18
+
19
+ def __init__(self, sctype):
20
+ if isinstance(sctype, NodeType):
21
+ self.__type = sctype.type
22
+ elif isinstance(sctype, str):
23
+ self.__type = NodeType.parse(sctype)
24
+ else:
25
+ self.__type = sctype
26
+
27
+ def __str__(self):
28
+ return NodeType.encode(self.__type)
29
+
30
+ @property
31
+ def type(self):
32
+ return self.__type
33
+
34
+ @staticmethod
35
+ def parse(sctype):
36
+ """
37
+ Parses a schema type string.
38
+ """
39
+
40
+ if isinstance(sctype, NodeType):
41
+ return sctype.type
42
+
43
+ if not isinstance(sctype, str):
44
+ return sctype
45
+
46
+ if NodeType.__basetypes.match(sctype):
47
+ if NodeType.__enum.match(sctype):
48
+ return NodeEnumType(*sctype[1:-1].split(","))
49
+ return sctype
50
+ if NodeType.__list.match(sctype):
51
+ return [NodeType.parse(sctype[1:-1])]
52
+ if NodeType.__set.match(sctype):
53
+ return set([NodeType.parse(sctype[1:-1])])
54
+ if NodeType.__tuple.match(sctype):
55
+ tupletypes = []
56
+ typletype = ""
57
+ for ttype in sctype[1:-1].split(","):
58
+ typletype += ttype
59
+ try:
60
+ tupletypes.append(NodeType.parse(typletype))
61
+ typletype = ""
62
+ except ValueError:
63
+ typletype += ","
64
+ return tuple(tupletypes)
65
+ raise ValueError(sctype)
66
+
67
+ @staticmethod
68
+ def encode(sctype):
69
+ """
70
+ Encodes a schema type into a string.
71
+ """
72
+
73
+ if isinstance(sctype, NodeType):
74
+ sctype = sctype.type
75
+
76
+ if isinstance(sctype, list):
77
+ return f"[{NodeType.encode(sctype[0])}]"
78
+
79
+ if isinstance(sctype, tuple):
80
+ return f"({','.join([NodeType.encode(sct) for sct in sctype])})"
81
+
82
+ if isinstance(sctype, set):
83
+ return f"{{{','.join([NodeType.encode(sct) for sct in sctype])}}}"
84
+
85
+ if isinstance(sctype, NodeEnumType):
86
+ return str(sctype)
87
+
88
+ if isinstance(sctype, str):
89
+ return sctype
90
+
91
+ raise ValueError(f"{sctype} not a recognized type")
92
+
93
+ @staticmethod
94
+ def contains(value, check):
95
+ """
96
+ Check if the type contains a specific type.
97
+ """
98
+ if check in (list, tuple, set, NodeEnumType):
99
+ if isinstance(value, check):
100
+ return True
101
+ if isinstance(value, list):
102
+ return NodeType.contains(value[0], check)
103
+ if isinstance(value, tuple):
104
+ return any([NodeType.contains(v, check) for v in value])
105
+ return value == check
106
+
107
+ @staticmethod
108
+ def to_tcl(value, sctype):
109
+ '''
110
+ Recursive helper function for converting Python values to safe TCL
111
+ values, based on the SC type string.
112
+ '''
113
+
114
+ if isinstance(sctype, list):
115
+ if value is None:
116
+ return '[list ]'
117
+ # Recurse into each item of list
118
+ valstr = ' '.join(NodeType.to_tcl(v, sctype[0]) for v in value)
119
+ return f'[list {valstr}]'
120
+
121
+ if isinstance(sctype, set):
122
+ if value is None:
123
+ return '[list ]'
124
+ # Recurse into each item of list
125
+ sctype = list(sctype)[0]
126
+ valstr = ' '.join(NodeType.to_tcl(v, sctype) for v in value)
127
+ return f'[list {valstr}]'
128
+
129
+ if isinstance(sctype, tuple):
130
+ if value is None:
131
+ return '[list ]'
132
+ valstr = ' '.join(NodeType.to_tcl(v, subtype) for v, subtype in zip(value, sctype))
133
+ return f'[list {valstr}]'
134
+
135
+ if value is None:
136
+ return ''
137
+
138
+ if sctype == 'str' or isinstance(sctype, NodeEnumType):
139
+ # Escape string by surrounding it with "" and escaping the few
140
+ # special characters that still get considered inside "". We don't
141
+ # use {}, since this requires adding permanent backslashes to any
142
+ # curly braces inside the string.
143
+ # Source: https://www.tcl.tk/man/tcl8.4/TclCmd/Tcl.html (section [4] on)
144
+ escaped_val = (value.replace('\\', '\\\\') # escape '\' to avoid backslash substitution
145
+ # (do this first, since other replaces
146
+ # insert '\')
147
+ .replace('[', '\\[') # escape '[' to avoid command substitution
148
+ .replace('$', '\\$') # escape '$' to avoid variable substitution
149
+ .replace('"', '\\"')) # escape '"' to avoid string terminating
150
+ return '"' + escaped_val + '"'
151
+ if sctype == 'bool':
152
+ return 'true' if value else 'false'
153
+
154
+ if sctype == 'int':
155
+ return str(value)
156
+
157
+ if sctype == 'float':
158
+ return f"{value:.9g}"
159
+
160
+ if sctype in ('file', 'dir'):
161
+ # Replace $VAR with $env(VAR) for tcl
162
+ value = re.sub(r'\${?(\w+)}?', r'$env(\1)', value)
163
+ # Same escapes as applied to string, minus $ (since we want to resolve env vars).
164
+ escaped_val = (value.replace('\\', '\\\\') # escape '\' to avoid backslash substitution
165
+ # (do this first, since other replaces
166
+ # insert '\')
167
+ .replace('[', '\\[') # escape '[' to avoid command substitution
168
+ .replace('"', '\\"')) # escape '"' to avoid string terminating
169
+ return '"' + escaped_val + '"'
170
+
171
+ raise TypeError(f'{sctype} is not a supported type')
172
+
173
+ @staticmethod
174
+ def normalize(value, sctype):
175
+ """
176
+ Normalizes a value into the appropriate datatype.
177
+ """
178
+
179
+ if isinstance(sctype, NodeType):
180
+ return NodeType.normalize(value, sctype.type)
181
+
182
+ if isinstance(sctype, list):
183
+ sctype = sctype[0]
184
+
185
+ # Need to try 2 different recursion strategies - if value is a list already, then we can
186
+ # recurse on it directly. However, if that doesn't work, then it might be a
187
+ # list-of-lists/tuples that needs to be wrapped in an outer list, so we try that.
188
+ if isinstance(value, (list, set, tuple)):
189
+ try:
190
+ return [NodeType.normalize(v, sctype) for v in value]
191
+ except ValueError:
192
+ pass
193
+
194
+ return [NodeType.normalize(v, sctype) for v in [value]]
195
+
196
+ if isinstance(sctype, set):
197
+ sctype = list(sctype)[0]
198
+
199
+ # Need to try 2 different recursion strategies - if value is a list already, then we can
200
+ # recurse on it directly. However, if that doesn't work, then it might be a
201
+ # list-of-lists/tuples that needs to be wrapped in an outer list, so we try that.
202
+ if isinstance(value, (list, set, tuple)):
203
+ try:
204
+ return set([NodeType.normalize(v, sctype) for v in value])
205
+ except ValueError:
206
+ pass
207
+
208
+ return set([NodeType.normalize(v, sctype) for v in [value]])
209
+
210
+ if isinstance(sctype, tuple):
211
+ if value is None:
212
+ return None
213
+
214
+ sctype = [*sctype]
215
+
216
+ if isinstance(value, str):
217
+ if NodeType.__tuple.match(value):
218
+ value = value[1:-1].split(',')
219
+ else:
220
+ value = value.split(',')
221
+ elif not isinstance(value, (list, tuple)):
222
+ valuetype = type(value)
223
+ if isinstance(value, Iterable):
224
+ value = ",".join(value)
225
+ raise ValueError(f"({value}) ({valuetype}) cannot be converted to tuple")
226
+
227
+ if len(value) != len(sctype):
228
+ raise ValueError(f"({','.join(value)}) does not have {len(sctype)} entries")
229
+ return tuple(
230
+ NodeType.normalize(v, base_type)
231
+ for v, base_type in zip(value, sctype))
232
+
233
+ if value is None:
234
+ return None
235
+
236
+ if isinstance(value, (list, tuple, set)):
237
+ if len(value) == 1:
238
+ return NodeType.normalize(list(value)[0], sctype)
239
+ raise ValueError(f"\"{type(value)}\" unable to convert to {sctype}")
240
+
241
+ if sctype == 'bool':
242
+ if isinstance(value, bool):
243
+ return value
244
+ if isinstance(value, str):
245
+ value = value.strip().lower()
246
+ if value == 'true' or value == 't':
247
+ return True
248
+ if value == 'false' or value == 'f':
249
+ return False
250
+ if isinstance(value, (int, float)):
251
+ return value != 0
252
+ raise ValueError(f"\"{value}\" unable to convert to boolean")
253
+
254
+ try:
255
+ if sctype == 'int':
256
+ return int(value)
257
+
258
+ if sctype == 'float':
259
+ return float(value)
260
+ except ValueError:
261
+ raise ValueError(f"\"{value}\" unable to convert to {sctype}")
262
+
263
+ if sctype == 'str':
264
+ if isinstance(value, str):
265
+ return value
266
+ elif isinstance(value, bool):
267
+ return str(value).lower()
268
+ else:
269
+ return str(value)
270
+
271
+ if sctype in ('file', 'dir'):
272
+ if isinstance(value, (str, Path)):
273
+ # Cast everything to a windows path and convert to posix.
274
+ # https://stackoverflow.com/questions/73682260
275
+ return PureWindowsPath(value).as_posix()
276
+ else:
277
+ raise ValueError(f"{sctype} must be a string or Path, not {type(value)}")
278
+
279
+ if isinstance(sctype, NodeEnumType):
280
+ if isinstance(value, str):
281
+ if value in sctype.values:
282
+ return value
283
+ valid = ", ".join(sorted(sctype.values))
284
+ raise ValueError(f'{value} is not a member of: {valid}')
285
+ else:
286
+ raise ValueError(f"enum must be a string, not a {type(value)}")
287
+
288
+ raise ValueError(f'Invalid type specifier: {sctype}')
289
+
290
+
291
+ class NodeEnumType:
292
+ """
293
+ Type for schema data type
294
+
295
+ Args:
296
+ values (list of str): list of legal values for this type.
297
+ """
298
+
299
+ def __init__(self, *values):
300
+ if not values:
301
+ raise ValueError("enum cannot be empty set")
302
+ self.__values = set(values)
303
+
304
+ def __eq__(self, other):
305
+ if isinstance(other, NodeEnumType):
306
+ return self.__values == other.__values
307
+ return False
308
+
309
+ def __str__(self):
310
+ return f"<{','.join(sorted(self.__values))}>"
311
+
312
+ def __repr__(self):
313
+ return str(self)
314
+
315
+ def __hash__(self):
316
+ return hash(tuple(self.__values))
317
+
318
+ @property
319
+ def values(self):
320
+ '''
321
+ Returns a set of the legal values for this enum.
322
+ '''
323
+ return self.__values