Coverage for pyEDAA/OSVVM/Project/__init__.py: 91%
470 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-27 22:24 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-27 22:24 +0000
1# ==================================================================================================================== #
2# _____ ____ _ _ ___ ______ ____ ____ __ #
3# _ __ _ _| ____| _ \ / \ / \ / _ \/ ___\ \ / /\ \ / / \/ | #
4# | '_ \| | | | _| | | | |/ _ \ / _ \ | | | \___ \\ \ / / \ \ / /| |\/| | #
5# | |_) | |_| | |___| |_| / ___ \ / ___ \ | |_| |___) |\ V / \ V / | | | | #
6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___/|____/ \_/ \_/ |_| |_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2025-2025 Patrick Lehmann - Boetzingen, Germany #
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#
31from pathlib import Path
32from typing import Optional as Nullable, List, Dict, Mapping, Iterable, TypeVar, Generic, Generator
34from pyTooling.Common import getFullyQualifiedName
35from pyTooling.Decorators import readonly, export
36from pyTooling.MetaClasses import ExtendedType
37from pyVHDLModel import VHDLVersion
39from pyEDAA.OSVVM import OSVVMException
42__all__ = ["osvvmContext"]
45_ParentType = TypeVar("_ParentType", bound="Base")
48@export
49class Base(Generic[_ParentType], metaclass=ExtendedType, slots=True):
50 _parent: Nullable[_ParentType]
52 def __init__(self, parent: Nullable[_ParentType] = None):
53 self._parent = parent
55 @readonly
56 def Parent(self) -> _ParentType:
57 return self._parent
60@export
61class Named(Base[_ParentType], Generic[_ParentType]):
62 _name: str
64 def __init__(
65 self,
66 name: str,
67 parent: Nullable[_ParentType] = None
68 ) -> None:
69 super().__init__(parent)
71 if not isinstance(name, str): # pragma: no cover
72 ex = TypeError(f"Parameter 'name' is not a string.")
73 ex.add_note(f"Got type '{getFullyQualifiedName(name)}'.")
74 raise ex
76 self._name = name
78 @readonly
79 def Name(self) -> str:
80 return self._name
82 def __repr__(self) -> str:
83 return f"{self.__class__.__name__}: {self._name}"
86@export
87class Option(metaclass=ExtendedType, slots=True):
88 pass
91@export
92class NoNullRangeWarning(Option):
93 def __init__(self) -> None:
94 super().__init__()
96 def __repr__(self) -> str:
97 return "NoNullRangeWarning"
100@export
101class SourceFile(Base[_ParentType], Generic[_ParentType]):
102 """A base-class describing any source file (VHDL, Verilog, ...) supported by OSVVM Scripts."""
104 _path: Path
106 def __init__(
107 self,
108 path: Path,
109 parent: Nullable[Base] = None
110 ) -> None:
111 super().__init__(parent)
113 if not isinstance(path, Path): # pragma: no cover
114 ex = TypeError(f"Parameter 'path' is not a Path.")
115 ex.add_note(f"Got type '{getFullyQualifiedName(path)}'.")
116 raise ex
118 self._path = path
120 @readonly
121 def Path(self) -> Path:
122 """
123 Read-only property to access the path to the sourcefile.
125 :returns: The sourcefile's path.
126 """
127 return self._path
129 def __repr__(self) -> str:
130 return f"SourceFile: {self._path}"
133@export
134class VHDLSourceFile(SourceFile["VHDLLibrary"]):
135 _vhdlVersion: VHDLVersion
136 _noNullRangeWarning: Nullable[bool]
138 def __init__(
139 self,
140 path: Path,
141 vhdlVersion: VHDLVersion = VHDLVersion.VHDL2008,
142 vhdlLibrary: Nullable["VHDLLibrary"] = None,
143 noNullRangeWarning: Nullable[bool] = None
144 ):
145 if vhdlLibrary is None:
146 super().__init__(path, None)
147 elif isinstance(vhdlLibrary, VHDLLibrary):
148 super().__init__(path, vhdlLibrary)
149 vhdlLibrary._files.append(self)
150 else: # pragma: no cover
151 ex = TypeError(f"Parameter 'vhdlLibrary' is not a Library.")
152 ex.add_note(f"Got type '{getFullyQualifiedName(vhdlLibrary)}'.")
153 raise ex
155 if not isinstance(vhdlVersion, VHDLVersion): # pragma: no cover
156 ex = TypeError(f"Parameter 'vhdlVersion' is not a VHDLVersion.")
157 ex.add_note(f"Got type '{getFullyQualifiedName(vhdlVersion)}'.")
158 raise ex
160 self._vhdlVersion = vhdlVersion
162 if noNullRangeWarning is not None and not isinstance(noNullRangeWarning, bool): 162 ↛ 163line 162 didn't jump to line 163 because the condition on line 162 was never true
163 ex = TypeError(f"Parameter 'noNullRangeWarning' is not a boolean.")
164 ex.add_note(f"Got type '{getFullyQualifiedName(noNullRangeWarning)}'.")
165 raise ex
167 self._noNullRangeWarning = noNullRangeWarning
169 @readonly
170 def VHDLLibrary(self) -> Nullable["VHDLLibrary"]:
171 return self._parent
173 @property
174 def VHDLVersion(self) -> VHDLVersion:
175 return self._vhdlVersion
177 @VHDLVersion.setter
178 def VHDLVersion(self, value: VHDLVersion) -> None:
179 if not isinstance(value, VHDLVersion): 179 ↛ 180line 179 didn't jump to line 180 because the condition on line 179 was never true
180 ex = TypeError(f"Parameter 'value' is not a VHDLVersion.")
181 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
182 raise ex
184 self._vhdlVersion = value
186 @property
187 def NoNullRangeWarning(self) -> bool:
188 return self._noNullRangeWarning
190 @NoNullRangeWarning.setter
191 def NoNullRangeWarning(self, value: bool) -> None:
192 if value is not None and not isinstance(value, bool):
193 ex = TypeError(f"Parameter 'value' is not a boolean.")
194 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
195 raise ex
197 self._noNullRangeWarning = value
199 def __repr__(self) -> str:
200 options = ""
201 if self._noNullRangeWarning is not None: 201 ↛ 202line 201 didn't jump to line 202 because the condition on line 201 was never true
202 options += f", NoNullRangeWarning"
203 return f"VHDLSourceFile: {self._path} ({self._vhdlVersion}{options})"
205@export
206class VHDLLibrary(Named["Build"]):
207 """A VHDL library collecting multiple VHDL files containing VHDL design units."""
209 _files: List[VHDLSourceFile]
211 def __init__(
212 self,
213 name: str,
214 vhdlFiles: Nullable[Iterable[VHDLSourceFile]] = None,
215 build: Nullable["Build"] = None
216 ) -> None:
217 if build is None:
218 super().__init__(name, None)
219 elif isinstance(build, Build):
220 super().__init__(name, build)
221 build._vhdlLibraries[name] = self
222 else: # pragma: no cover
223 ex = TypeError(f"Parameter 'build' is not a Build.")
224 ex.add_note(f"Got type '{getFullyQualifiedName(build)}'.")
225 raise ex
227 self._files = []
228 if vhdlFiles is None:
229 pass
230 elif isinstance(vhdlFiles, Iterable):
231 for vhdlFile in vhdlFiles:
232 vhdlFile._parent = self
233 self._files.append(vhdlFile)
234 else: # pragma: no cover
235 ex = TypeError(f"Parameter 'vhdlFiles' is not an iterable of VHDLSourceFile.")
236 ex.add_note(f"Got type '{getFullyQualifiedName(vhdlFiles)}'.")
237 raise ex
239 @readonly
240 def Build(self) -> Nullable["Build"]:
241 return self._parent
243 @readonly
244 def Files(self) -> List[SourceFile]:
245 return self._files
247 def AddFile(self, file: VHDLSourceFile) -> None:
248 if not isinstance(file, VHDLSourceFile): # pragma: no cover
249 ex = TypeError(f"Parameter 'file' is not a VHDLSourceFile.")
250 ex.add_note(f"Got type '{getFullyQualifiedName(file)}'.")
251 raise ex
253 file._parent = self
254 self._files.append(file)
256 def __repr__(self) -> str:
257 return f"VHDLLibrary: {self._name}"
260@export
261class GenericValue(Option):
262 _name: str
263 _value: str
265 def __init__(
266 self,
267 name: str,
268 value: str
269 ) -> None:
270 super().__init__()
272 if not isinstance(name, str): # pragma: no cover
273 ex = TypeError(f"Parameter 'name' is not a string.")
274 ex.add_note(f"Got type '{getFullyQualifiedName(name)}'.")
275 raise ex
277 self._name = name
279 if not isinstance(value, str): # pragma: no cover
280 ex = TypeError(f"Parameter 'value' is not a string.")
281 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
282 raise ex
284 self._value = value
286 @readonly
287 def Name(self) -> str:
288 return self._name
290 @readonly
291 def Value(self) -> str:
292 return self._value
294 def __repr__(self) -> str:
295 return f"{self._name} = {self._value}"
298@export
299class Testcase(Named["Testsuite"]):
300 _toplevelName: Nullable[str]
301 _generics: Dict[str, str]
303 def __init__(
304 self,
305 name: str,
306 toplevelName: Nullable[str] = None,
307 generics: Nullable[Iterable[GenericValue] | Mapping[str, str]] = None,
308 testsuite: Nullable["Testsuite"] = None
309 ) -> None:
310 if testsuite is None:
311 super().__init__(name, None)
312 elif isinstance(testsuite, Testsuite):
313 super().__init__(name, testsuite)
314 testsuite._testcases[name] = self
315 else: # pragma: no cover
316 ex = TypeError(f"Parameter 'testsuite' is not a Testsuite.")
317 ex.add_note(f"Got type '{getFullyQualifiedName(testsuite)}'.")
318 raise ex
320 if not (toplevelName is None or isinstance(toplevelName, str)): # pragma: no cover
321 ex = TypeError(f"Parameter 'toplevelName' is not a string.")
322 ex.add_note(f"Got type '{getFullyQualifiedName(toplevelName)}'.")
323 raise ex
325 self._toplevelName = toplevelName
327 self._generics = {}
328 if generics is None:
329 pass
330 elif isinstance(generics, Mapping):
331 for key, value in generics.items():
332 self._generics[key] = value
333 elif isinstance(generics, Iterable):
334 for item in generics:
335 self._generics[item._name] = item._value
336 else: # pragma: no cover
337 ex = TypeError(f"Parameter 'generics' is not an iterable of GenericValue nor a dictionary of strings.")
338 ex.add_note(f"Got type '{getFullyQualifiedName(generics)}'.")
339 raise ex
341 @readonly
342 def Testsuite(self) -> "Testsuite":
343 return self._parent
345 @readonly
346 def ToplevelName(self) -> str:
347 return self._toplevelName
349 @readonly
350 def Generics(self) -> Dict[str, str]:
351 return self._generics
353 def SetToplevel(self, toplevelName: str) -> None:
354 if not isinstance(toplevelName, str): # pragma: no cover
355 ex = TypeError(f"Parameter 'toplevelName' is not a string.")
356 ex.add_note(f"Got type '{getFullyQualifiedName(toplevelName)}'.")
357 raise ex
359 self._toplevelName = toplevelName
361 def AddGeneric(self, genericValue: GenericValue):
362 if not isinstance(genericValue, GenericValue): # pragma: no cover
363 ex = TypeError(f"Parameter 'genericValue' is not a GenericValue.")
364 ex.add_note(f"Got type '{getFullyQualifiedName(genericValue)}'.")
365 raise ex
367 self._generics[genericValue._name] = genericValue._value
369 def __repr__(self) -> str:
370 generics = f" - [{', '.join([f'{n}={v}' for n,v in self._generics.items()])}]" if len(self._generics) > 0 else ""
371 return f"Testcase: {self._name}{generics}"
374@export
375class Testsuite(Named["Build"]):
376 _testcases: Dict[str, Testcase]
378 def __init__(
379 self,
380 name: str,
381 testcases: Nullable[Iterable[Testcase] | Mapping[str, Testcase]] = None,
382 build: Nullable["Build"] = None
383 ) -> None:
384 if build is None:
385 super().__init__(name, None)
386 elif isinstance(build, Build):
387 super().__init__(name, build)
388 build._testsuites[name] = self
389 else: # pragma: no cover
390 ex = TypeError(f"Parameter 'build' is not a Build.")
391 ex.add_note(f"Got type '{getFullyQualifiedName(build)}'.")
392 raise ex
394 self._testcases = {}
395 if testcases is None:
396 pass
397 elif isinstance(testcases, Mapping):
398 for key, value in testcases.items():
399 value._parent = self
400 self._testcases[key] = value
401 elif isinstance(testcases, Iterable):
402 for item in testcases:
403 item._parent = self
404 self._testcases[item._name] = item
405 else: # pragma: no cover
406 ex = TypeError(f"Parameter 'testcases' is not an iterable of Testcase nor a mapping of Testcase.")
407 ex.add_note(f"Got type '{getFullyQualifiedName(testcases)}'.")
408 raise ex
410 @readonly
411 def Build(self) -> Nullable["Build"]:
412 return self._parent
414 @readonly
415 def Testcases(self) -> Dict[str, Testcase]:
416 return self._testcases
418 def AddTestcase(self, testcase: Testcase) -> None:
419 if not isinstance(testcase, Testcase): # pragma: no cover
420 ex = TypeError(f"Parameter 'testcase' is not a Testcase.")
421 ex.add_note(f"Got type '{getFullyQualifiedName(testcase)}'.")
422 raise ex
424 testcase._parent = self
425 self._testcases[testcase._name] = testcase
427 def __repr__(self) -> str:
428 return f"Testsuite: {self._name}"
431@export
432class BuildName(Option):
433 _name: str
435 def __init__(
436 self,
437 name: str,
438 ) -> None:
439 super().__init__()
441 if not isinstance(name, str): # pragma: no cover
442 ex = TypeError(f"Parameter 'name' is not a string.")
443 ex.add_note(f"Got type '{getFullyQualifiedName(name)}'.")
444 raise ex
446 self._name = name
448 @readonly
449 def Name(self) -> str:
450 return self._name
452 def __repr__(self) -> str:
453 return f"BuildName: {self._name}"
456@export
457class Build(Named["Project"]):
458 _includedFiles: List[Path]
459 _vhdlLibraries: Dict[str, VHDLLibrary]
460 _testsuites: Dict[str, Testsuite]
462 def __init__(
463 self,
464 name: str,
465 vhdlLibraries: Nullable[Iterable[VHDLLibrary] | Mapping[str, VHDLLibrary]] = None,
466 testsuites: Nullable[Iterable[Testsuite] | Mapping[str, Testsuite]] = None,
467 project: Nullable[Base] = None
468 ) -> None:
469 if project is None:
470 super().__init__(name, None)
471 elif isinstance(project, Project):
472 super().__init__(name, project)
473 project._builds[name] = self
474 else: # pragma: no cover
475 ex = TypeError(f"Parameter 'project' is not a Project.")
476 ex.add_note(f"Got type '{getFullyQualifiedName(project)}'.")
477 raise ex
479 self._includedFiles = []
480 self._vhdlLibraries = {}
481 if vhdlLibraries is None:
482 pass
483 elif isinstance(vhdlLibraries, Mapping):
484 for key, value in vhdlLibraries.items():
485 value._parent = self
486 self._vhdlLibraries[key] = value
487 elif isinstance(vhdlLibraries, Iterable):
488 for item in vhdlLibraries:
489 item._parent = self
490 self._vhdlLibraries[item._name] = item
491 else: # pragma: no cover
492 ex = TypeError(f"Parameter 'libraries' is not an iterable of VHDLLibrary nor a mapping of VHDLLibrary.")
493 ex.add_note(f"Got type '{getFullyQualifiedName(vhdlLibraries)}'.")
494 raise ex
496 self._testsuites = {}
497 if testsuites is None:
498 pass
499 elif isinstance(testsuites, Mapping):
500 for key, value in testsuites.items():
501 value._parent = self
502 self._testsuites[key] = value
503 elif isinstance(testsuites, Iterable):
504 for item in testsuites:
505 item._parent = self
506 self._testsuites[item._name] = item
507 else: # pragma: no cover
508 ex = TypeError(f"Parameter 'testsuites' is not an iterable of Testsuite nor a mapping of Testsuite.")
509 ex.add_note(f"Got type '{getFullyQualifiedName(testsuites)}'.")
510 raise ex
512 @readonly
513 def Project(self) -> Nullable["Project"]:
514 return self._parent
516 @readonly
517 def IncludedFiles(self) -> Generator[Path, None, None]:
518 return (file for file in self._includedFiles)
520 @readonly
521 def VHDLLibraries(self) -> Dict[str, VHDLLibrary]:
522 return self._vhdlLibraries
524 @readonly
525 def Testsuites(self) -> Dict[str, Testsuite]:
526 return self._testsuites
528 def AddVHDLLibrary(self, vhdlLibrary: VHDLLibrary) -> None:
529 if not isinstance(vhdlLibrary, VHDLLibrary): # pragma: no cover
530 ex = TypeError(f"Parameter 'vhdlLibrary' is not a VHDLLibrary.")
531 ex.add_note(f"Got type '{getFullyQualifiedName(vhdlLibrary)}'.")
532 raise ex
534 vhdlLibrary._parent = self
535 self._vhdlLibraries[vhdlLibrary._name] = vhdlLibrary
537 def AddTestsuite(self, testsuite: Testsuite) -> None:
538 if not isinstance(testsuite, Testsuite): # pragma: no cover
539 ex = TypeError(f"Parameter 'testsuite' is not a Testsuite.")
540 ex.add_note(f"Got type '{getFullyQualifiedName(testsuite)}'.")
541 raise ex
543 testsuite._parent = self
544 self._testsuites[testsuite._name] = testsuite
546 def __repr__(self) -> str:
547 return f"Build: {self._name}"
550@export
551class Project(Named[None]):
552 _builds: Dict[str, Build]
554 def __init__(
555 self,
556 name: str,
557 builds: Nullable[Iterable[Build] | Mapping[str, Build]] = None
558 ) -> None:
559 super().__init__(name, None)
561 self._builds = {}
562 if builds is None:
563 pass
564 elif isinstance(builds, Mapping):
565 for key, value in builds.items():
566 value._parent = self
567 self._builds[key] = value
568 elif isinstance(builds, Iterable):
569 for item in builds:
570 item._parent = self
571 self._builds[item._name] = item
572 else: # pragma: no cover
573 ex = TypeError(f"Parameter 'builds' is not an iterable of Build nor a mapping of Build.")
574 ex.add_note(f"Got type '{getFullyQualifiedName(builds)}'.")
575 raise ex
577 @readonly
578 def Builds(self) -> Dict[str, Build]:
579 return self._builds
581 @readonly
582 def IncludedFiles(self) -> Generator[Path, None, None]:
583 for build in self._builds.values():
584 yield from build.IncludedFiles
586 def AddBuild(self, build: Build) -> None:
587 if not isinstance(build, Build): # pragma: no cover
588 ex = TypeError(f"Parameter 'build' is not a Build.")
589 ex.add_note(f"Got type '{getFullyQualifiedName(build)}'.")
590 raise ex
592 build._parent = self
593 self._builds[build._name] = build
595 def __repr__(self) -> str:
596 return f"Project: {self._name}"
598@export
599class Context(Base):
600 # _tcl: TclEnvironment
602 _processor: "OsvvmProFileProcessor"
603 _lastException: Exception
605 _workingDirectory: Path
606 _currentDirectory: Path
607 _includedFiles: List[Path]
609 _vhdlversion: VHDLVersion
611 _vhdlLibraries: Dict[str, VHDLLibrary]
612 _vhdlLibrary: Nullable[VHDLLibrary]
614 _testsuites: Dict[str, Testsuite]
615 _testsuite: Nullable[Testsuite]
616 _testcase: Nullable[Testcase]
617 _options: Dict[int, Option]
619 _builds: Dict[str, Build]
620 _build: Nullable[Build]
622 def __init__(self) -> None:
623 super().__init__()
625 self._processor = None
626 self._lastException = None
628 self._workingDirectory = Path.cwd()
629 self._currentDirectory = self._workingDirectory
630 self._includedFiles = []
632 self._vhdlversion = VHDLVersion.VHDL2008
634 self._vhdlLibrary = None
635 self._vhdlLibraries = {}
637 self._testcase = None
638 self._testsuite = None
639 self._testsuites = {}
640 self._options = {}
642 self._build = None
643 self._builds = {}
645 def Clear(self) -> None:
646 self._processor = None
647 self._lastException = None
649 self._workingDirectory = Path.cwd()
650 self._currentDirectory = self._workingDirectory
651 self._includedFiles = []
653 self._vhdlversion = VHDLVersion.VHDL2008
655 self._vhdlLibrary = None
656 self._vhdlLibraries = {}
658 self._testcase = None
659 self._testsuite = None
660 self._testsuites = {}
661 self._options = {}
663 self._build = None
664 self._builds = {}
666 @readonly
667 def Processor(self): # -> "Tk":
668 return self._processor
670 @property
671 def LastException(self) -> Exception:
672 lastException = self._lastException
673 self._lastException = None
674 return lastException
676 @LastException.setter
677 def LastException(self, value: Exception) -> None:
678 self._lastException = value
680 @readonly
681 def WorkingDirectory(self) -> Path:
682 return self._workingDirectory
684 @readonly
685 def CurrentDirectory(self) -> Path:
686 return self._currentDirectory
688 @property
689 def VHDLVersion(self) -> VHDLVersion:
690 return self._vhdlversion
692 @VHDLVersion.setter
693 def VHDLVersion(self, value: VHDLVersion) -> None:
694 self._vhdlversion = value
696 @readonly
697 def IncludedFiles(self) -> List[Path]:
698 return self._includedFiles
700 @readonly
701 def VHDLLibraries(self) -> Dict[str, VHDLLibrary]:
702 return self._vhdlLibraries
704 @readonly
705 def VHDLLibrary(self) -> VHDLLibrary:
706 return self._vhdlLibrary
708 @readonly
709 def Testsuites(self) -> Dict[str, Testsuite]:
710 return self._testsuites
712 @readonly
713 def Testsuite(self) -> Testsuite:
714 return self._testsuite
716 @readonly
717 def TestCase(self) -> Testcase:
718 return self._testcase
720 @readonly
721 def Build(self) -> Build:
722 return self._build
724 @readonly
725 def Builds(self) -> Dict[str, Build]:
726 return self._builds
728 def ToProject(self, projectName: str) -> Project:
729 project = Project(projectName, self._builds)
731 return project
733 def BeginBuild(self, buildName: str) -> Build:
734 if len(self._vhdlLibraries) > 0: 734 ↛ 735line 734 didn't jump to line 735 because the condition on line 734 was never true
735 raise OSVVMException(f"VHDL libraries have been created outside of an OSVVM build script.")
736 if len(self._testsuites) > 0: 736 ↛ 737line 736 didn't jump to line 737 because the condition on line 736 was never true
737 raise OSVVMException(f"Testsuites have been created outside of an OSVVM build script.")
739 build = Build(buildName)
740 build._vhdlLibraries = self._vhdlLibraries
741 build._testsuites = self._testsuites
743 self._build = build
744 self._builds[buildName] = build
746 return build
748 def EndBuild(self) -> Build:
749 build = self._build
751 self._vhdlLibrary = None
752 self._vhdlLibraries = {}
753 self._testcase = None
754 self._testsuite = None
755 self._testsuites = {}
756 self._build = None
758 return build
760 def IncludeFile(self, proFileOrBuildDirectory: Path) -> Path:
761 if not isinstance(proFileOrBuildDirectory, Path): # pragma: no cover
762 ex = TypeError(f"Parameter 'proFileOrBuildDirectory' is not a Path.")
763 ex.add_note(f"Got type '{getFullyQualifiedName(proFileOrBuildDirectory)}'.")
764 self._lastException = ex
765 raise ex
767 if proFileOrBuildDirectory.is_absolute(): 767 ↛ 768line 767 didn't jump to line 768 because the condition on line 767 was never true
768 ex = OSVVMException(f"Absolute path '{proFileOrBuildDirectory}' not supported.")
769 self._lastException = ex
770 raise ex
772 path = (self._currentDirectory / proFileOrBuildDirectory).resolve()
773 if path.is_file():
774 if path.suffix == ".pro": 774 ↛ 778line 774 didn't jump to line 778 because the condition on line 774 was always true
775 self._currentDirectory = path.parent.relative_to(self._workingDirectory, walk_up=True)
776 proFile = self._currentDirectory / path.name
777 else:
778 ex = OSVVMException(f"Path '{proFileOrBuildDirectory}' is not a *.pro file.")
779 self._lastException = ex
780 raise ex
781 elif path.is_dir():
782 self._currentDirectory = path
783 proFile = path / "build.pro"
784 if not proFile.exists():
785 proFile = path / f"{path.name}.pro"
786 if not proFile.exists(): # pragma: no cover
787 ex = OSVVMException(f"Path '{proFileOrBuildDirectory}' is not a build directory.")
788 ex.__cause__ = FileNotFoundError(path / "build.pro")
789 self._lastException = ex
790 raise ex
791 else: # pragma: no cover
792 ex = OSVVMException(f"Path '{proFileOrBuildDirectory}' is not a *.pro file or build directory.")
793 self._lastException = ex
794 raise ex
796 self._includedFiles.append(proFile)
797 return proFile
799 def EvaluateFile(self, proFile: Path) -> None:
800 self._processor.EvaluateProFile(proFile)
802 def SetLibrary(self, name: str):
803 try:
804 self._vhdlLibrary = self._vhdlLibraries[name]
805 except KeyError:
806 self._vhdlLibrary = VHDLLibrary(name, build=self._build)
807 self._vhdlLibraries[name] = self._vhdlLibrary
809 def AddVHDLFile(self, vhdlFile: VHDLSourceFile) -> None:
810 if self._vhdlLibrary is None:
811 self.SetLibrary("default")
813 vhdlFile.VHDLVersion = self._vhdlversion
814 self._vhdlLibrary.AddFile(vhdlFile)
816 def SetTestsuite(self, testsuiteName: str):
817 try:
818 self._testsuite = self._testsuites[testsuiteName]
819 except KeyError:
820 self._testsuite = Testsuite(testsuiteName)
821 self._testsuites[testsuiteName] = self._testsuite
823 def AddTestcase(self, testName: str) -> TestCase:
824 if self._testsuite is None:
825 self.SetTestsuite("default")
827 self._testcase = Testcase(testName)
828 self._testsuite._testcases[testName] = self._testcase
830 return self._testcase
832 def SetTestcaseToplevel(self, toplevel: str) -> TestCase:
833 if self._testcase is None: 833 ↛ 834line 833 didn't jump to line 834 because the condition on line 833 was never true
834 ex = OSVVMException("Can't set testcase toplevel, because no testcase was setup.")
835 self._lastException = ex
836 raise ex
838 self._testcase.SetToplevel(toplevel)
840 return self._testcase
842 def AddOption(self, option: Option) -> int:
843 optionID = id(option)
844 self._options[optionID] = option
846 return optionID
849osvvmContext: Context = Context()
850"""
851Global OSVVM processing context.
853:type: Context
854"""