From 6b27f2438f23907ea478ed2c7ce7a5fc989ded3f Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 27 Oct 2024 20:17:02 +0100 Subject: [PATCH] General code updates. --- .github/pull_request_template.md | 18 +++++- .github/workflows/Pipeline.yml | 2 + dist/requirements.txt | 4 +- doc/Dependency.rst | 26 ++++----- doc/conf.py | 2 +- doc/index.rst | 4 +- doc/requirements.txt | 9 +-- pyEDAA/ProjectModel/OSVVM.py | 8 +-- pyEDAA/ProjectModel/Xilinx/Vivado.py | 6 +- pyEDAA/ProjectModel/__init__.py | 85 ++++++++++++++++------------ pyproject.toml | 43 ++++++++++---- requirements.txt | 2 +- tests/requirements.txt | 10 ++-- 13 files changed, 137 insertions(+), 82 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ac698f89..4ed2d900 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,16 +1,30 @@ # New Features - + +* tbd * tbd # Changes +* tbd * tbd # Bug Fixes +* tbd +* tbd + +# Documentation + +* tbd +* tbd + +# Unit Tests + +* tbd * tbd ---------- -# Related PRs: +# Related Issues and Pull-Requests * tbd +* tbd diff --git a/.github/workflows/Pipeline.yml b/.github/workflows/Pipeline.yml index c0acfaa4..68c0bf98 100644 --- a/.github/workflows/Pipeline.yml +++ b/.github/workflows/Pipeline.yml @@ -46,6 +46,8 @@ jobs: uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@dev needs: - UnitTesting + with: + additional_merge_args: '"--pytest=rewrite-dunder-init;reduce-depth:pytest.tests.unit"' Package: uses: pyTooling/Actions/.github/workflows/Package.yml@dev diff --git a/dist/requirements.txt b/dist/requirements.txt index 5be2dd07..878e3e51 100644 --- a/dist/requirements.txt +++ b/dist/requirements.txt @@ -1,2 +1,2 @@ -wheel ~= 0.43 -twine ~= 5.0 +wheel ~= 0.44 +twine ~= 5.1 diff --git a/doc/Dependency.rst b/doc/Dependency.rst index ddcb7590..dbaaeeb4 100644 --- a/doc/Dependency.rst +++ b/doc/Dependency.rst @@ -27,7 +27,7 @@ pyEDAA.ProjectModel Package +------------------------------------------------------------------------+-------------+-------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ | **Package** | **Version** | **License** | **Dependencies** | +========================================================================+=============+===========================================================================================+========================================================================================================================================================+ -| `pyTooling `__ | ≥6.1.0 | `Apache License, 2.0 `__ | *None* | +| `pyTooling `__ | ≥7.0 | `Apache License, 2.0 `__ | *None* | +------------------------------------------------------------------------+-------------+-------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ | `pyVHDLModel `__ | ≥0.27.1 | `Apache License, 2.0 `__ | * `pyTooling `__ (`Apache License, 2.0 `__) | +------------------------------------------------------------------------+-------------+-------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -61,17 +61,17 @@ the mandatory dependencies too. +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ | **Package** | **Version** | **License** | **Dependencies** | +=====================================================================+=============+========================================================================================+======================+ -| `pytest `__ | ≥8.2 | `MIT `__ | *Not yet evaluated.* | +| `pytest `__ | ≥8.3 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ | `pytest-cov `__ | ≥5.0 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ -| `Coverage `__ | ≥7.5 | `Apache License, 2.0 `__ | *Not yet evaluated.* | +| `Coverage `__ | ≥7.6 | `Apache License, 2.0 `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ -| `mypy `__ | ≥1.10 | `MIT `__ | *Not yet evaluated.* | +| `mypy `__ | ≥1.13 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ -| `typing-extensions `__ | ≥4.11 | `PSF-2.0 `__ | *Not yet evaluated.* | +| `typing-extensions `__ | ≥4.12 | `PSF-2.0 `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ -| `lxml `__ | ≥5.1 | `BSD 3-Clause `__ | *Not yet evaluated.* | +| `lxml `__ | ≥5.3 | `BSD 3-Clause `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ @@ -99,15 +99,15 @@ the mandatory dependencies too. +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | **Package** | **Version** | **License** | **Dependencies** | +=================================================================================================+==============+==========================================================================================================+======================================================================================================================================================+ -| `pyTooling `__ | ≥6.1.0 | `Apache License, 2.0 `__ | *None* | +| `pyTooling `__ | ≥7.0 | `Apache License, 2.0 `__ | *None* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Sphinx `__ | ≥7.3 | `BSD 3-Clause `__ | *Not yet evaluated.* | +| `Sphinx `__ | ≥8.1 | `BSD 3-Clause `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | `sphinx_btd_theme `__ | ≥0.5.2 | `MIT `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | !! `sphinx_fontawesome `__ | ≥0.0.6 | `GPL 2.0 `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `sphinx_autodoc_typehints `__ | ≥2.1 | `MIT `__ | *Not yet evaluated.* | +| `sphinx_autodoc_typehints `__ | ≥2.5 | `MIT `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -135,9 +135,9 @@ install the mandatory dependencies too. +----------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | **Package** | **Version** | **License** | **Dependencies** | +============================================================================+==============+==========================================================================================================+======================================================================================================================================================+ -| `pyTooling `__ | ≥6.1.0 | `Apache License, 2.0 `__ | *None* | +| `pyTooling `__ | ≥7.0 | `Apache License, 2.0 `__ | *None* | +----------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `wheel `__ | ≥0.43 | `MIT `__ | *Not yet evaluated.* | +| `wheel `__ | ≥0.44 | `MIT `__ | *Not yet evaluated.* | +----------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -166,7 +166,7 @@ install the mandatory dependencies too. +----------------------------------------------------------+--------------+-------------------------------------------------------------------------------------------+----------------------+ | **Package** | **Version** | **License** | **Dependencies** | +==========================================================+==============+===========================================================================================+======================+ -| `wheel `__ | ≥0.43 | `MIT `__ | *Not yet evaluated.* | +| `wheel `__ | ≥0.44 | `MIT `__ | *Not yet evaluated.* | +----------------------------------------------------------+--------------+-------------------------------------------------------------------------------------------+----------------------+ -| `Twine `__ | ≥5.0 | `Apache License, 2.0 `__ | *Not yet evaluated.* | +| `Twine `__ | ≥5.1 | `Apache License, 2.0 `__ | *Not yet evaluated.* | +----------------------------------------------------------+--------------+-------------------------------------------------------------------------------------------+----------------------+ diff --git a/doc/conf.py b/doc/conf.py index 931677a3..3009b804 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -61,7 +61,7 @@ # ============================================================================== prologPath = Path("prolog.inc") try: - with prologPath.open("r") as fileHandle: + with prologPath.open("r", encoding="utf-8") as fileHandle: rst_prolog = fileHandle.read() except Exception as ex: print(f"[ERROR:] While reading '{prologPath}'.") diff --git a/doc/index.rst b/doc/index.rst index e346302e..99bce7b0 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -98,7 +98,7 @@ News * ProjectModel became first citizen of `EDA² `__ and got integrated into the `pyEDAA` namespace at PyPI. -.. _contributors: +.. _CONTRIBUTORS: Contributors ************ @@ -108,6 +108,8 @@ Contributors * `and more... `__ +.. _LICENSE: + License ******* diff --git a/doc/requirements.txt b/doc/requirements.txt index 332bfd42..2fb10459 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,12 +1,13 @@ -r ../requirements.txt -pyTooling ~= 6.1 +pyTooling ~= 7.0 # Enforce latest version on ReadTheDocs -sphinx ~= 7.3 +sphinx ~= 8.1 +docutils ~= 0.21 # Sphinx Extenstions -sphinxcontrib-mermaid>=0.7.1 +sphinxcontrib-mermaid ~= 1.0 autoapi>=2.0.1 sphinx_fontawesome>=0.0.6 -sphinx_autodoc_typehints ~= 2.1 +sphinx_autodoc_typehints ~= 2.5 diff --git a/pyEDAA/ProjectModel/OSVVM.py b/pyEDAA/ProjectModel/OSVVM.py index 5827f670..b9888a55 100644 --- a/pyEDAA/ProjectModel/OSVVM.py +++ b/pyEDAA/ProjectModel/OSVVM.py @@ -46,9 +46,9 @@ class OSVVMProjectFile(ProjectFile, TCLContent): def __init__( self, path: Path, - project: Project = None, - design: Design = None, - fileSet: FileSet = None + project: Nullable[Project] = None, + design: Nullable[Design] = None, + fileSet: Nullable[FileSet] = None ): super().__init__(path, project, design, fileSet) @@ -154,7 +154,7 @@ def _Parse(self) -> List: instructions: List = [] print() - with path.open("r") as file: + with path.open("r", encoding="utf-8") as file: i = 1 for line in file: line = line.lstrip() diff --git a/pyEDAA/ProjectModel/Xilinx/Vivado.py b/pyEDAA/ProjectModel/Xilinx/Vivado.py index 5f67aeb7..530e7345 100644 --- a/pyEDAA/ProjectModel/Xilinx/Vivado.py +++ b/pyEDAA/ProjectModel/Xilinx/Vivado.py @@ -90,9 +90,9 @@ class VivadoProjectFile(ProjectFile, XMLContent): def __init__( self, path: Path, - project: Project = None, - design: Design = None, - fileSet: FileSet = None + project: Nullable[Project] = None, + design: Nullable[Design] = None, + fileSet: Nullable[FileSet] = None ) -> None: super().__init__(path, project, design, fileSet) diff --git a/pyEDAA/ProjectModel/__init__.py b/pyEDAA/ProjectModel/__init__.py index 5ef9bebe..b76a9c14 100644 --- a/pyEDAA/ProjectModel/__init__.py +++ b/pyEDAA/ProjectModel/__init__.py @@ -39,8 +39,10 @@ from os.path import relpath as path_relpath from pathlib import Path as pathlib_Path +from sys import version_info from typing import Dict, Union, Optional as Nullable, List, Iterable, Generator, Tuple, Any as typing_Any, Type, Set, Any +from pyTooling.Common import getFullyQualifiedName from pyTooling.Decorators import export from pyTooling.MetaClasses import ExtendedType from pyTooling.Graph import Graph, Vertex @@ -123,9 +125,9 @@ class File(metaclass=FileType, slots=True): def __init__( self, path: pathlib_Path, - project: 'Project' = None, - design: 'Design' = None, - fileSet: 'FileSet' = None + project: Nullable["Project"] = None, + design: Nullable["Design"] = None, + fileSet: Nullable["FileSet"] = None ): self._fileType = getattr(FileTypes, self.__class__.__name__) self._path = path @@ -266,7 +268,12 @@ def __getitem__(self, key: Type[Attribute]) -> Any: try: return self._attributes[key] except KeyError: - return key.resolve(self, key) + try: + return key.resolve(self, key) + except KeyError: + attribute = key() + self._attributes[key] = attribute + return attribute def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None: """ @@ -405,7 +412,7 @@ class VHDLSourceFile(HDLSourceFile, HumanReadableContent): _vhdlLibrary: Nullable['VHDLLibrary'] _vhdlVersion: VHDLVersion - def __init__(self, path: pathlib_Path, vhdlLibrary: Union[str, 'VHDLLibrary'] = None, vhdlVersion: VHDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None): + def __init__(self, path: pathlib_Path, vhdlLibrary: Union[str, 'VHDLLibrary'] = None, vhdlVersion: Nullable[VHDLVersion] = None, project: Nullable["Project"] = None, design: Nullable["Design"] = None, fileSet: Nullable["FileSet"] = None): super().__init__(path, project, design, fileSet) if isinstance(vhdlLibrary, str): @@ -427,7 +434,10 @@ def __init__(self, path: pathlib_Path, vhdlLibrary: Union[str, 'VHDLLibrary'] = elif vhdlLibrary is None: self._vhdlLibrary = None else: - raise TypeError(f"Parameter 'vhdlLibrary' is neither a 'str' nor 'VHDLibrary'.") + ex = TypeError(f"Parameter 'vhdlLibrary' is neither a 'str' nor 'VHDLibrary'.") + if version_info >= (3, 11): # pragma: no cover + ex.add_note(f"Got type '{getFullyQualifiedName(vhdlLibrary)}'.") + raise ex self._vhdlVersion = vhdlVersion @@ -513,7 +523,7 @@ def SVVersion(self, value: SystemVerilogVersion) -> None: class VerilogBaseFile(HDLSourceFile, HumanReadableContent): _version: SystemVerilogVersion - def __init__(self, path: pathlib_Path, version: SystemVerilogVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None): + def __init__(self, path: pathlib_Path, version: Nullable[SystemVerilogVersion] = None, project: Nullable["Project"] = None, design: Nullable["Design"] = None, fileSet: Nullable["FileSet"] = None): super().__init__(path, project, design, fileSet) self._version = version @@ -550,7 +560,7 @@ class SystemRDLSourceFile(RDLSourceFile, HumanReadableContent): _srdlVersion: SystemRDLVersion - def __init__(self, path: pathlib_Path, srdlVersion: SystemRDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None): + def __init__(self, path: pathlib_Path, srdlVersion: Nullable[SystemRDLVersion] = None, project: Nullable["Project"] = None, design: Nullable["Design"] = None, fileSet: Nullable["FileSet"] = None): super().__init__(path, project, design, fileSet) self._srdlVersion = srdlVersion @@ -684,16 +694,16 @@ class FileSet(metaclass=ExtendedType, slots=True): def __init__( self, name: str, - topLevel: str = None, - directory: pathlib_Path = pathlib_Path("."), - project: 'Project' = None, - design: 'Design' = None, - parent: Nullable['FileSet'] = None, - vhdlLibrary: Union[str, 'VHDLLibrary'] = None, - vhdlVersion: VHDLVersion = None, - verilogVersion: SystemVerilogVersion = None, - svVersion: SystemVerilogVersion = None, - srdlVersion: SystemRDLVersion = None + topLevel: Nullable[str] = None, + directory: pathlib_Path = pathlib_Path("."), + project: Nullable["Project"] = None, + design: Nullable["Design"] = None, + parent: Nullable['FileSet'] = None, + vhdlLibrary: Union[str, 'VHDLLibrary'] = None, + vhdlVersion: Nullable[VHDLVersion] = None, + verilogVersion: Nullable[SystemVerilogVersion] = None, + svVersion: Nullable[SystemVerilogVersion] = None, + srdlVersion: Nullable[SystemRDLVersion] = None ): self._name = name self._topLevel = topLevel @@ -902,11 +912,13 @@ def AddFile(self, file: File) -> None: raise TypeError("Parameter 'file' is not of type ProjectModel.File.") elif file._fileSet is not None: ex = ValueError(f"File '{file.Path!s}' is already part of fileset '{file.FileSet.Name}'.") - ex.add_note(f"A file can't be assigned to another fileset.") + if version_info >= (3, 11): # pragma: no cover + ex.add_note(f"A file can't be assigned to another fileset.") raise ex elif file in self._set: ex = ValueError(f"File '{file.Path!s}' is already part of this fileset.") - ex.add_note(f"A file can't be added twice to a fileset.") + if version_info >= (3, 11): # pragma: no cover + ex.add_note(f"A file can't be added twice to a fileset.") raise ex self._files.append(file) @@ -1127,9 +1139,9 @@ class VHDLLibrary(metaclass=ExtendedType, slots=True): def __init__( self, name: str, - project: 'Project' = None, - design: 'Design' = None, - vhdlVersion: VHDLVersion = None + project: Nullable["Project"] = None, + design: Nullable["Design"] = None, + vhdlVersion: Nullable[VHDLVersion] = None ): self._name = name if project is not None: @@ -1236,7 +1248,10 @@ def AddDependency(self, library: 'VHDLLibrary') -> None: def AddFile(self, vhdlFile: VHDLSourceFile) -> None: if not isinstance(vhdlFile, VHDLSourceFile): - raise TypeError(f"Parameter 'vhdlFile' is not a 'VHDLSourceFile'.") + ex = TypeError(f"Parameter 'vhdlFile' is not a 'VHDLSourceFile'.") + if version_info >= (3, 11): # pragma: no cover + ex.add_note(f"Got type '{getFullyQualifiedName(vhdlFile)}'.") + raise ex self._files.append(vhdlFile) @@ -1344,13 +1359,13 @@ class Design(metaclass=ExtendedType, slots=True): def __init__( self, name: str, - topLevel: str = None, - directory: pathlib_Path = pathlib_Path("."), - project: 'Project' = None, - vhdlVersion: VHDLVersion = None, - verilogVersion: SystemVerilogVersion = None, - svVersion: SystemVerilogVersion = None, - srdlVersion: SystemRDLVersion = None + topLevel: Nullable[str] = None, + directory: pathlib_Path = pathlib_Path("."), + project: Nullable["Project"] = None, + vhdlVersion: Nullable[VHDLVersion] = None, + verilogVersion: Nullable[SystemVerilogVersion] = None, + svVersion: Nullable[SystemVerilogVersion] = None, + srdlVersion: Nullable[SystemRDLVersion] = None ): self._name = name self._topLevel = topLevel @@ -1687,10 +1702,10 @@ class Project(metaclass=ExtendedType, slots=True): def __init__( self, name: str, - rootDirectory: pathlib_Path = pathlib_Path("."), - vhdlVersion: VHDLVersion = None, - verilogVersion: SystemVerilogVersion = None, - svVersion: SystemVerilogVersion = None + rootDirectory: pathlib_Path = pathlib_Path("."), + vhdlVersion: Nullable[VHDLVersion] = None, + verilogVersion: Nullable[SystemVerilogVersion] = None, + svVersion: Nullable[SystemVerilogVersion] = None ): self._name = name self._rootDirectory = rootDirectory diff --git a/pyproject.toml b/pyproject.toml index c7f25089..9319678c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [build-system] requires = [ - "setuptools ~= 69.5", - "wheel ~= 0.40.0", - "pyTooling ~= 6.1" + "setuptools ~= 75.2", + "wheel ~= 0.44", + "pyTooling ~= 7.0" ] build-backend = "setuptools.build_meta" @@ -10,15 +10,18 @@ build-backend = "setuptools.build_meta" line-length = 120 [tool.mypy] -python_version = "3.11" -namespace_packages = true - +files = ["pyEDAA.ProjectModel"] +python_version = "3.12" +#ignore_missing_imports = true +strict = true pretty = true show_error_context = true - +show_error_codes = true +namespace_packages = true html_report = "report/typing" [tool.pytest.ini_options] +addopts = "--tb=native" # Don't set 'python_classes = *' otherwise, pytest doesn't search for classes # derived from unittest.Testcase python_files = "*" @@ -27,13 +30,28 @@ filterwarnings = [ "error::DeprecationWarning", "error::PendingDeprecationWarning" ] +junit_logging = "all" + +[tool.interrogate] +color = true +verbose = 1 # possible values: 0 (minimal output), 1 (-v), 2 (-vv) +fail-under = 59 +exclude = [ + "build", + "dist", + "doc", + "tests", + "setup.py" +] +ignore-setters = true [tool.coverage.run] branch = true +relative_files = true omit = [ "*site-packages*", "setup.py", - "tests/*" + "tests/unit/*" ] [tool.coverage.report] @@ -47,9 +65,12 @@ omit = [ "tests/*" ] +[tool.coverage.xml] +output = "report/coverage/coverage.xml" + +[tool.coverage.json] +output = "report/coverage/coverage.json" + [tool.coverage.html] directory = "report/coverage/html" title="Code Coverage of pyEDAA.ProjectModel" - -[tool.coverage.xml] -output = "report/coverage/coverage.xml" diff --git a/requirements.txt b/requirements.txt index 896deb2e..0c9b60d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -pyTooling ~= 6.1 +pyTooling ~= 7.0 pyVHDLModel >= 0.27.1, < 0.28 pySVModel >= 0.4.0, < 0.5 pySystemRDLModel >= 0.2.0, < 0.3 diff --git a/tests/requirements.txt b/tests/requirements.txt index d7bdbde9..130f5c68 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,13 +1,13 @@ -r ../requirements.txt # Coverage collection -Coverage ~= 7.5 +Coverage ~= 7.6 # Test Runner -pytest ~= 8.2 +pytest ~= 8.3 pytest-cov ~= 5.0 # Static Type Checking -mypy ~= 1.10 -typing_extensions ~= 4.11 -lxml ~= 5.1 +mypy ~= 1.13 +typing_extensions ~= 4.12 +lxml ~= 5.3