diff --git a/doc/Dependency.rst b/doc/Dependency.rst index 520f2c7ea..c0da885eb 100644 --- a/doc/Dependency.rst +++ b/doc/Dependency.rst @@ -23,7 +23,7 @@ pyVHDLModel Package +--------------------------------------------------------+-------------+------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ | **Package** | **Version** | **License** | **Dependencies** | +========================================================+=============+==========================================================================================+=================================================================================================================================+ -| `pyTooling `__ | ≥8.7 | `Apache License, 2.0 `__ | *None* | +| `pyTooling `__ | ≥8.8 | `Apache License, 2.0 `__ | *None* | +--------------------------------------------------------+-------------+------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ @@ -51,7 +51,7 @@ the mandatory dependencies too. +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ | **Package** | **Version** | **License** | **Dependencies** | +=====================================================================+=============+========================================================================================+======================+ -| `pytest `__ | ≥8.4 | `MIT `__ | *Not yet evaluated.* | +| `pytest `__ | ≥9.0 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ | `pytest-cov `__ | ≥7.0 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ @@ -89,7 +89,7 @@ the mandatory dependencies too. +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+----------------------+ | **Package** | **Version** | **License** | **Dependencies** | +=================================================================================================+==============+==========================================================================================================+======================+ -| `pyTooling `__ | ≥8.7 | `Apache License, 2.0 `__ | *None* | +| `pyTooling `__ | ≥8.8 | `Apache License, 2.0 `__ | *None* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+----------------------+ | `Sphinx `__ | ≥8.2 | `BSD 3-Clause `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+----------------------+ @@ -129,7 +129,7 @@ install the mandatory dependencies too. +----------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | **Package** | **Version** | **License** | **Dependencies** | +============================================================================+==============+==========================================================================================================+======================================================================================================================================================+ -| `pyTooling `__ | ≥8.7 | `Apache License, 2.0 `__ | *None* | +| `pyTooling `__ | ≥8.8 | `Apache License, 2.0 `__ | *None* | +----------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | `wheel `__ | ≥0.45 | `MIT `__ | *Not yet evaluated.* | +----------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/pyVHDLModel/Exception.py b/pyVHDLModel/Exception.py index 18f50a7c0..a26cfe889 100644 --- a/pyVHDLModel/Exception.py +++ b/pyVHDLModel/Exception.py @@ -35,28 +35,36 @@ The module ``Exceptions`` contains all structured errors that are raised by pyVHDLModel. Besides a default error message in english, each exception object contains one or multiple references to the exception's context. """ -from sys import version_info -from typing import List - from pyTooling.Decorators import export, readonly +from pyTooling.Warning import Warning, CriticalWarning + +from pyVHDLModel.Symbol import Symbol + + +@export +class VHDLModelWarning(Warning): + pass + + +@export +class NotImplementedWarning(VHDLModelWarning): + pass + -from pyVHDLModel.Symbol import Symbol +@export +class VHDLModelCriticalWarning(Warning): + pass + + +@export +class BlackboxWarning(VHDLModelCriticalWarning): + pass @export class VHDLModelException(Exception): """Base-class for all exceptions (errors) raised by pyVHDLModel.""" - # WORKAROUND: for Python <3.11 - # Implementing a dummy method for Python versions before - __notes__: List[str] - if version_info < (3, 11): # pragma: no cover - def add_note(self, message: str) -> None: - try: - self.__notes__.append(message) - except AttributeError: - self.__notes__ = [message] - @export class LibraryExistsInDesignError(VHDLModelException): diff --git a/pyVHDLModel/Expression.py b/pyVHDLModel/Expression.py index 2bd8815d4..b50b76038 100644 --- a/pyVHDLModel/Expression.py +++ b/pyVHDLModel/Expression.py @@ -35,7 +35,7 @@ All declarations for literals, aggregates, operators forming an expressions. """ from enum import Flag -from typing import Tuple, List, Iterable, Union, ClassVar +from typing import Tuple, List, Iterable, Union, ClassVar, Optional as Nullable from pyTooling.Decorators import export, readonly @@ -211,77 +211,76 @@ class BitStringBase(Flag): @export class BitStringLiteral(Literal): # _base: ClassVar[BitStringBase] - _value: str - _bits: int + _value: str + _binaryValue: str + _bits: int + _length: Nullable[int] + _signed: Nullable[bool] - def __init__(self, value: str) -> None: + def __init__(self, value: str, length: Nullable[int] = None, signed: Nullable[bool] = None) -> None: super().__init__() - self._bits = len(value) self._value = value + self._length = length + self._signed = signed - @readonly - def Bits(self) -> int: - return self._bits + self._binaryValue = None + self._bits = None @readonly def Value(self) -> str: return self._value + @readonly + def BinaryValue(self) -> str: + return self._binaryValue + + @readonly + def Bits(self) -> Nullable[int]: + return self._bits + + @readonly + def Length(self) -> Nullable[int]: + return self._length + + @readonly + def Signed(self) -> Nullable[bool]: + return self._signed + def __str__(self) -> str: - return "\"" + self._value + "\"" + signed = "" if self._signed is None else "s" if self._signed is True else "u" + if self._base is BitStringBase.NoBase: + base = "" + elif self._base is BitStringBase.Binary: + base = "b" + elif self._base is BitStringBase.Octal: + base = "o" + elif self._base is BitStringBase.Decimal: + base = "d" + elif self._base is BitStringBase.Hexadecimal: + base = "x" + length = "" if self._length is None else str(self._length) + return length + signed + base + "\"" + self._value + "\"" @export class BinaryBitStringLiteral(BitStringLiteral): _base: ClassVar[BitStringBase] = BitStringBase.Binary - def __init__(self, value: str, bits: int = 0) -> None: - super().__init__(value) - if bits > 0: - self._bits = bits - - def __str__(self) -> str: - return "b\"" + self._value + "\"" - @export class OctalBitStringLiteral(BitStringLiteral): _base: ClassVar[BitStringBase] = BitStringBase.Octal - def __init__(self, value: str, bits: int = 0) -> None: - super().__init__(value) - if bits > 0: - self._bits = bits - - def __str__(self) -> str: - return "o\"" + self._value + "\"" - @export class DecimalBitStringLiteral(BitStringLiteral): _base: ClassVar[BitStringBase] = BitStringBase.Decimal - def __init__(self, value: str, bits: int = 0) -> None: - super().__init__(value) - if bits > 0: - self._bits = bits - - def __str__(self) -> str: - return "d\"" + self._value + "\"" - @export class HexadecimalBitStringLiteral(BitStringLiteral): _base: ClassVar[BitStringBase] = BitStringBase.Hexadecimal - def __init__(self, value: str, bits: int = 0) -> None: - super().__init__(value) - if bits > 0: - self._bits = bits - - def __str__(self) -> str: - return "x\"" + self._value + "\"" - @export class ParenthesisExpression: #(Protocol): diff --git a/pyVHDLModel/Regions.py b/pyVHDLModel/Regions.py index 9754497cc..98c84e2b4 100644 --- a/pyVHDLModel/Regions.py +++ b/pyVHDLModel/Regions.py @@ -34,7 +34,7 @@ tbd. """ -from typing import List, Dict, Iterable, Optional as Nullable +from typing import List, Dict, Iterable, Optional as Nullable, Any from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType @@ -61,6 +61,7 @@ class ConcurrentDeclarationRegionMixin(metaclass=ExtendedType, mixin=True): # _subprograms: Dict[str, Dict[str, Subprogram]] #: Dictionary of all subprograms declared in this concurrent declaration region. _functions: Dict[str, Dict[str, Function]] #: Dictionary of all functions declared in this concurrent declaration region. _procedures: Dict[str, Dict[str, Procedure]] #: Dictionary of all procedures declared in this concurrent declaration region. + _components: Dict[str, Any] #: Dictionary of all components declared in this concurrent declaration region. def __init__(self, declaredItems: Nullable[Iterable] = None) -> None: # TODO: extract to mixin @@ -80,6 +81,7 @@ def __init__(self, declaredItems: Nullable[Iterable] = None) -> None: # self._subprograms = {} self._functions = {} self._procedures = {} + self._components = {} @readonly def DeclaredItems(self) -> List: @@ -125,6 +127,10 @@ def Functions(self) -> Dict[str, Dict[str, Function]]: def Procedures(self) -> Dict[str, Dict[str, Procedure]]: return self._procedures + @readonly + def Components(self) -> Dict[str, Any]: + return self._components + def IndexDeclaredItems(self) -> None: """ Index declared items listed in the concurrent declaration region. @@ -155,6 +161,8 @@ def IndexDeclaredItems(self) -> None: :meth:`pyVHDLModel.Library._IndexOtherDeclaredItem` Iterate all packages in the library and index declared items. """ + from pyVHDLModel.DesignUnit import Component + for item in self._declaredItems: if isinstance(item, FullType): self._types[item._normalizedIdentifier] = item @@ -187,6 +195,9 @@ def IndexDeclaredItems(self) -> None: for normalizedIdentifier in item._normalizedIdentifiers: self._files[normalizedIdentifier] = item self._namespace._elements[normalizedIdentifier] = item + elif isinstance(item, Component): + self._components[item._normalizedIdentifier] = item + self._namespace._elements[item._normalizedIdentifier] = item else: self._IndexOtherDeclaredItem(item) diff --git a/pyVHDLModel/STD.py b/pyVHDLModel/STD.py index 40aceb937..f9e7d9e58 100644 --- a/pyVHDLModel/STD.py +++ b/pyVHDLModel/STD.py @@ -36,8 +36,8 @@ from pyVHDLModel.Base import Range, Direction from pyVHDLModel.Name import SimpleName from pyVHDLModel.Symbol import SimpleSubtypeSymbol -from pyVHDLModel.Expression import EnumerationLiteral, IntegerLiteral, PhysicalIntegerLiteral -from pyVHDLModel.Type import EnumeratedType, IntegerType, Subtype, PhysicalType, ArrayType +from pyVHDLModel.Expression import EnumerationLiteral, IntegerLiteral, FloatingPointLiteral, PhysicalIntegerLiteral +from pyVHDLModel.Type import EnumeratedType, IntegerType, RealType, PhysicalType, ArrayType, AccessType, Subtype from pyVHDLModel.Predefined import PredefinedLibrary, PredefinedPackage, PredefinedPackageBody @@ -122,6 +122,9 @@ def __init__(self) -> None: self._declaredItems.append(integer) # real + real = RealType("real", Range(FloatingPointLiteral(-5.0), FloatingPointLiteral(5.0), Direction.To), None) + self._types[real._normalizedIdentifier] = real + self._declaredItems.append(real) time = PhysicalType("time", Range(IntegerLiteral(-2**63), IntegerLiteral(2**63 - 1), Direction.To), primaryUnit="fs", units=( ("ps", PhysicalIntegerLiteral(1000, "fs")), @@ -155,6 +158,10 @@ def __init__(self) -> None: self._types[string._normalizedIdentifier] = string self._declaredItems.append(string) + line = AccessType("line", SimpleSubtypeSymbol(SimpleName("character")), None) + self._types[line._normalizedIdentifier] = line + self._declaredItems.append(line) + booleanVector = ArrayType("boolean_vector", (SimpleSubtypeSymbol(SimpleName("natural")),), SimpleSubtypeSymbol(SimpleName("boolean")), None) self._types[booleanVector._normalizedIdentifier] = booleanVector self._declaredItems.append(booleanVector) diff --git a/pyVHDLModel/__init__.py b/pyVHDLModel/__init__.py index 646e85648..2d8fd649d 100644 --- a/pyVHDLModel/__init__.py +++ b/pyVHDLModel/__init__.py @@ -48,7 +48,7 @@ __email__ = "Paebbels@gmail.com" __copyright__ = "2016-2025, Patrick Lehmann" __license__ = "Apache License, Version 2.0" -__version__ = "0.32.0" +__version__ = "0.33.0" from enum import unique, Enum, Flag, auto @@ -60,8 +60,9 @@ from pyTooling.Common import getFullyQualifiedName from pyTooling.Decorators import export, readonly from pyTooling.Graph import Graph, Vertex, Edge +from pyTooling.Warning import WarningCollector -from pyVHDLModel.Exception import VHDLModelException +from pyVHDLModel.Exception import VHDLModelException, NotImplementedWarning, BlackboxWarning from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError @@ -1054,6 +1055,8 @@ def CreateCompileOrderGraph(self) -> None: def ImportObjects(self) -> None: def _ImportObjects(package: Package) -> None: + from pyVHDLModel.Declaration import AttributeSpecification + for referencedLibrary in package._referencedPackages.values(): for referencedPackage in referencedLibrary.values(): for declaredItem in referencedPackage._declaredItems: @@ -1062,6 +1065,10 @@ def _ImportObjects(package: Package) -> None: package._namespace._elements[normalizedIdentifier] = declaredItem elif isinstance(declaredItem, NamedEntityMixin): package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem + elif isinstance(declaredItem, AttributeSpecification): + # FIXME: actually, this is not a declared item, but a application of an attribute to named entities + WarningCollector.Raise(NotImplementedWarning(f"Attribute specification.")) + else: raise VHDLModelException(f"Unexpected declared item.") @@ -1154,7 +1161,7 @@ def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Verte _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex) _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex) elif isinstance(expression, TernaryExpression): - pass + WarningCollector.Raise(NotImplementedWarning(f"Handling of ternary expression.")) elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): obj = namespace.FindObject(expression) expression._reference = obj @@ -1162,7 +1169,7 @@ def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Verte edge = obj._objectVertex.EdgeToVertex(typeVertex) edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression else: - pass + WarningCollector.Raise(NotImplementedWarning(f"Unhandled else-branch")) def _LinkItems(package: Package): for item in package._declaredItems: @@ -1301,10 +1308,11 @@ def LinkContexts(self) -> None: # TODO: update the namespace with visible members if isinstance(symbol, AllPackageMembersReferenceSymbol): - pass + WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'.")) elif isinstance(symbol, PackageMemberReferenceSymbol): - raise NotImplementedError() + WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'.")) + else: raise VHDLModelException() @@ -1495,11 +1503,14 @@ def LinkPackageReferences(self) -> None: # TODO: update the namespace with visible members if isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): + WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'. Exception: components are handled.")) + for componentIdentifier, component in package._components.items(): designUnit._namespace._elements[componentIdentifier] = component elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol): - raise NotImplementedError() + WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'.")) + else: raise VHDLModelException() @@ -1624,11 +1635,10 @@ def LinkInstantiations(self) -> None: dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance) dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation else: - print(f"Found a blackbox for '{instance.Label}: {instance.Component.Name}'.") + WarningCollector.Raise(BlackboxWarning(f"Blackbox caused by '{instance.Label}: {instance.Component.Name}'.")) elif isinstance(instance, ConfigurationInstantiation): - # pass - print(instance.Label, instance.Configuration) + WarningCollector.Raise(NotImplementedWarning(f"Configuration instantiation of '{instance.Label}: {instance.Configuration}'.")) def IndexPackages(self) -> None: """ @@ -1841,7 +1851,7 @@ def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]: yield compileOrderNode.Value def GetUnusedDesignUnits(self) -> List[DesignUnit]: - raise NotImplementedError() + WarningCollector.Raise(NotImplementedWarning(f"Compute unused design units.")) def __repr__(self) -> str: """ diff --git a/pyproject.toml b/pyproject.toml index 4653aa7c2..ac3e10e80 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ requires = [ "setuptools >= 80.0", "wheel ~= 0.45", - "pyTooling ~= 8.7" + "pyTooling ~= 8.8" ] build-backend = "setuptools.build_meta" @@ -36,23 +36,21 @@ namespace_packages = true html_report = "report/typing" [tool.pytest] -junit_xml = "report/unit/UnittestReportSummary.xml" - -[tool.pyedaa-reports] -junit_xml = "report/unit/unittest.xml" - -[tool.pytest.ini_options] -addopts = "--tb=native" +addopts = ["--tb=native"] # Don't set 'python_classes = *' otherwise, pytest doesn't search for classes # derived from unittest.Testcase -python_files = "*" -python_functions = "test_*" +python_files = ["*"] +python_functions = ["test_*"] filterwarnings = [ "error::DeprecationWarning", "error::PendingDeprecationWarning" ] +junit_xml = "report/unit/UnittestReportSummary.xml" junit_logging = "all" +[tool.pyedaa-reports] +junit_xml = "report/unit/unittest.xml" + [tool.interrogate] color = true verbose = 1 # possible values: 0 (minimal output), 1 (-v), 2 (-vv) diff --git a/requirements.txt b/requirements.txt index 4fcd21991..a5238b41c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pyTooling ~= 8.7 +pyTooling ~= 8.8 diff --git a/run.ps1 b/run.ps1 index 1aed3335f..be12e05d6 100644 --- a/run.ps1 +++ b/run.ps1 @@ -33,7 +33,7 @@ Param( ) $PackageName = "pyVHDLModel" -$PackageVersion = "0.32.0" +$PackageVersion = "0.33.0" # set default values $EnableDebug = [bool]$PSCmdlet.MyInvocation.BoundParameters["Debug"] diff --git a/setup.py b/setup.py index c6b15f46f..4f2de6178 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,6 @@ pythonVersions=("3.11", "3.12", "3.13", "3.14"), dataFiles={ packageName: ["py.typed"] - }, - debug=True + } ) ) diff --git a/tests/requirements.txt b/tests/requirements.txt index 787c2e678..7a7add365 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -4,7 +4,7 @@ Coverage ~= 7.11 # Test Runner -pytest ~= 8.4 +pytest ~= 9.0 pytest-cov ~= 7.0 # Static Type Checking diff --git a/tests/unit/Instantiate.py b/tests/unit/Instantiate.py index 68c37f02c..0ed9fa7b1 100644 --- a/tests/unit/Instantiate.py +++ b/tests/unit/Instantiate.py @@ -35,7 +35,7 @@ from pyTooling.Graph import Graph -from pyVHDLModel import Design, Library, Document, IEEEFlavor +from pyVHDLModel import Design, Library, Document, IEEEFlavor, LibraryExistsInDesignError from pyVHDLModel.Base import Direction, Range from pyVHDLModel.Name import SelectedName, SimpleName, AllName, AttributeName from pyVHDLModel.Object import Constant, Signal @@ -630,7 +630,7 @@ def test_StdLibrary(self) -> None: self.assertSetEqual(set(design.IterateDesignUnits()), set(stdLibrary.IterateDesignUnits())) - with self.assertRaises(Exception): + with self.assertRaises(LibraryExistsInDesignError): design.LoadStdLibrary() def test_IeeeLibrary_implicit(self) -> None: