pyEDAA.OutputFilter 0.2.0__tar.gz → 0.4.0__tar.gz

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 (27) hide show
  1. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/PKG-INFO +25 -25
  2. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/README.md +1 -1
  3. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/CLI/Vivado.py +331 -0
  4. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/Commands.py +713 -0
  5. pyedaa_outputfilter-0.2.0/pyEDAA/OutputFilter/Xilinx/__init__.py → pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/Common.py +114 -303
  6. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/Common2.py +495 -0
  7. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/Exception.py +59 -0
  8. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py +599 -0
  9. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py +127 -0
  10. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py +754 -0
  11. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/RouteDesign.py +527 -0
  12. pyedaa_outputfilter-0.2.0/pyEDAA/OutputFilter/Xilinx/Synthesis.py → pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py +176 -233
  13. pyedaa_outputfilter-0.4.0/pyEDAA/OutputFilter/Xilinx/__init__.py +267 -0
  14. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyEDAA/OutputFilter/__init__.py +1 -1
  15. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyEDAA.OutputFilter.egg-info/PKG-INFO +25 -25
  16. pyedaa_outputfilter-0.4.0/pyEDAA.OutputFilter.egg-info/SOURCES.txt +23 -0
  17. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyEDAA.OutputFilter.egg-info/requires.txt +23 -23
  18. pyedaa_outputfilter-0.2.0/pyEDAA/OutputFilter/CLI/Vivado.py +0 -192
  19. pyedaa_outputfilter-0.2.0/pyEDAA.OutputFilter.egg-info/SOURCES.txt +0 -15
  20. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/LICENSE.md +0 -0
  21. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyEDAA/OutputFilter/CLI/__init__.py +0 -0
  22. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyEDAA.OutputFilter.egg-info/dependency_links.txt +0 -0
  23. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyEDAA.OutputFilter.egg-info/entry_points.txt +0 -0
  24. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyEDAA.OutputFilter.egg-info/top_level.txt +0 -0
  25. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/pyproject.toml +0 -0
  26. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/setup.cfg +0 -0
  27. {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.4.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyEDAA.OutputFilter
3
- Version: 0.2.0
3
+ Version: 0.4.0
4
4
  Summary: Post-processing of EDA Tool outputs (log files).
5
5
  Home-page: https://GitHub.com/edaa-org/pyEDAA.OutputFilter
6
6
  Author: Patrick Lehmann
@@ -27,45 +27,45 @@ Description-Content-Type: text/markdown
27
27
  License-File: LICENSE.md
28
28
  Requires-Dist: pyTooling[terminal]~=8.5
29
29
  Provides-Extra: doc
30
- Requires-Dist: sphinx_design~=0.6.1; extra == "doc"
30
+ Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "doc"
31
+ Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
31
32
  Requires-Dist: pyTooling[terminal]~=8.5; extra == "doc"
33
+ Requires-Dist: autoapi>=2.0.1; extra == "doc"
32
34
  Requires-Dist: docutils_stubs~=0.0.22; extra == "doc"
33
- Requires-Dist: sphinx_rtd_theme~=3.0; extra == "doc"
34
- Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "doc"
35
35
  Requires-Dist: sphinx_autodoc_typehints~=3.2; extra == "doc"
36
- Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
37
36
  Requires-Dist: sphinx~=8.2; extra == "doc"
38
- Requires-Dist: sphinx_reports~=0.9; extra == "doc"
39
- Requires-Dist: autoapi>=2.0.1; extra == "doc"
37
+ Requires-Dist: sphinx_rtd_theme~=3.0; extra == "doc"
40
38
  Requires-Dist: docutils~=0.21; extra == "doc"
41
- Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "doc"
39
+ Requires-Dist: sphinx_design~=0.6.1; extra == "doc"
40
+ Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "doc"
41
+ Requires-Dist: sphinx_reports~=0.9; extra == "doc"
42
42
  Provides-Extra: test
43
+ Requires-Dist: lxml~=6.0; extra == "test"
44
+ Requires-Dist: mypy~=1.16; extra == "test"
43
45
  Requires-Dist: pyTooling[terminal]~=8.5; extra == "test"
46
+ Requires-Dist: Coverage~=7.10; extra == "test"
47
+ Requires-Dist: pytest~=8.4; extra == "test"
44
48
  Requires-Dist: typing_extensions~=4.14; extra == "test"
45
49
  Requires-Dist: pytest-cov~=6.2; extra == "test"
46
- Requires-Dist: pytest~=8.4; extra == "test"
47
- Requires-Dist: Coverage~=7.9; extra == "test"
48
- Requires-Dist: lxml~=5.4; extra == "test"
49
- Requires-Dist: mypy~=1.16; extra == "test"
50
50
  Provides-Extra: all
51
- Requires-Dist: sphinx_design~=0.6.1; extra == "all"
51
+ Requires-Dist: lxml~=6.0; extra == "all"
52
+ Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "all"
53
+ Requires-Dist: sphinx-copybutton>=0.5.2; extra == "all"
52
54
  Requires-Dist: pyTooling[terminal]~=8.5; extra == "all"
55
+ Requires-Dist: autoapi>=2.0.1; extra == "all"
56
+ Requires-Dist: mypy~=1.16; extra == "all"
57
+ Requires-Dist: Coverage~=7.10; extra == "all"
53
58
  Requires-Dist: docutils_stubs~=0.0.22; extra == "all"
54
- Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "all"
55
- Requires-Dist: sphinx_rtd_theme~=3.0; extra == "all"
56
59
  Requires-Dist: sphinx_autodoc_typehints~=3.2; extra == "all"
57
- Requires-Dist: sphinx-copybutton>=0.5.2; extra == "all"
58
60
  Requires-Dist: sphinx~=8.2; extra == "all"
61
+ Requires-Dist: sphinx_rtd_theme~=3.0; extra == "all"
62
+ Requires-Dist: docutils~=0.21; extra == "all"
63
+ Requires-Dist: sphinx_design~=0.6.1; extra == "all"
64
+ Requires-Dist: pytest~=8.4; extra == "all"
59
65
  Requires-Dist: typing_extensions~=4.14; extra == "all"
60
- Requires-Dist: sphinx_reports~=0.9; extra == "all"
61
66
  Requires-Dist: pytest-cov~=6.2; extra == "all"
62
- Requires-Dist: pytest~=8.4; extra == "all"
63
- Requires-Dist: Coverage~=7.9; extra == "all"
64
- Requires-Dist: lxml~=5.4; extra == "all"
65
- Requires-Dist: autoapi>=2.0.1; extra == "all"
66
- Requires-Dist: docutils~=0.21; extra == "all"
67
- Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "all"
68
- Requires-Dist: mypy~=1.16; extra == "all"
67
+ Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "all"
68
+ Requires-Dist: sphinx_reports~=0.9; extra == "all"
69
69
  Dynamic: author
70
70
  Dynamic: author-email
71
71
  Dynamic: classifier
@@ -127,7 +127,7 @@ Dynamic: summary
127
127
 
128
128
  ```python
129
129
  from pathlib import Path
130
- from pyEDAA.OutputFilter.Xilinx.Synthesis import Processor
130
+ from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import Processor
131
131
 
132
132
  logfile = Path("tests/data/Stopwatch/toplevel.vds")
133
133
  processor = Processor(logfile)
@@ -44,7 +44,7 @@
44
44
 
45
45
  ```python
46
46
  from pathlib import Path
47
- from pyEDAA.OutputFilter.Xilinx.Synthesis import Processor
47
+ from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import Processor
48
48
 
49
49
  logfile = Path("tests/data/Stopwatch/toplevel.vds")
50
50
  processor = Processor(logfile)
@@ -0,0 +1,331 @@
1
+ # ==================================================================================================================== #
2
+ # _____ ____ _ _ ___ _ _ _____ _ _ _ #
3
+ # _ __ _ _| ____| _ \ / \ / \ / _ \ _ _| |_ _ __ _ _| |_| ___(_) | |_ ___ _ __ #
4
+ # | '_ \| | | | _| | | | |/ _ \ / _ \ | | | | | | | __| '_ \| | | | __| |_ | | | __/ _ \ '__| #
5
+ # | |_) | |_| | |___| |_| / ___ \ / ___ \ | |_| | |_| | |_| |_) | |_| | |_| _| | | | || __/ | #
6
+ # | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___/ \__,_|\__| .__/ \__,_|\__|_| |_|_|\__\___|_| #
7
+ # |_| |___/ |_| #
8
+ # ==================================================================================================================== #
9
+ # Authors: #
10
+ # Patrick Lehmann #
11
+ # #
12
+ # License: #
13
+ # ==================================================================================================================== #
14
+ # Copyright 2025-2025 Electronic Design Automation Abstraction (EDA²) #
15
+ # #
16
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
17
+ # you may not use this file except in compliance with the License. #
18
+ # You may obtain a copy of the License at #
19
+ # #
20
+ # http://www.apache.org/licenses/LICENSE-2.0 #
21
+ # #
22
+ # Unless required by applicable law or agreed to in writing, software #
23
+ # distributed under the License is distributed on an "AS IS" BASIS, #
24
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
25
+ # See the License for the specific language governing permissions and #
26
+ # limitations under the License. #
27
+ # #
28
+ # SPDX-License-Identifier: Apache-2.0 #
29
+ # ==================================================================================================================== #
30
+ #
31
+ from argparse import Namespace
32
+ from pathlib import Path
33
+ from sys import stdin as sys_stdin
34
+ from typing import NoReturn, Iterable
35
+
36
+ from pyTooling.Decorators import readonly
37
+ from pyTooling.MetaClasses import ExtendedType
38
+ from pyTooling.Attributes.ArgParse import CommandHandler
39
+ from pyTooling.Attributes.ArgParse.Flag import LongFlag
40
+ from pyTooling.Attributes.ArgParse.ValuedFlag import LongValuedFlag
41
+ from pyTooling.Stopwatch import Stopwatch
42
+
43
+ from pyEDAA.OutputFilter.Xilinx import Document, ProcessorException, SynthesizeDesign, Processor
44
+ from pyEDAA.OutputFilter.Xilinx.Common import LineKind, Line
45
+ from pyEDAA.OutputFilter.Xilinx.Common2 import Preamble
46
+ from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import WritingSynthesisReport, LoadingPart
47
+
48
+
49
+
50
+ class VivadoHandlers(metaclass=ExtendedType, mixin=True):
51
+ @CommandHandler("vivado", help="Parse AMD/Xilinx Vivado log files.", description="Parse AMD/Xilinx Vivado log files.")
52
+ @LongFlag("--stdin", dest="stdin", help="Read log from STDIN.")
53
+ @LongValuedFlag("--file", dest="logfile", metaName='Log file', optional=True, help="Read from log file (*.vds|*.vdi).")
54
+ @LongFlag("--colored", dest="colored", help="Render logfile with colored lines.")
55
+ @LongFlag("--summary", dest="summary", help="Print a summary.")
56
+ @LongFlag("--info", dest="info", help="Print info messages.")
57
+ @LongFlag("--warning", dest="warning", help="Print warning messages.")
58
+ @LongFlag("--critical", dest="critical", help="Print critical warning messages.")
59
+ @LongFlag("--error", dest="error", help="Print error messages.")
60
+ @LongFlag("--influxdb", dest="influxdb", help="Write statistics as InfluxDB line protocol file (*.line).")
61
+ # @LongValuedFlag("--file", dest="logfile", metaName='Synthesis Log', help="Synthesis log file (*.vds).")
62
+ def HandleVivado(self, args: Namespace) -> None:
63
+ """Handle program calls with command ``vivado``."""
64
+ self._PrintHeadline()
65
+
66
+ if args.stdin is True:
67
+ if args.logfile is not None:
68
+ self.WriteError(f"If option '--stdin' is set, then option '--file' can't be set, too.")
69
+ self.Exit(2)
70
+
71
+ self.WriteVerbose("Reading lines from STDIN ...")
72
+ inputFile = sys_stdin
73
+ elif args.logfile is None:
74
+ self.WriteError(f"No input file (<logfile> or '-' for STDIN) specified via option '--file=<logfile>'.")
75
+ self.Exit(2)
76
+ elif args.logfile == "-":
77
+ self.WriteVerbose("Reading lines from STDIN ...")
78
+ inputFile = sys_stdin
79
+ else:
80
+ logfile = Path(args.logfile)
81
+ if not logfile.exists():
82
+ self.WriteError(f"Vivado log file '{logfile}' doesn't exist.")
83
+ self.Exit(3)
84
+
85
+ try:
86
+ inputFile = logfile.open("r")
87
+ except OSError as ex:
88
+ self.WriteError(f"Vivado log file '{logfile}' cannot be opened.")
89
+ self.WriteError(f" {ex}")
90
+ self.Exit(4)
91
+
92
+ processor = Processor()
93
+
94
+ if args.colored:
95
+ writeOutput = self._WriteColoredOutput
96
+ else:
97
+ writeOutput = self._WriteOutput
98
+
99
+ with Stopwatch() as sw:
100
+ next(generator := processor.LineClassification())
101
+ for rawLine in inputFile.readlines():
102
+ line = generator.send(rawLine.rstrip("\r\n"))
103
+
104
+ writeOutput(line)
105
+
106
+ def _WriteOutput(self, line: Line):
107
+ self.WriteNormal(f"{line}")
108
+
109
+ def _WriteColoredOutput(self, line: Line):
110
+ color = self.GetColorOfLine(line)
111
+ message = str(line).replace("{", "{{").replace("}", "}}")
112
+ self.WriteNormal(f"{{{color}}}{message}{{NOCOLOR}}".format(**self.Foreground))
113
+
114
+
115
+ # if args.info:
116
+ # self.WriteNormal(f"INFO messages: {len(processor.InfoMessages)}")
117
+ # for message in processor.InfoMessages:
118
+ # self.WriteNormal(f" {message}")
119
+ # if args.warning:
120
+ # self.WriteNormal(f"WARNING messages: {len(processor.WarningMessages)}")
121
+ # for message in processor.WarningMessages:
122
+ # self.WriteNormal(f" {message}")
123
+ # if args.critical:
124
+ # self.WriteNormal(f"CRITICAL WARNING: messages {len(processor.CriticalWarningMessages)}")
125
+ # for message in processor.CriticalWarningMessages:
126
+ # self.WriteNormal(f" {message}")
127
+ # if args.error:
128
+ # self.WriteNormal(f"ERROR messages: {len(processor.ErrorMessages)}")
129
+ # for message in processor.ErrorMessages:
130
+ # self.WriteNormal(f" {message}")
131
+ #
132
+ # if args.influxdb:
133
+ # synthesizeDesign = processor[SynthesizeDesign]
134
+ # influxString = "vivado_synthesis_overview"
135
+ # influxString += f",version={processor.Preamble.ToolVersion}"
136
+ # influxString += f",branch=main"
137
+ # influxString += f",design=Stopwatch"
138
+ # influxString += " "
139
+ # influxString += f"processing_duration={processor.Duration:.3f}"
140
+ # influxString += f",synthesis_duration={synthesizeDesign[WritingSynthesisReport].Duration:.1f}"
141
+ # influxString += f",info_count={len(processor.InfoMessages)}u"
142
+ # influxString += f",warning_count={len(processor.WarningMessages)}u"
143
+ # influxString += f",critical_count={len(processor.CriticalWarningMessages)}u"
144
+ # influxString += f",error_count={len(processor.ErrorMessages)}u"
145
+ # influxString += f",blackbox_count={len(synthesizeDesign[WritingSynthesisReport].Blackboxes)}u"
146
+ # influxString += "\n"
147
+ # influxString += "vivado_synthesis_cells"
148
+ # influxString += f",version={processor.Preamble.ToolVersion}"
149
+ # influxString += f",branch=main"
150
+ # influxString += f",design=Stopwatch"
151
+ # influxString += " "
152
+ # influxString += ",".join(f"{cellName}={cellCount}" for cellName, cellCount in synthesizeDesign[WritingSynthesisReport].Cells.items() if not cellName.endswith("_bbox"))
153
+ #
154
+ # self.WriteNormal(influxString)
155
+ #
156
+ # if args.summary:
157
+ # synthesizeDesign : SynthesizeDesign = processor[SynthesizeDesign]
158
+ # self.WriteNormal("Summary:")
159
+ # self.WriteNormal(f" Tool version: {processor.Preamble.ToolVersion}")
160
+ # self.WriteNormal(f" Started at: {processor.Preamble.StartDatetime}")
161
+ # self.WriteNormal(f" Processing duration: {processor.Duration:.3f} s")
162
+ # self.WriteNormal(f" Info: {len(processor.InfoMessages)}")
163
+ # self.WriteNormal(f" Warning: {len(processor.WarningMessages)}")
164
+ # self.WriteNormal(f" Critical Warning: {len(processor.CriticalWarningMessages)}")
165
+ # self.WriteNormal(f" Error: {len(processor.ErrorMessages)}")
166
+ # self.WriteNormal(f" Part: {synthesizeDesign[LoadingPart].Part}")
167
+ #
168
+ # self.WriteNormal("Policies:")
169
+ # self.WriteNormal(f" Latches: {'found' if synthesizeDesign.HasLatches else '----'}")
170
+ # if synthesizeDesign.HasLatches:
171
+ # for cellName in ("LD", ):
172
+ # try:
173
+ # self.WriteNormal(f" {cellName}: {synthesizeDesign.Cells[cellName]}")
174
+ # except KeyError:
175
+ # pass
176
+ # for latch in synthesizeDesign.Latches:
177
+ # self.WriteNormal(f" {latch}")
178
+ # self.WriteNormal(f" Blackboxes: {'found' if synthesizeDesign.HasBlackboxes else '----'}")
179
+ # if synthesizeDesign.HasBlackboxes:
180
+ # for bbox in synthesizeDesign.Blackboxes:
181
+ # self.WriteNormal(f" {bbox}")
182
+ #
183
+ # self.WriteNormal(f"VHDL report statements ({len(synthesizeDesign.VHDLReportMessages)}):")
184
+ # for message in synthesizeDesign.VHDLReportMessages:
185
+ # self.WriteNormal(f" {message}")
186
+ # self.WriteNormal(f"VHDL assert statements ({len(synthesizeDesign.VHDLAssertMessages)}):")
187
+ # for message in synthesizeDesign.VHDLAssertMessages:
188
+ # self.WriteNormal(f" {message}")
189
+ #
190
+ # self.WriteNormal(f"Cells: {len(synthesizeDesign.Cells)}")
191
+ # for cell, count in synthesizeDesign.Cells.items():
192
+ # self.WriteNormal(f" {cell}: {count}")
193
+
194
+ self.ExitOnPreviousErrors()
195
+
196
+ def GetColorOfLine(self, line: Line) -> str:
197
+ colorDict = {
198
+ "normal": "WHITE",
199
+ "info": "GRAY", # "DARK_BLUE",
200
+ "warning": "YELLOW",
201
+ "critical": "MAGENTA",
202
+ "error": "RED",
203
+ "tcl": "CYAN",
204
+ "success": "GREEN",
205
+ "failed": "RED",
206
+ "verbose": "GRAY",
207
+ "unprocessed": "DARK_GRAY",
208
+ "empty": "NOCOLOR",
209
+ "sectionDelimiter": "DARK_GRAY",
210
+ "sectionStart": "DARK_CYAN",
211
+ "sectionEnd": "DARK_CYAN",
212
+ "sectionTime": "DARK_GREEN",
213
+ "subsectionStart": "DARK_CYAN",
214
+ "subsectionEnd": "DARK_CYAN",
215
+ "subsectionTime": "DARK_GREEN",
216
+ "taskStart": "YELLOW",
217
+ "taskEnd": "YELLOW",
218
+ "taskTime": "DARK_GREEN",
219
+ "phaseStart": "BLUE",
220
+ "phaseEnd": "BLUE",
221
+ "phaseTime": "DARK_GREEN",
222
+ "subphaseStart": "DARK_CYAN",
223
+ "subphaseEnd": "DARK_CYAN",
224
+ "subphaseTime": "DARK_GREEN",
225
+ "subsubphaseStart": "DARK_CYAN",
226
+ "subsubphaseEnd": "DARK_CYAN",
227
+ "subsubphaseTime": "DARK_GREEN",
228
+ "subsubsubphaseStart": "DARK_CYAN",
229
+ "subsubsubphaseEnd": "DARK_CYAN",
230
+ "subsubsubphaseTime": "DARK_GREEN",
231
+ "paragraphHeadline": "DARK_YELLOW",
232
+ "hierarchyStart": "DARK_CYAN",
233
+ "hierarchyEnd": "DARK_GRAY",
234
+ "xdcStart": "DARK_CYAN",
235
+ "xdcEnd": "DARK_GRAY",
236
+ "table": "GRAY",
237
+ }
238
+
239
+ if line._kind is LineKind.Normal:
240
+ return colorDict["normal"]
241
+ elif LineKind.Message in line.Kind:
242
+ if line.Kind is LineKind.InfoMessage:
243
+ return colorDict["info"]
244
+ elif line.Kind is LineKind.WarningMessage:
245
+ return colorDict["warning"]
246
+ elif line.Kind is LineKind.CriticalWarningMessage:
247
+ return colorDict["critical"]
248
+ elif line.Kind is LineKind.ErrorMessage:
249
+ return colorDict["error"]
250
+ elif LineKind.TclCommand in line.Kind:
251
+ return colorDict["tcl"]
252
+ elif LineKind.Success in line.Kind:
253
+ return colorDict["success"]
254
+ elif LineKind.Failed in line.Kind:
255
+ return colorDict["failed"]
256
+ elif LineKind.Verbose in line.Kind:
257
+ return colorDict["verbose"]
258
+ elif line.Kind is LineKind.Unprocessed:
259
+ return colorDict["unprocessed"]
260
+ elif line.Kind is LineKind.Empty:
261
+ return colorDict["empty"]
262
+ elif LineKind.Start in line.Kind:
263
+ if LineKind.Task in line.Kind:
264
+ return colorDict["taskStart"]
265
+ elif LineKind.Phase in line.Kind:
266
+ return colorDict["phaseStart"]
267
+ elif LineKind.SubPhase in line.Kind:
268
+ return colorDict["subphaseStart"]
269
+ elif LineKind.SubSubPhase in line.Kind:
270
+ return colorDict["subsubphaseStart"]
271
+ elif LineKind.SubSubSubPhase in line.Kind:
272
+ return colorDict["subsubsubphaseStart"]
273
+ elif LineKind.Section in line.Kind:
274
+ return colorDict["sectionStart"]
275
+ elif LineKind.SubSection in line.Kind:
276
+ return colorDict["subsectionStart"]
277
+ else:
278
+ raise Exception(f"Unknown LineKind.****Start '{line._kind}' for line {line._lineNumber}.")
279
+ elif LineKind.End in line.Kind:
280
+ if LineKind.Task in line.Kind:
281
+ return colorDict["taskEnd"]
282
+ elif LineKind.Phase in line.Kind:
283
+ return colorDict["phaseEnd"]
284
+ elif LineKind.SubPhase in line.Kind:
285
+ return colorDict["subphaseEnd"]
286
+ elif LineKind.SubSubPhase in line.Kind:
287
+ return colorDict["subsubphaseEnd"]
288
+ elif LineKind.SubSubSubPhase in line.Kind:
289
+ return colorDict["subsubsubphaseEnd"]
290
+ elif LineKind.Section in line.Kind:
291
+ return colorDict["sectionEnd"]
292
+ elif LineKind.SubSection in line.Kind:
293
+ return colorDict["subsectionEnd"]
294
+ else:
295
+ raise Exception(f"Unknown LineKind.****End '{line._kind}' for line {line._lineNumber}.")
296
+ elif LineKind.Time in line.Kind:
297
+ if LineKind.Task in line.Kind:
298
+ return colorDict["taskTime"]
299
+ elif LineKind.Phase in line.Kind:
300
+ return colorDict["phaseTime"]
301
+ elif LineKind.SubPhase in line.Kind:
302
+ return colorDict["subphaseTime"]
303
+ elif LineKind.SubSubPhase in line.Kind:
304
+ return colorDict["subsubphaseTime"]
305
+ elif LineKind.SubSubSubPhase in line.Kind:
306
+ return colorDict["subsubsubphaseTime"]
307
+ elif LineKind.Section in line.Kind:
308
+ return colorDict["sectionTime"]
309
+ elif LineKind.SubSection in line.Kind:
310
+ return colorDict["subsectionTime"]
311
+ else:
312
+ raise Exception(f"Unknown LineKind.****Time '{line._kind}' for line {line._lineNumber}.")
313
+ elif LineKind.Table in line.Kind:
314
+ return colorDict["table"]
315
+ elif LineKind.Delimiter in line.Kind:
316
+ if LineKind.Section in line.Kind:
317
+ return colorDict["sectionDelimiter"]
318
+ else:
319
+ raise Exception(f"Unknown LineKind.****Delimiter '{line._kind}' for line {line._lineNumber}.")
320
+ elif line.Kind is LineKind.PhaseFinal:
321
+ return colorDict["verbose"]
322
+ elif line.Kind is LineKind.ParagraphHeadline:
323
+ return colorDict["paragraphHeadline"]
324
+ elif line.Kind is LineKind.ProcessorError:
325
+ raise Exception(f"Erroneous line {line._lineNumber} '{line._kind}' should have been wrapped in an exception.")
326
+ elif LineKind.Table in line.Kind:
327
+ raise Exception()
328
+ elif LineKind.Delimiter in line.Kind:
329
+ raise Exception()
330
+ else:
331
+ raise Exception(f"Unknown LineKind '{line._kind}' for line {line._lineNumber}.")