From cd227376faabc95020fa2fec92adad3bd456f51b Mon Sep 17 00:00:00 2001 From: anton schulte Date: Wed, 27 Sep 2023 10:34:16 +0200 Subject: [PATCH 1/9] all checked for UI --- mypy.ini | 3 + vunit/configuration.py | 14 +- vunit/library.py | 9 +- vunit/project.py | 16 +- vunit/sim_if/__init__.py | 6 +- vunit/sim_if/factory.py | 11 +- vunit/source_file.py | 16 +- vunit/test/bench.py | 13 +- vunit/test/bench_list.py | 18 +- vunit/ui/__init__.py | 188 +++++++++-------- vunit/ui/common.py | 17 +- vunit/ui/library.py | 415 +++++++++++++++++++------------------- vunit/ui/packagefacade.py | 14 +- vunit/ui/results.py | 13 +- vunit/ui/source.py | 129 ++++++------ vunit/ui/test.py | 42 ++-- vunit/ui/testbench.py | 51 ++--- 17 files changed, 525 insertions(+), 450 deletions(-) create mode 100644 mypy.ini diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 000000000..d9aa13bf2 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +[mypy-vunit.ui.*] +disallow_untyped_defs = True \ No newline at end of file diff --git a/vunit/configuration.py b/vunit/configuration.py index a6e01a532..473024883 100644 --- a/vunit/configuration.py +++ b/vunit/configuration.py @@ -12,6 +12,7 @@ import inspect from pathlib import Path from copy import copy +from typing import Any, Callable, OrderedDict, Union from vunit.sim_if.factory import SIMULATOR_FACTORY @@ -111,7 +112,7 @@ def set_vhdl_configuration_name(self, name): """ self.vhdl_configuration_name = name - def set_generic(self, name, value): + def set_generic(self, name: str, value: Any) -> None: """ Set generic """ @@ -128,7 +129,7 @@ def set_generic(self, name, value): else: self.generics[name] = value - def set_sim_option(self, name, value): + def set_sim_option(self, name: str, value: Union[str, list[str], bool]): """ Set sim option """ @@ -195,11 +196,10 @@ class ConfigurationVisitor(object): def _check_enabled(self): pass - @staticmethod - def get_configuration_dicts(): + def get_configuration_dicts(self) -> list[OrderedDict[Any, Configuration]]: raise NotImplementedError - def set_attribute(self, name, value): + def set_attribute(self, name: str, value: Any): """ Set attribute """ @@ -226,7 +226,7 @@ def set_vhdl_configuration_name(self, value: str): for config in configs.values(): config.set_vhdl_configuration_name(value) - def set_sim_option(self, name, value, overwrite=True): + def set_sim_option(self, name: str, value: Union[str, list[str], bool], overwrite=True) -> None: """ Set sim option @@ -240,7 +240,7 @@ def set_sim_option(self, name, value, overwrite=True): continue config.set_sim_option(name, value) - def set_pre_config(self, value): + def set_pre_config(self, value: Callable) -> None: """ Set pre_config function """ diff --git a/vunit/library.py b/vunit/library.py index 94142943d..af0f49957 100644 --- a/vunit/library.py +++ b/vunit/library.py @@ -11,6 +11,9 @@ """ import logging +from typing import cast +from vunit.design_unit import Entity, VHDLDesignUnit +from vunit.source_file import SourceFile, VHDLSourceFile, VerilogSourceFile from vunit.vhdl_standard import VHDLStandard LOGGER = logging.getLogger(__name__) @@ -46,7 +49,7 @@ def __init__(self, name: str, directory: str, vhdl_standard: VHDLStandard, is_ex self._is_external = is_external - def add_source_file(self, source_file): + def add_source_file(self, source_file: SourceFile) -> SourceFile: """ Add source file to library unless it exists @@ -104,7 +107,7 @@ def _check_duplication(self, dictionary, design_unit): if design_unit.name in dictionary: self._warning_on_duplication(design_unit, dictionary[design_unit.name].source_file.name) - def add_vhdl_design_units(self, design_units): + def add_vhdl_design_units(self, design_units: list[VHDLDesignUnit]): """ Add VHDL design units to the library """ @@ -119,7 +122,7 @@ def add_vhdl_design_units(self, design_units): self._entities[design_unit.name] = design_unit for architecture in self._architectures[design_unit.name].values(): - design_unit.add_architecture(architecture) + cast(Entity, design_unit).add_architecture(architecture) else: if design_unit.unit_type == "architecture": diff --git a/vunit/project.py b/vunit/project.py index c9bc4f14c..3671094bc 100644 --- a/vunit/project.py +++ b/vunit/project.py @@ -45,15 +45,15 @@ def __init__(self, depend_on_package_body=False, database=None): self._database = database self._vhdl_parser = VHDLParser(database=self._database) self._verilog_parser = VerilogParser(database=self._database) - self._libraries = OrderedDict() + self._libraries: OrderedDict[str, Library] = OrderedDict() # Mapping between library lower case name and real library name self._lower_library_names_dict = {} - self._source_files_in_order = [] + self._source_files_in_order: list[SourceFile] = [] self._manual_dependencies = [] self._depend_on_package_body = depend_on_package_body self._builtin_libraries = set(["ieee", "std"]) - def _validate_new_library_name(self, library_name): + def _validate_new_library_name(self, library_name: str) -> None: """ Check that the library_name is valid or raise RuntimeError """ @@ -74,7 +74,7 @@ def _validate_new_library_name(self, library_name): f"Library name {self._lower_library_names_dict[lower_name]!r} previously defined" ) - def add_builtin_library(self, logical_name): + def add_builtin_library(self, logical_name: str) -> None: """ Add a builtin library name that does not give missing dependency warnings """ @@ -82,7 +82,7 @@ def add_builtin_library(self, logical_name): def add_library( self, - logical_name, + logical_name: str, directory: Union[str, Path], vhdl_standard: VHDLStandard = VHDL.STD_2008, is_external=False, @@ -118,7 +118,7 @@ def add_source_file( # pylint: disable=too-many-arguments defines=None, vhdl_standard: Optional[VHDLStandard] = None, no_parse=False, - ): + ) -> SourceFile: """ Add a file_name as a source file in library_name with file_type @@ -515,7 +515,7 @@ def _get_files_to_recompile(self, files, dependency_graph, incremental): result_list.append(source_file) return result_list - def get_dependencies_in_compile_order(self, target_files=None, implementation_dependencies=False): + def get_dependencies_in_compile_order(self, target_files=None, implementation_dependencies=False) -> list[SourceFile]: """ Get a list of dependencies of target files including the target files. @@ -591,7 +591,7 @@ def comparison_key(source_file): return sorted(files, key=comparison_key) - def get_source_files_in_order(self): + def get_source_files_in_order(self) -> list[SourceFile]: """ Get a list of source files in the order they were added to the project """ diff --git a/vunit/sim_if/__init__.py b/vunit/sim_if/__init__.py index 5596dbd3c..2358c8f5f 100644 --- a/vunit/sim_if/__init__.py +++ b/vunit/sim_if/__init__.py @@ -13,11 +13,13 @@ from os import environ, listdir, pathsep import subprocess from pathlib import Path -from typing import List +from typing import Any, List, Union from ..ostools import Process, simplify_path from ..exceptions import CompileError from ..color_printer import NO_COLOR_PRINTER +OptionType = Union[str, list[str], bool] + class Option(object): """ @@ -416,7 +418,7 @@ def validate(self, value): raise ValueError(f"Option {self.name!r} must be one of {self._legal_values!s}. Got {value!r}") -def is_string_not_iterable(value): +def is_string_not_iterable(value: Any) -> bool: """ Returns True if value is a string and not another iterable """ diff --git a/vunit/sim_if/factory.py b/vunit/sim_if/factory.py index 0fa9d0d4b..b9b49cace 100644 --- a/vunit/sim_if/factory.py +++ b/vunit/sim_if/factory.py @@ -9,13 +9,14 @@ """ import os +from typing import Union from .activehdl import ActiveHDLInterface from .ghdl import GHDLInterface from .incisive import IncisiveInterface from .modelsim import ModelSimInterface from .nvc import NVCInterface from .rivierapro import RivieraProInterface -from . import BooleanOption, ListOfStringOption, VHDLAssertLevelOption +from . import BooleanOption, ListOfStringOption, Option, VHDLAssertLevelOption class SimulatorFactory(object): @@ -37,7 +38,7 @@ def supported_simulators(): NVCInterface, ] - def _extract_compile_options(self): + def _extract_compile_options(self) -> dict[str, Option]: """ Return all supported compile options """ @@ -51,7 +52,7 @@ def _extract_compile_options(self): result[opt.name] = opt return result - def _extract_sim_options(self): + def _extract_sim_options(self) -> dict[str, Option]: """ Return all supported sim options """ @@ -75,7 +76,7 @@ def _extract_sim_options(self): return result - def check_sim_option(self, name, value): + def check_sim_option(self, name: str, value: Union[str, list[str], bool]): """ Check that sim_option has legal name and value """ @@ -94,7 +95,7 @@ def check_compile_option_name(self, name): if name not in known_options: raise ValueError(f"Unknown compile_option {name!r}, expected one of {known_options!r}") - def check_compile_option(self, name, value): + def check_compile_option(self, name: str, value: Union[str, list[str], bool]) -> None: """ Check that the compile option is valid """ diff --git a/vunit/source_file.py b/vunit/source_file.py index 85265e7dc..4ee7b11fe 100644 --- a/vunit/source_file.py +++ b/vunit/source_file.py @@ -8,10 +8,11 @@ Functionality to represent and operate on VHDL and Verilog source files """ from pathlib import Path -from typing import Union +from typing import Literal, Union import logging from copy import copy import traceback +from vunit.sim_if import OptionType from vunit.sim_if.factory import SIMULATOR_FACTORY from vunit.hashing import hash_string from vunit.vhdl_parser import VHDLReference @@ -35,7 +36,7 @@ def __init__(self, name, library, file_type): self.file_type = file_type self.design_units = [] self._content_hash = None - self._compile_options = {} + self._compile_options: dict[str, OptionType] = {} # The file name before preprocessing self.original_name = name @@ -70,14 +71,14 @@ def __hash__(self): def __repr__(self): return f"SourceFile({self.name!s}, {self.library.name!s})" - def set_compile_option(self, name, value): + def set_compile_option(self, name: str, value: OptionType): """ Set compile option """ SIMULATOR_FACTORY.check_compile_option(name, value) self._compile_options[name] = copy(value) - def add_compile_option(self, name, value): + def add_compile_option(self, name: str, value: OptionType): """ Add compile option """ @@ -86,7 +87,7 @@ def add_compile_option(self, name, value): if name not in self._compile_options: self._compile_options[name] = copy(value) else: - self._compile_options[name] += value + self._compile_options[name] += value # type: ignore @property def compile_options(self): @@ -118,6 +119,9 @@ def content_hash(self): """ return hash_string(self._content_hash + self._compile_options_hash()) + def add_to_library(self, library: Library): + raise NotImplemented + class VerilogSourceFile(SourceFile): """ @@ -347,7 +351,7 @@ def add_to_library(self, library): FILE_TYPES = ("vhdl",) + VERILOG_FILE_TYPES -def file_type_of(file_name): +def file_type_of(file_name: Union[str, Path]) -> Literal["vhdl", "verilog", "systemverilog"]: """ Return the file type of file_name based on the file ending """ diff --git a/vunit/test/bench.py b/vunit/test/bench.py index 90962edb3..3e03c2f32 100644 --- a/vunit/test/bench.py +++ b/vunit/test/bench.py @@ -14,6 +14,7 @@ import bisect import collections from collections import OrderedDict +from typing import Any, Iterable, Union from ..ostools import file_exists from ..cached import cached from ..vhdl_parser import remove_comments as remove_vhdl_comments @@ -37,7 +38,7 @@ def __init__(self, design_unit, database=None): self._database = database self._individual_tests = False - self._configs = {} + self._configs: OrderedDict[Any, Configuration] = OrderedDict() self._test_cases = [] self._implicit_test = None @@ -142,7 +143,7 @@ def get_test_case(self, name): return test_case raise KeyError(name) - def get_configuration_dicts(self): # pylint: disable=arguments-differ + def get_configuration_dicts(self) -> list[OrderedDict[str, Configuration]]: # pylint: disable=arguments-differ """ Get all configurations within the test bench @@ -166,7 +167,7 @@ def _get_configurations_to_run(self): del configs[DEFAULT_NAME] return configs.values() - def scan_tests_from_file(self, file_name): + def scan_tests_from_file(self, file_name: Union[str, Path]) -> None: """ Scan file for test cases and attributes """ @@ -337,7 +338,7 @@ def __init__(self, test, design_unit, enable_configuration, default_config): assert test.is_explicit self.design_unit = design_unit self._enable_configuration = enable_configuration - self._configs = OrderedDict({default_config.name: default_config}) + self._configs: OrderedDict[Any, Configuration] = OrderedDict({default_config.name: default_config}) @property def name(self): @@ -358,13 +359,13 @@ def _check_enabled(self): if not self._enable_configuration: raise RuntimeError("Individual test configuration is not possible with run_all_in_same_sim") - def get_configuration_dicts(self): # pylint: disable=arguments-differ + def get_configuration_dicts(self) -> list[OrderedDict[Any, Configuration]]: # pylint: disable=arguments-differ """ Get all configurations of this test """ return [self._configs] - def _get_configurations_to_run(self): + def _get_configurations_to_run(self) -> Iterable[Configuration]: """ Get all simulation runs for this test bench """ diff --git a/vunit/test/bench_list.py b/vunit/test/bench_list.py index 3b3aaf3a9..a1f91ee13 100644 --- a/vunit/test/bench_list.py +++ b/vunit/test/bench_list.py @@ -11,6 +11,8 @@ import re import logging from collections import OrderedDict + +from vunit.source_file import SourceFile from .list import TestList from .bench import TestBench @@ -23,10 +25,10 @@ class TestBenchList(object): """ def __init__(self, database=None): - self._libraries = OrderedDict() + self._libraries: OrderedDict[str, OrderedDict[str, TestBench]] = OrderedDict() self._database = database - def add_from_source_file(self, source_file): + def add_from_source_file(self, source_file: SourceFile) -> None: """ Scan test benches from the source file and add to test bench list """ @@ -36,7 +38,7 @@ def add_from_source_file(self, source_file): if design_unit.is_module or design_unit.is_entity: self._add_test_bench(TestBench(design_unit, self._database)) - def _add_test_bench(self, test_bench): + def _add_test_bench(self, test_bench: TestBench) -> None: """ Add the test bench """ @@ -44,13 +46,13 @@ def _add_test_bench(self, test_bench): self._libraries[test_bench.library_name] = OrderedDict() self._libraries[test_bench.library_name][test_bench.name] = test_bench - def get_test_bench(self, library_name, name): + def get_test_bench(self, library_name, name) -> TestBench: return self._libraries[library_name][name] - def get_test_benches_in_library(self, library_name): + def get_test_benches_in_library(self, library_name: str) -> list[TestBench]: return list(self._libraries.get(library_name, {}).values()) - def get_test_benches(self): + def get_test_benches(self) -> list[TestBench]: """ Get all test benches """ @@ -60,7 +62,7 @@ def get_test_benches(self): result.append(test_bench) return result - def create_tests(self, simulator_if, elaborate_only): + def create_tests(self, simulator_if, elaborate_only) -> TestList: """ Create all test cases from the test benches """ @@ -69,7 +71,7 @@ def create_tests(self, simulator_if, elaborate_only): test_bench.create_tests(simulator_if, elaborate_only, test_list) return test_list - def warn_when_empty(self): + def warn_when_empty(self) -> None: """ Log a warning when there are no test benches """ diff --git a/vunit/ui/__init__.py b/vunit/ui/__init__.py index 3ddc531e3..bb6d4a3f8 100644 --- a/vunit/ui/__init__.py +++ b/vunit/ui/__init__.py @@ -10,21 +10,26 @@ Public VUnit User Interface (UI) """ +from argparse import Namespace import csv import sys import traceback import logging import json import os -from typing import Optional, Set, Union +from typing import Any, Callable, Literal, Optional, Set, Union, cast from pathlib import Path from fnmatch import fnmatch +from vunit.test.list import TestList + +from vunit.ui.preprocessor import Preprocessor +from vunit.source_file import SourceFile as Source_File from ..database import PickledDataBase, DataBase from .. import ostools from ..vunit_cli import VUnitCLI from ..sim_if.factory import SIMULATOR_FACTORY -from ..sim_if import SimulatorInterface +from ..sim_if import OptionType, SimulatorInterface from ..color_printer import COLOR_PRINTER, NO_COLOR_PRINTER from ..project import Project @@ -58,9 +63,9 @@ class VUnit(object): # pylint: disable=too-many-instance-attributes, too-many-p @classmethod def from_argv( cls, - argv=None, + argv: Optional[Namespace] = None, vhdl_standard: Optional[str] = None, - ): + ) -> "VUnit": """ Create VUnit instance from command line arguments. @@ -89,9 +94,9 @@ def from_argv( @classmethod def from_args( cls, - args, + args: Namespace, vhdl_standard: Optional[str] = None, - ): + ) -> "VUnit": """ Create VUnit instance from args namespace. Intended for users who adds custom command line options. @@ -113,9 +118,9 @@ def from_args( def __init__( self, - args, + args: Namespace, vhdl_standard: Optional[str] = None, - ): + ) -> None: self._args = args self._configure_logging(args.log_level) self._output_path = str(Path(args.output_path).resolve()) @@ -125,7 +130,7 @@ def __init__( else: self._printer = COLOR_PRINTER - def test_filter(name, attribute_names): + def test_filter(name: str, attribute_names: set) -> bool: keep = any(fnmatch(name, pattern) for pattern in args.test_patterns) if args.with_attributes is not None: @@ -162,7 +167,7 @@ def test_filter(name, attribute_names): self._builtins = Builtins(self, self._vhdl_standard, simulator_class) - def _create_database(self): + def _create_database(self) -> PickledDataBase: """ Create a persistent database to store expensive parse results @@ -185,12 +190,12 @@ def _create_database(self): if create_new: database = DataBase(project_database_file_name, new=True) - database[key] = version + cast(DataBase, database)[key] = version return PickledDataBase(database) @staticmethod - def _configure_logging(log_level): + def _configure_logging(log_level: str) -> None: """ Configure logging based on log_level string """ @@ -207,7 +212,9 @@ def _which_vhdl_standard(self, vhdl_standard: Optional[str]) -> VHDLStandard: return VHDL.standard(vhdl_standard) - def add_external_library(self, library_name, path: Union[str, Path], vhdl_standard: Optional[str] = None): + def add_external_library( + self, library_name: str, path: Union[str, Path], vhdl_standard: Optional[str] = None + ) -> Library: """ Add an externally compiled library as a black-box @@ -233,7 +240,9 @@ def add_external_library(self, library_name, path: Union[str, Path], vhdl_standa ) return self.library(library_name) - def add_source_files_from_csv(self, project_csv_path: Union[str, Path], vhdl_standard: Optional[str] = None): + def add_source_files_from_csv( + self, project_csv_path: Union[str, Path], vhdl_standard: Optional[str] = None + ) -> SourceFileList: """ Add a project configuration, mapping all the libraries and files @@ -269,8 +278,8 @@ def add_library( self, library_name: str, vhdl_standard: Optional[str] = None, - allow_duplicate: Optional[bool] = False, - ): + allow_duplicate: bool = False, + ) -> Library: """ Add a library managed by VUnit. @@ -297,7 +306,7 @@ def add_library( raise ValueError(f"Library {library_name!s} already added. Use allow_duplicate to ignore this error.") return self.library(library_name) - def library(self, library_name: str): + def library(self, library_name: str) -> Library: """ Get a library @@ -310,9 +319,9 @@ def library(self, library_name: str): def get_libraries( self, - pattern="*", - allow_empty: Optional[bool] = False, - ): + pattern: str = "*", + allow_empty: bool = False, + ) -> LibraryList: """ Get a list of libraries @@ -320,7 +329,7 @@ def get_libraries( :param allow_empty: To disable an error if no labraries matched the pattern :returns: A :class:`.LibraryList` object """ - results = [] + results: list[Library] = [] for library in self._project.get_libraries(): if not fnmatch(library.name, pattern): @@ -332,7 +341,7 @@ def get_libraries( return LibraryList(results) - def set_attribute(self, name: str, value: str, allow_empty: Optional[bool] = False): + def set_attribute(self, name: str, value: str, allow_empty: bool = False) -> None: """ Set a value of attribute in all |configurations| @@ -353,7 +362,7 @@ def set_attribute(self, name: str, value: str, allow_empty: Optional[bool] = Fal for test_bench in check_not_empty(test_benches, allow_empty, "No test benches found"): test_bench.set_attribute(name, value) - def set_generic(self, name: str, value: str, allow_empty: Optional[bool] = False): + def set_generic(self, name: str, value: str, allow_empty: bool = False) -> None: """ Set a value of generic in all |configurations| @@ -374,7 +383,7 @@ def set_generic(self, name: str, value: str, allow_empty: Optional[bool] = False for test_bench in check_not_empty(test_benches, allow_empty, "No test benches found"): test_bench.set_generic(name.lower(), value) - def set_parameter(self, name: str, value: str, allow_empty: Optional[bool] = False): + def set_parameter(self, name: str, value: Union[str, int], allow_empty: bool = False) -> None: """ Set value of parameter in all |configurations| @@ -398,10 +407,10 @@ def set_parameter(self, name: str, value: str, allow_empty: Optional[bool] = Fal def set_sim_option( self, name: str, - value: str, - allow_empty: Optional[bool] = False, - overwrite: Optional[bool] = True, - ): + value: OptionType, + allow_empty: bool = False, + overwrite: bool = True, + ) -> None: """ Set simulation option in all |configurations| @@ -423,7 +432,7 @@ def set_sim_option( for test_bench in check_not_empty(test_benches, allow_empty, "No test benches found"): test_bench.set_sim_option(name, value, overwrite) - def set_compile_option(self, name: str, value: str, allow_empty: Optional[bool] = False): + def set_compile_option(self, name: str, value: OptionType, allow_empty: bool = False) -> None: """ Set compile option of all files @@ -445,7 +454,7 @@ def set_compile_option(self, name: str, value: str, allow_empty: Optional[bool] for source_file in check_not_empty(source_files, allow_empty, "No source files found"): source_file.set_compile_option(name, value) - def add_compile_option(self, name: str, value: str, allow_empty: Optional[bool] = False): + def add_compile_option(self, name: str, value: OptionType, allow_empty: bool = False) -> None: """ Add compile option to all files @@ -460,7 +469,7 @@ def add_compile_option(self, name: str, value: str, allow_empty: Optional[bool] for source_file in check_not_empty(source_files, allow_empty, "No source files found"): source_file.add_compile_option(name, value) - def get_source_file(self, file_name: Union[str, Path], library_name: Optional[str] = None): + def get_source_file(self, file_name: Union[str, Path], library_name: Optional[str] = None) -> SourceFile: """ Get a source file @@ -483,10 +492,10 @@ def get_source_file(self, file_name: Union[str, Path], library_name: Optional[st def get_source_files( self, - pattern="*", + pattern: str = "*", library_name: Optional[str] = None, - allow_empty: Optional[bool] = False, - ): + allow_empty: bool = False, + ) -> SourceFileList: """ Get a list of source files @@ -520,16 +529,16 @@ def get_source_files( def add_source_files( # pylint: disable=too-many-arguments self, - pattern, + pattern: Union[str, Path], library_name: str, - preprocessors=None, - include_dirs=None, - defines=None, - allow_empty: Optional[bool] = False, + preprocessors: Optional[list[Preprocessor]] = None, + include_dirs: Optional[list] = None, + defines: Optional[dict] = None, + allow_empty: bool = False, vhdl_standard: Optional[str] = None, - no_parse: Optional[bool] = False, - file_type=None, - ): + no_parse: bool = False, + file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + ) -> SourceFileList: """ Add source files matching wildcard pattern to library @@ -567,13 +576,13 @@ def add_source_file( # pylint: disable=too-many-arguments self, file_name: Union[str, Path], library_name: str, - preprocessors=None, - include_dirs=None, - defines=None, + preprocessors: Optional[list[Preprocessor]] = None, + include_dirs: Optional[list[Any]] = None, + defines: Optional[dict] = None, vhdl_standard: Optional[str] = None, - no_parse: Optional[bool] = False, - file_type=None, - ): + no_parse: bool = False, + file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + ) -> SourceFile: """ Add source file to library @@ -605,7 +614,9 @@ def add_source_file( # pylint: disable=too-many-arguments file_type=file_type, ) - def _preprocess(self, library_name: str, file_name: Union[str, Path], preprocessors): + def _preprocess( + self, library_name: str, file_name: Union[str, Path], preprocessors: Optional[list[Preprocessor]] + ) -> str: """ Preprocess file_name within library_name using explicit preprocessors if preprocessors is None then use implicit globally defined preprocessors. @@ -648,7 +659,7 @@ def _preprocess(self, library_name: str, file_name: Union[str, Path], preprocess ostools.write_file(pp_file_name, code, encoding=HDL_FILE_ENCODING) return pp_file_name - def add_preprocessor(self, preprocessor): + def add_preprocessor(self, preprocessor: Preprocessor) -> None: """ Adds a custom preprocessor to be used on all files. Must be called before adding any files. @@ -656,7 +667,12 @@ def add_preprocessor(self, preprocessor): """ self._preprocessors.append((preprocessor)) - def enable_location_preprocessing(self, additional_subprograms=None, exclude_subprograms=None, order=100): + def enable_location_preprocessing( + self, + additional_subprograms: Optional[list[str]] = None, + exclude_subprograms: Optional[list[str]] = None, + order: int = 100, + ) -> None: """ Inserts file name and line number information into VUnit check and log subprograms calls. Custom subprograms can also be added. Must be called before adding any files. @@ -686,7 +702,7 @@ def enable_location_preprocessing(self, additional_subprograms=None, exclude_sub self.add_preprocessor(preprocessor) - def enable_check_preprocessing(self, order=200): + def enable_check_preprocessing(self, order: int = 200) -> None: """ Inserts error context information into VUnit check_relation calls. @@ -696,7 +712,7 @@ def enable_check_preprocessing(self, order=200): """ self.add_preprocessor(CheckPreprocessor(order)) - def main(self, post_run=None): + def main(self, post_run: Optional[Callable[[Results], None]] = None) -> None: """ Run vunit main function and exit @@ -723,7 +739,7 @@ def main(self, post_run=None): sys.exit(0) - def _create_tests(self, simulator_if: Union[None, SimulatorInterface]): + def _create_tests(self, simulator_if: Optional[SimulatorInterface]) -> TestList: """ Create the test cases """ @@ -732,7 +748,7 @@ def _create_tests(self, simulator_if: Union[None, SimulatorInterface]): test_list.keep_matches(self._test_filter) return test_list - def _main(self, post_run): + def _main(self, post_run: Optional[Callable[[Results], None]]) -> bool: """ Base vunit main function without performing exit """ @@ -752,7 +768,7 @@ def _main(self, post_run): all_ok = self._main_run(post_run) return all_ok - def _create_simulator_if(self): + def _create_simulator_if(self) -> SimulatorInterface: """ Create new simulator instance """ @@ -770,7 +786,7 @@ def _create_simulator_if(self): return self._simulator_class.from_args(args=self._args, output_path=self._simulator_output_path) - def _main_run(self, post_run): + def _main_run(self, post_run: Optional[Callable[[Results], None]]) -> bool: """ Main with running tests """ @@ -794,7 +810,7 @@ def _main_run(self, post_run): report.print_str() if post_run is not None: - post_run(results=Results(self._output_path, simulator_if, report)) + post_run(Results(self._output_path, simulator_if, report)) del simulator_if @@ -804,7 +820,7 @@ def _main_run(self, post_run): return report.all_ok() - def _main_list_only(self): + def _main_list_only(self) -> Literal[True]: """ Main function when only listing test cases """ @@ -814,7 +830,7 @@ def _main_list_only(self): print(f"Listed {test_list.num_tests} tests") return True - def _main_export_json(self, json_file_name: Union[str, Path]): # pylint: disable=too-many-locals + def _main_export_json(self, json_file_name: Union[str, Path]) -> Literal[True]: # pylint: disable=too-many-locals """ Main function when exporting to JSON """ @@ -869,7 +885,7 @@ def _main_export_json(self, json_file_name: Union[str, Path]): # pylint: disabl return True - def _main_list_files_only(self): + def _main_list_files_only(self) -> Literal[True]: """ Main function when only listing files """ @@ -879,7 +895,7 @@ def _main_list_files_only(self): print(f"Listed {len(files)} files") return True - def _main_compile_only(self): + def _main_compile_only(self) -> Literal[True]: """ Main function when only compiling """ @@ -887,7 +903,7 @@ def _main_compile_only(self): self._compile(simulator_if) return True - def _create_output_path(self, clean: bool): + def _create_output_path(self, clean: bool) -> None: """ Create or re-create the output path if necessary """ @@ -903,14 +919,14 @@ def vhdl_standard(self) -> str: return str(self._vhdl_standard) @property - def _preprocessed_path(self): + def _preprocessed_path(self) -> str: return str(Path(self._output_path) / "preprocessed") @property - def codecs_path(self): + def codecs_path(self) -> str: return str(Path(self._output_path) / "codecs") - def _compile(self, simulator_if: SimulatorInterface): + def _compile(self, simulator_if: SimulatorInterface) -> None: """ Compile entire project """ @@ -927,7 +943,7 @@ def _compile(self, simulator_if: SimulatorInterface): target_files=target_files, ) - def _get_testbench_files(self, simulator_if: Union[None, SimulatorInterface]): + def _get_testbench_files(self, simulator_if: Union[None, SimulatorInterface]) -> list[Source_File]: """ Return the list of all test bench files for the currently selected tests to run """ @@ -938,7 +954,7 @@ def _get_testbench_files(self, simulator_if: Union[None, SimulatorInterface]): for file_name in tb_file_names ] - def _run_test(self, test_cases, report): + def _run_test(self, test_cases: TestList, report: TestReport) -> None: """ Run the test suites and return the report """ @@ -961,7 +977,7 @@ def _run_test(self, test_cases, report): ) runner.run(test_cases) - def add_verilog_builtins(self): + def add_verilog_builtins(self) -> None: """ Add VUnit Verilog builtin libraries. @@ -972,7 +988,9 @@ def add_verilog_builtins(self): """ self._builtins.add_verilog_builtins() - def add_vhdl_builtins(self, external=None, use_external_log=None): + def add_vhdl_builtins( + self, external: Optional[dict[str, list[str]]] = None, use_external_log: Optional[Union[str, Path]] = None + ) -> None: """ Add VUnit VHDL builtin libraries. @@ -996,43 +1014,43 @@ def add_vhdl_builtins(self, external=None, use_external_log=None): """ self._builtins.add_vhdl_builtins(external=external, use_external_log=use_external_log) - def add_com(self): + def add_com(self) -> None: """ Add communication package """ self._builtins.add("com") - def add_array_util(self): + def add_array_util(self) -> None: """ Add array util """ self._builtins.add("array_util") - def add_random(self): + def add_random(self) -> None: """ Add random """ self._builtins.add("random") - def add_verification_components(self): + def add_verification_components(self) -> None: """ Add verification component library """ self._builtins.add("verification_components") - def add_osvvm(self): + def add_osvvm(self) -> None: """ Add osvvm library """ self._builtins.add("osvvm") - def add_json4vhdl(self): + def add_json4vhdl(self) -> None: """ Add JSON-for-VHDL library """ self._builtins.add("json4vhdl") - def get_compile_order(self, source_files=None): + def get_compile_order(self, source_files: Optional[list[SourceFile]] = None) -> SourceFileList: """ Get the compile order of all or specific source files and their dependencies. @@ -1053,10 +1071,10 @@ def get_compile_order(self, source_files=None): source_files = self.get_source_files(allow_empty=True) target_files = [source_file._source_file for source_file in source_files] # pylint: disable=protected-access - source_files = self._project.get_dependencies_in_compile_order(target_files) - return SourceFileList([SourceFile(source_file, self._project, self) for source_file in source_files]) + source_files_ordered = self._project.get_dependencies_in_compile_order(target_files) + return SourceFileList([SourceFile(source_file, self._project, self) for source_file in source_files_ordered]) - def get_implementation_subset(self, source_files): + def get_implementation_subset(self, source_files: list[SourceFile]) -> SourceFileList: """ Get the subset of files which are required to successfully elaborate the list of input files without any missing @@ -1066,10 +1084,12 @@ def get_implementation_subset(self, source_files): :returns: A list of :class:`.SourceFile` objects which is the implementation subset. """ target_files = [source_file._source_file for source_file in source_files] # pylint: disable=protected-access - source_files = self._project.get_dependencies_in_compile_order(target_files, implementation_dependencies=True) - return SourceFileList([SourceFile(source_file, self._project, self) for source_file in source_files]) + source_files_ordered = self._project.get_dependencies_in_compile_order( + target_files, implementation_dependencies=True + ) + return SourceFileList([SourceFile(source_file, self._project, self) for source_file in source_files_ordered]) - def get_simulator_name(self): + def get_simulator_name(self) -> Optional[str]: """ Get the name of the simulator used. @@ -1079,7 +1099,7 @@ def get_simulator_name(self): return None return self._simulator_class.name - def simulator_supports_coverage(self): + def simulator_supports_coverage(self) -> Union[None, bool]: """ Returns True when the simulator supports coverage diff --git a/vunit/ui/common.py b/vunit/ui/common.py index 3ba87335a..1f8865620 100644 --- a/vunit/ui/common.py +++ b/vunit/ui/common.py @@ -12,7 +12,9 @@ from glob import glob from os import environ from logging import getLogger -from typing import Optional, List +from typing import Any, Iterable, Optional, List, TypeVar, Union + +from vunit.ui.source import SourceFile from ..sim_if import is_string_not_iterable from ..vhdl_standard import VHDL, VHDLStandard @@ -35,7 +37,10 @@ def select_vhdl_standard(vhdl_standard: Optional[str] = None) -> VHDLStandard: raise -def lower_generics(generics): +T = TypeVar("T") + + +def lower_generics(generics: dict[str, T]) -> dict[str, T]: """ Convert all generics names to lower case to match internal representation. @TODO Maybe warn in case of conflict. VHDL forbids this though so the user will notice anyway. @@ -43,7 +48,7 @@ def lower_generics(generics): return dict((name.lower(), value) for name, value in generics.items()) -def check_not_empty(lst, allow_empty, error_msg): +def check_not_empty(lst: list[T], allow_empty: bool, error_msg: str) -> list[T]: """ Raise ValueError if the list is empty unless allow_empty is True Returns the list @@ -53,12 +58,12 @@ def check_not_empty(lst, allow_empty, error_msg): return lst -def get_checked_file_names_from_globs(pattern, allow_empty): +def get_checked_file_names_from_globs(pattern: Union[Iterable[str], str, Path], allow_empty: bool) -> list[str]: """ Get file names from globs and check that exist """ - if is_string_not_iterable(pattern): - patterns = [pattern] + if isinstance(pattern, str): + patterns: Iterable[str] = [pattern] elif isinstance(pattern, Path): patterns = [str(pattern)] else: diff --git a/vunit/ui/library.py b/vunit/ui/library.py index 475a4c237..c882b91a9 100644 --- a/vunit/ui/library.py +++ b/vunit/ui/library.py @@ -10,7 +10,12 @@ from pathlib import Path from fnmatch import fnmatch -from typing import Optional +from typing import Any, List, Literal, Optional, Union +from vunit.sim_if import OptionType + +from vunit.test.bench_list import TestBenchList +from vunit.ui import VUnit +from vunit.ui.preprocessor import Preprocessor from ..vhdl_standard import VHDL, VHDLStandard from ..project import Project from ..source_file import file_type_of, FILE_TYPES, VERILOG_FILE_TYPES @@ -21,199 +26,25 @@ from .packagefacade import PackageFacade -class LibraryList(list): - """ - A list of :class:`.Library` - """ - - def __init__(self, libraries): - list.__init__(self, libraries) - - def get_test_benches(self, pattern="*", allow_empty=False): - """ - Get a list of test benches - - :param pattern: A wildcard pattern matching the test_bench name - :param allow_empty: To disable an error when no test benches were found - :returns: A list of :class:`.TestBench` objects - """ - results = [] - for library in self: - results += library.get_test_benches(pattern, allow_empty=True) - - return check_not_empty( - results, - allow_empty, - "No testbenches found within libraries", - ) - - def set_generic(self, name, value, allow_empty=False): - """ - Set a value of generic within all |configurations| of test benches and tests in these libraries - - :param name: The name of the generic - :param value: The value of the generic - :param allow_empty: To disable an error when no test benches were found - - :example: - - .. code-block:: python - - libs.set_generic("data_width", 16) - - .. note:: - Only affects test benches added *before* the generic is set. - """ - check_not_empty( - self.get_test_benches(allow_empty=True), - allow_empty, - "No testbenches in libraries", - ) - - for library in self: - library.set_generic(name, value, allow_empty=True) - - def set_parameter(self, name, value, allow_empty=False): - """ - Set a value of parameter within all |configurations| of test benches and tests in these libraries - - :param name: The name of the parameter - :param value: The value of the parameter - :param allow_empty: To disable an error when no test benches were found - - :example: - - .. code-block:: python - - libs.set_parameter("data_width", 16) - - .. note:: - Only affects test benches added *before* the parameter is set. - """ - check_not_empty( - self.get_test_benches(allow_empty=True), - allow_empty, - "No testbenches in libraries", - ) - - for library in self: - library.set_parameter(name, value, allow_empty=True) - - def set_sim_option(self, name, value, allow_empty=False, overwrite=True): - """ - Set simulation option within all |configurations| of test benches and tests in these libraries. - - :param name: |simulation_options| - :param value: The value of the simulation option - :param allow_empty: To disable an error when no test benches were found - :param overwrite: To overwrite the option or append to the existing value - - :example: - - .. code-block:: python - - libs.set_sim_option("ghdl.a_flags", ["--no-vital-checks"]) - - .. note:: - Only affects test benches added *before* the option is set. - """ - check_not_empty( - self.get_test_benches(allow_empty=True), - allow_empty, - "No testbenches in libraries", - ) - - for library in self: - library.set_sim_option(name, value, allow_empty=True, overwrite=overwrite) - - def get_source_files(self, pattern="*", allow_empty=False): - """ - Get a list of source files within these libraries - - :param pattern: A wildcard pattern matching either an absolute or relative path - :param allow_empty: To disable an error if no files matched the pattern - :returns: A :class:`.SourceFileList` object - """ - - results = [ - source_file for library in self for source_file in library.get_source_files(pattern, allow_empty=True) - ] - - check_not_empty( - results, - allow_empty, - f"Pattern {pattern} did not match any file", - ) - - return SourceFileList(results) - - def set_compile_option(self, name, value, allow_empty=False): - """ - Set compile option for all files within these libraries - - :param name: |compile_option| - :param value: The value of the compile option - :param allow_empty: To disable an error when no source files were found - - :example: - - .. code-block:: python - - libs.set_compile_option("ghdl.a_flags", ["--no-vital-checks"]) - - - .. note:: - Only affects files added *before* the option is set. - """ - check_not_empty( - self.get_source_files(allow_empty=True), - allow_empty, - "No source files in libraries", - ) - - for library in self: - library.set_compile_option(name, value, allow_empty=True) - - def add_compile_option(self, name, value, allow_empty=False): - """ - Add compile option to all files within these libraries - - :param name: |compile_option| - :param value: The value of the compile option - :param allow_empty: To disable an error when no source files were found - - .. note:: - Only affects files added *before* the option is set. - """ - check_not_empty( - self.get_source_files(allow_empty=True), - allow_empty, - "No source files in libraries", - ) - - for library in self: - library.add_compile_option(name, value, allow_empty=True) - - class Library(object): """ User interface of a library """ - def __init__(self, library_name, parent, project: Project, test_bench_list): + def __init__(self, library_name: str, parent: VUnit, project: Project, test_bench_list: TestBenchList) -> None: self._library_name = library_name self._parent = parent self._project = project self._test_bench_list = test_bench_list @property - def name(self): + def name(self) -> str: """ The name of the library """ return self._library_name - def set_generic(self, name, value, allow_empty=False): + def set_generic(self, name: str, value: Any, allow_empty: bool = False) -> None: """ Set a value of generic within all |configurations| of test benches and tests this library @@ -233,7 +64,7 @@ def set_generic(self, name, value, allow_empty=False): for test_bench in self.get_test_benches(allow_empty=allow_empty): test_bench.set_generic(name.lower(), value) - def set_parameter(self, name, value, allow_empty=False): + def set_parameter(self, name: str, value: Any, allow_empty: bool = False) -> None: """ Set a value of parameter within all |configurations| of test benches and tests this library @@ -253,7 +84,7 @@ def set_parameter(self, name, value, allow_empty=False): for test_bench in self.get_test_benches(allow_empty=allow_empty): test_bench.set_generic(name, value) - def set_sim_option(self, name, value, allow_empty=False, overwrite=True): + def set_sim_option(self, name: str, value: OptionType, allow_empty: bool = False, overwrite: bool = True) -> None: """ Set simulation option within all |configurations| of test benches and tests this library @@ -274,7 +105,7 @@ def set_sim_option(self, name, value, allow_empty=False, overwrite=True): for test_bench in self.get_test_benches(allow_empty=allow_empty): test_bench.set_sim_option(name, value, overwrite) - def set_compile_option(self, name, value, allow_empty=False): + def set_compile_option(self, name: str, value: OptionType, allow_empty: bool = False) -> None: """ Set compile option for all files within the library @@ -295,7 +126,7 @@ def set_compile_option(self, name, value, allow_empty=False): for source_file in self.get_source_files(allow_empty=allow_empty): source_file.set_compile_option(name, value) - def add_compile_option(self, name, value, allow_empty=False): + def add_compile_option(self, name: str, value: OptionType, allow_empty: bool = False) -> None: """ Add compile option to all files within the library @@ -309,7 +140,7 @@ def add_compile_option(self, name, value, allow_empty=False): for source_file in self.get_source_files(allow_empty=allow_empty): source_file.add_compile_option(name, value) - def get_source_file(self, file_name): + def get_source_file(self, file_name: str) -> SourceFile: """ Get a source file within this library @@ -319,7 +150,7 @@ def get_source_file(self, file_name): """ return self._parent.get_source_file(file_name, self._library_name) - def get_source_files(self, pattern="*", allow_empty=False): + def get_source_files(self, pattern: str = "*", allow_empty: bool = False) -> SourceFileList: """ Get a list of source files within this libary @@ -331,15 +162,15 @@ def get_source_files(self, pattern="*", allow_empty=False): def add_source_files( # pylint: disable=too-many-arguments self, - pattern, - preprocessors=None, - include_dirs=None, - defines=None, - allow_empty=False, + pattern: Union[str, Path], + preprocessors: Optional[list[Preprocessor]] = None, + include_dirs: Optional[list[str]] = None, + defines: Optional[dict] = None, + allow_empty: bool = False, vhdl_standard: Optional[str] = None, - no_parse=False, - file_type=None, - ): + no_parse: bool = False, + file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + ) -> SourceFileList: """ Add source files matching wildcard pattern to library @@ -377,14 +208,14 @@ def add_source_files( # pylint: disable=too-many-arguments def add_source_file( # pylint: disable=too-many-arguments self, - file_name, - preprocessors=None, - include_dirs=None, - defines=None, + file_name: Union[str, Path], + preprocessors: Optional[list[Preprocessor]] = None, + include_dirs: Optional[list[str]] = None, + defines: Optional[dict] = None, vhdl_standard: Optional[str] = None, - no_parse=False, - file_type=None, - ): + no_parse: bool = False, + file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + ) -> SourceFile: """ Add source file to library @@ -435,7 +266,7 @@ def add_source_file( # pylint: disable=too-many-arguments return SourceFile(source_file, self._project, self._parent) - def package(self, name): + def package(self, name: str) -> PackageFacade: """ Get a package within the library """ @@ -449,7 +280,7 @@ def package(self, name): return PackageFacade(self._parent, self._library_name, name, design_unit) - def entity(self, name): + def entity(self, name: str) -> TestBench: """ Get an entity within the library @@ -464,7 +295,7 @@ def entity(self, name): return self.test_bench(name) - def module(self, name): + def module(self, name: str) -> TestBench: """ Get a module within the library @@ -478,7 +309,7 @@ def module(self, name): return self.test_bench(name) - def test_bench(self, name): + def test_bench(self, name: str) -> TestBench: """ Get a test bench within this library @@ -490,7 +321,7 @@ def test_bench(self, name): return TestBench(self._test_bench_list.get_test_bench(self._library_name, name), self) - def get_test_benches(self, pattern="*", allow_empty=False): + def get_test_benches(self, pattern: str = "*", allow_empty: bool = False) -> list[TestBench]: """ Get a list of test benches @@ -500,7 +331,7 @@ def get_test_benches(self, pattern="*", allow_empty=False): """ results = [] for test_bench in self._test_bench_list.get_test_benches_in_library(self._library_name): - if not fnmatch(Path(test_bench.name).resolve(), pattern): + if not fnmatch(str(Path(test_bench.name).resolve()), pattern): continue results.append(TestBench(test_bench, self)) @@ -520,3 +351,177 @@ def _which_vhdl_standard(self, vhdl_standard: Optional[str]) -> VHDLStandard: return self._project.get_library(self._library_name).vhdl_standard return VHDL.standard(vhdl_standard) + + +class LibraryList(List[Library]): + """ + A list of :class:`.Library` + """ + + def __init__(self, libraries: "list[Library]"): + list.__init__(self, libraries) + + def get_test_benches(self, pattern: str = "*", allow_empty: bool = False) -> list[TestBench]: + """ + Get a list of test benches + + :param pattern: A wildcard pattern matching the test_bench name + :param allow_empty: To disable an error when no test benches were found + :returns: A list of :class:`.TestBench` objects + """ + results = [] + for library in self: + results += library.get_test_benches(pattern, allow_empty=True) + + return check_not_empty( + results, + allow_empty, + "No testbenches found within libraries", + ) + + def set_generic(self, name: str, value: Any, allow_empty: bool = False) -> None: + """ + Set a value of generic within all |configurations| of test benches and tests in these libraries + + :param name: The name of the generic + :param value: The value of the generic + :param allow_empty: To disable an error when no test benches were found + + :example: + + .. code-block:: python + + libs.set_generic("data_width", 16) + + .. note:: + Only affects test benches added *before* the generic is set. + """ + check_not_empty( + self.get_test_benches(allow_empty=True), + allow_empty, + "No testbenches in libraries", + ) + + for library in self: + library.set_generic(name, value, allow_empty=True) + + def set_parameter(self, name: str, value: Any, allow_empty: bool = False) -> None: + """ + Set a value of parameter within all |configurations| of test benches and tests in these libraries + + :param name: The name of the parameter + :param value: The value of the parameter + :param allow_empty: To disable an error when no test benches were found + + :example: + + .. code-block:: python + + libs.set_parameter("data_width", 16) + + .. note:: + Only affects test benches added *before* the parameter is set. + """ + check_not_empty( + self.get_test_benches(allow_empty=True), + allow_empty, + "No testbenches in libraries", + ) + + for library in self: + library.set_parameter(name, value, allow_empty=True) + + def set_sim_option(self, name: str, value: OptionType, allow_empty: bool = False, overwrite: bool = True) -> None: + """ + Set simulation option within all |configurations| of test benches and tests in these libraries. + + :param name: |simulation_options| + :param value: The value of the simulation option + :param allow_empty: To disable an error when no test benches were found + :param overwrite: To overwrite the option or append to the existing value + + :example: + + .. code-block:: python + + libs.set_sim_option("ghdl.a_flags", ["--no-vital-checks"]) + + .. note:: + Only affects test benches added *before* the option is set. + """ + check_not_empty( + self.get_test_benches(allow_empty=True), + allow_empty, + "No testbenches in libraries", + ) + + for library in self: + library.set_sim_option(name, value, allow_empty=True, overwrite=overwrite) + + def get_source_files(self, pattern: str = "*", allow_empty: bool = False) -> SourceFileList: + """ + Get a list of source files within these libraries + + :param pattern: A wildcard pattern matching either an absolute or relative path + :param allow_empty: To disable an error if no files matched the pattern + :returns: A :class:`.SourceFileList` object + """ + + results = [ + source_file for library in self for source_file in library.get_source_files(pattern, allow_empty=True) + ] + + check_not_empty( + results, + allow_empty, + f"Pattern {pattern} did not match any file", + ) + + return SourceFileList(results) + + def set_compile_option(self, name: str, value: OptionType, allow_empty: bool = False) -> None: + """ + Set compile option for all files within these libraries + + :param name: |compile_option| + :param value: The value of the compile option + :param allow_empty: To disable an error when no source files were found + + :example: + + .. code-block:: python + + libs.set_compile_option("ghdl.a_flags", ["--no-vital-checks"]) + + + .. note:: + Only affects files added *before* the option is set. + """ + check_not_empty( + self.get_source_files(allow_empty=True), + allow_empty, + "No source files in libraries", + ) + + for library in self: + library.set_compile_option(name, value, allow_empty=True) + + def add_compile_option(self, name: str, value: OptionType, allow_empty: bool = False) -> None: + """ + Add compile option to all files within these libraries + + :param name: |compile_option| + :param value: The value of the compile option + :param allow_empty: To disable an error when no source files were found + + .. note:: + Only affects files added *before* the option is set. + """ + check_not_empty( + self.get_source_files(allow_empty=True), + allow_empty, + "No source files in libraries", + ) + + for library in self: + library.add_compile_option(name, value, allow_empty=True) diff --git a/vunit/ui/packagefacade.py b/vunit/ui/packagefacade.py index 7c6d6d04b..ea1decc96 100644 --- a/vunit/ui/packagefacade.py +++ b/vunit/ui/packagefacade.py @@ -9,6 +9,11 @@ """ from pathlib import Path +from typing import Optional, Union +from vunit.design_unit import DesignUnit + +from vunit.ui import VUnit +from vunit.ui.source import SourceFileList from ..com import codec_generator @@ -17,13 +22,18 @@ class PackageFacade(object): User interface of a Package """ - def __init__(self, parent, library_name, package_name, design_unit): + def __init__(self, parent: VUnit, library_name: str, package_name: str, design_unit: DesignUnit) -> None: self._parent = parent self._library_name = library_name self._package_name = package_name self._design_unit = design_unit - def generate_codecs(self, codec_package_name=None, used_packages=None, output_file_name=None): + def generate_codecs( + self, + codec_package_name: Optional[str] = None, + used_packages: Optional[list[str]] = None, + output_file_name: Optional[Union[str, Path]] = None, + ) -> SourceFileList: """ Generates codecs for the datatypes in this Package """ diff --git a/vunit/ui/results.py b/vunit/ui/results.py index ea2ddfd6b..0570f7a45 100644 --- a/vunit/ui/results.py +++ b/vunit/ui/results.py @@ -9,7 +9,10 @@ """ from pathlib import Path -from typing import Dict, Union +from typing import Any, Dict, Optional, Union + +from vunit.sim_if import SimulatorInterface +from vunit.test.report import TestReport from .common import TEST_OUTPUT_PATH @@ -18,12 +21,12 @@ class Results(object): Gives access to results after running tests """ - def __init__(self, output_path, simulator_if, report): + def __init__(self, output_path: str, simulator_if: SimulatorInterface, report: TestReport) -> None: self._output_path = output_path self._simulator_if = simulator_if self._report = report - def merge_coverage(self, file_name, args=None): + def merge_coverage(self, file_name: str, args: Optional[list[str]] = None) -> None: """ Create a merged coverage report from the individual coverage files @@ -32,7 +35,7 @@ def merge_coverage(self, file_name, args=None): """ self._simulator_if.merge_coverage(file_name=file_name, args=args) - def get_report(self): + def get_report(self) -> "Report": """ Get a report (dictionary) of tests: status, time and output path @@ -92,7 +95,7 @@ def post_func(results): vu.main(post_run=post_func) """ - def __init__(self, test_output_path: Union[str, Path], status, time, path: Union[str, Path]): + def __init__(self, test_output_path: Union[str, Path], status: Any, time: Any, path: Union[str, Path]) -> None: self._test_output_path = Path(test_output_path) self.status = status self.time = time diff --git a/vunit/ui/source.py b/vunit/ui/source.py index 18ab1268c..b2b88984e 100644 --- a/vunit/ui/source.py +++ b/vunit/ui/source.py @@ -8,58 +8,14 @@ UI classes SourceFile and SourceFileList """ -from .. import ostools - - -class SourceFileList(list): - """ - A list of :class:`.SourceFile` - """ - - def __init__(self, source_files): - list.__init__(self, source_files) - - def set_compile_option(self, name, value): - """ - Set compile option for all files in the list - - :param name: |compile_option| - :param value: The value of the compile option - - :example: - - .. code-block:: python +from typing import Iterable, List, Optional, Union - files.set_compile_option("ghdl.a_flags", ["--no-vital-checks"]) - """ - for source_file in self: - source_file.set_compile_option(name, value) - - def add_compile_option(self, name, value): - """ - Add compile option to all files in the list - - :param name: |compile_option| - :param value: The value of the compile option - """ - for source_file in self: - source_file.add_compile_option(name, value) - - def add_dependency_on(self, source_file): - """ - Add manual dependency of these files on other file(s) - - :param source_file: The file(s) which this file depends on - - :example: - - .. code-block:: python - - other_file = lib.get_source_file("other_file.vhd") - files.add_dependency_on(other_file) - """ - for my_source_file in self: - my_source_file.add_dependency_on(source_file) +from vunit.project import Project +from vunit.sim_if import OptionType +from vunit.ui import VUnit +from vunit.ui.library import Library +from .. import ostools +from vunit.source_file import SourceFile as Source_File, VHDLSourceFile class SourceFile(object): @@ -67,37 +23,37 @@ class SourceFile(object): A single file """ - def __init__(self, source_file, project, ui): + def __init__(self, source_file: Source_File, project: Project, ui: VUnit) -> None: self._source_file = source_file self._project = project self._ui = ui @property - def name(self): + def name(self) -> str: """ The name of the SourceFile """ return ostools.simplify_path(self._source_file.name) @property - def vhdl_standard(self): + def vhdl_standard(self) -> Optional[str]: """ The VHDL standard applicable to the file, None if not a VHDL file """ - if self._source_file.file_type == "vhdl": + if isinstance(self._source_file, VHDLSourceFile): return str(self._source_file.get_vhdl_standard()) return None @property - def library(self): + def library(self) -> Library: """ The library of the source file """ return self._ui.library(self._source_file.library.name) - def set_compile_option(self, name, value): + def set_compile_option(self, name: str, value: OptionType) -> None: """ Set compile option for this file @@ -112,7 +68,7 @@ def set_compile_option(self, name, value): """ self._source_file.set_compile_option(name, value) - def add_compile_option(self, name, value): + def add_compile_option(self, name: str, value: OptionType) -> None: """ Add compile option to this file @@ -121,7 +77,7 @@ def add_compile_option(self, name, value): """ self._source_file.add_compile_option(name, value) - def get_compile_option(self, name): + def get_compile_option(self, name: str) -> OptionType: """ Return compile option of this file @@ -129,7 +85,7 @@ def get_compile_option(self, name): """ return self._source_file.get_compile_option(name) - def add_dependency_on(self, source_file): + def add_dependency_on(self, source_file: Union[Iterable[Source_File], Source_File]) -> None: """ Add manual dependency of this file other file(s) @@ -145,8 +101,59 @@ def add_dependency_on(self, source_file): if isinstance(source_file, SourceFile): private_source_file = source_file._source_file # pylint: disable=protected-access self._project.add_manual_dependency(self._source_file, depends_on=private_source_file) - elif hasattr(source_file, "__iter__"): + elif isinstance(source_file, Iterable): for element in source_file: self.add_dependency_on(element) else: raise ValueError(source_file) + + +class SourceFileList(List[SourceFile]): + """ + A list of :class:`.SourceFile` + """ + + def __init__(self, source_files: Iterable[SourceFile]): + list.__init__(self, source_files) + + def set_compile_option(self, name: str, value: OptionType) -> None: + """ + Set compile option for all files in the list + + :param name: |compile_option| + :param value: The value of the compile option + + :example: + + .. code-block:: python + + files.set_compile_option("ghdl.a_flags", ["--no-vital-checks"]) + """ + for source_file in self: + source_file.set_compile_option(name, value) + + def add_compile_option(self, name: str, value: OptionType) -> None: + """ + Add compile option to all files in the list + + :param name: |compile_option| + :param value: The value of the compile option + """ + for source_file in self: + source_file.add_compile_option(name, value) + + def add_dependency_on(self, source_file: Source_File) -> None: + """ + Add manual dependency of these files on other file(s) + + :param source_file: The file(s) which this file depends on + + :example: + + .. code-block:: python + + other_file = lib.get_source_file("other_file.vhd") + files.add_dependency_on(other_file) + """ + for my_source_file in self: + my_source_file.add_dependency_on(source_file) diff --git a/vunit/ui/test.py b/vunit/ui/test.py index ddb5f7be5..635d30c31 100644 --- a/vunit/ui/test.py +++ b/vunit/ui/test.py @@ -8,6 +8,10 @@ UI class Test """ +from typing import Any, Callable, Optional, cast +from vunit.sim_if import OptionType +from vunit.test.bench import TestConfigurationVisitor +from vunit.ui.results import Results from .common import lower_generics @@ -17,11 +21,11 @@ class Test(object): """ - def __init__(self, test_case): + def __init__(self, test_case: TestConfigurationVisitor) -> None: self._test_case = test_case @property - def name(self): + def name(self) -> str: """ :returns: the entity or module name of the test bench """ @@ -29,15 +33,15 @@ def name(self): def add_config( # pylint: disable=too-many-arguments self, - name, - generics=None, - parameters=None, - pre_config=None, - post_check=None, - sim_options=None, - attributes=None, - vhdl_configuration_name=None, - ): + name: str, + generics: Optional[dict] = None, + parameters: Optional[dict] = None, + pre_config: Optional[Callable] = None, + post_check: Optional[Callable] = None, + sim_options: Optional[dict[str, OptionType]] = None, + attributes: Optional[dict] = None, + vhdl_configuration_name: Optional[str] = None, + ) -> None: """ Add a configuration to this test copying the default configuration. @@ -79,7 +83,7 @@ def add_config( # pylint: disable=too-many-arguments generics = {} if generics is None else generics generics = lower_generics(generics) parameters = {} if parameters is None else parameters - generics.update(parameters) + cast(dict, generics).update(parameters) attributes = {} if attributes is None else attributes self._test_case.add_config( name=name, @@ -91,7 +95,7 @@ def add_config( # pylint: disable=too-many-arguments vhdl_configuration_name=vhdl_configuration_name, ) - def set_attribute(self, name, value): + def set_attribute(self, name: str, value: Any) -> None: """ Set a value of attribute within all |configurations| of this test @@ -107,7 +111,7 @@ def set_attribute(self, name, value): """ self._test_case.set_attribute(name, value) - def set_generic(self, name, value): + def set_generic(self, name: str, value: Any) -> None: """ Set a value of generic within all |configurations| of this test @@ -123,7 +127,7 @@ def set_generic(self, name, value): """ self._test_case.set_generic(name.lower(), value) - def set_parameter(self, name, value): + def set_parameter(self, name: str, value: Any) -> None: """ Set a value of parameter within all |configurations| of this test @@ -139,7 +143,7 @@ def set_parameter(self, name, value): """ self._test_case.set_generic(name, value) - def set_vhdl_configuration_name(self, value: str): + def set_vhdl_configuration_name(self, value: str) -> None: """ Set VHDL configuration name of all |configurations| of this test @@ -148,7 +152,7 @@ def set_vhdl_configuration_name(self, value: str): """ self._test_case.set_vhdl_configuration_name(value) - def set_sim_option(self, name, value, overwrite=True): + def set_sim_option(self, name: str, value: OptionType, overwrite: bool = True) -> None: """ Set simulation option within all |configurations| of this test @@ -165,7 +169,7 @@ def set_sim_option(self, name, value, overwrite=True): """ self._test_case.set_sim_option(name, value, overwrite) - def set_pre_config(self, value): + def set_pre_config(self, value: Callable) -> None: """ Set :ref:`pre_config ` function of all |configurations| of this test @@ -173,7 +177,7 @@ def set_pre_config(self, value): """ self._test_case.set_pre_config(value) - def set_post_check(self, value): + def set_post_check(self, value: Callable) -> None: """ Set :ref:`post_check ` function of all |configurations| of this test diff --git a/vunit/ui/testbench.py b/vunit/ui/testbench.py index 9a7b7d63c..cca617560 100644 --- a/vunit/ui/testbench.py +++ b/vunit/ui/testbench.py @@ -9,8 +9,13 @@ """ from fnmatch import fnmatch +from typing import Any, Callable, Optional, cast + +from vunit.sim_if import OptionType +from vunit.ui.library import Library from .common import lower_generics from .test import Test +from vunit.test.bench import TestBench as Test_Bench class TestBench(object): @@ -20,25 +25,25 @@ class TestBench(object): bench will apply that option to all test cases belonging to that test bench. """ - def __init__(self, test_bench, library): + def __init__(self, test_bench: Test_Bench, library: Library) -> None: self._test_bench = test_bench self._library = library @property - def name(self): + def name(self) -> str: """ :returns: The entity or module name of the test bench """ return self._test_bench.name @property - def library(self): + def library(self) -> Library: """ :returns: The library that contains this test bench """ return self._library - def set_attribute(self, name, value): + def set_attribute(self, name: str, value: str) -> None: """ Set a value of attribute within all |configurations| of this test bench or test cases within it @@ -54,7 +59,7 @@ def set_attribute(self, name, value): """ self._test_bench.set_attribute(name, value) - def set_generic(self, name, value): + def set_generic(self, name: str, value: Any) -> None: """ Set a value of generic within all |configurations| of this test bench or test cases within it @@ -70,7 +75,7 @@ def set_generic(self, name, value): """ self._test_bench.set_generic(name.lower(), value) - def set_parameter(self, name, value): + def set_parameter(self, name: str, value: Any) -> None: """ Set a value of parameter within all |configurations| of this test bench or test cases within it @@ -86,7 +91,7 @@ def set_parameter(self, name, value): """ self._test_bench.set_generic(name, value) - def set_vhdl_configuration_name(self, value: str): + def set_vhdl_configuration_name(self, value: str) -> None: """ Set VHDL configuration name of all |configurations| of this test bench or test cases within it @@ -95,7 +100,7 @@ def set_vhdl_configuration_name(self, value: str): """ self._test_bench.set_vhdl_configuration_name(value) - def set_sim_option(self, name, value, overwrite=True): + def set_sim_option(self, name: str, value: OptionType, overwrite: bool = True) -> None: """ Set simulation option within all |configurations| of this test bench or test cases within it @@ -112,7 +117,7 @@ def set_sim_option(self, name, value, overwrite=True): """ self._test_bench.set_sim_option(name, value, overwrite) - def set_pre_config(self, value): + def set_pre_config(self, value: Callable) -> None: """ Set :ref:`pre_config ` function of all |configurations| of this test bench or test cases within it @@ -121,7 +126,7 @@ def set_pre_config(self, value): """ self._test_bench.set_pre_config(value) - def set_post_check(self, value): + def set_post_check(self, value: Callable) -> None: """ Set :ref:`post_check ` function of all |configurations| of this test bench or test cases within it @@ -132,15 +137,15 @@ def set_post_check(self, value): def add_config( # pylint: disable=too-many-arguments self, - name, - generics=None, - parameters=None, - pre_config=None, - post_check=None, - sim_options=None, - attributes=None, - vhdl_configuration_name=None, - ): + name: str, + generics: Optional[dict[str, Any]] = None, + parameters: Optional[dict[str, Any]] = None, + pre_config: Optional[Callable] = None, + post_check: Optional[Callable] = None, + sim_options: Optional[dict[str, OptionType]] = None, + attributes: Optional[dict[str, Any]] = None, + vhdl_configuration_name: Optional[str] = None, + ) -> None: """ Add a configuration of this test bench or to all test cases within it by copying the default configuration. @@ -183,7 +188,7 @@ def add_config( # pylint: disable=too-many-arguments generics = {} if generics is None else generics generics = lower_generics(generics) parameters = {} if parameters is None else parameters - generics.update(parameters) + cast(dict, generics).update(parameters) attributes = {} if attributes is None else attributes self._test_bench.add_config( name=name, @@ -195,7 +200,7 @@ def add_config( # pylint: disable=too-many-arguments vhdl_configuration_name=vhdl_configuration_name, ) - def test(self, name): + def test(self, name: str) -> Test: """ Get a test within this test bench @@ -204,7 +209,7 @@ def test(self, name): """ return Test(self._test_bench.get_test_case(name)) - def get_tests(self, pattern="*"): + def get_tests(self, pattern: str = "*") -> list[Test]: """ Get a list of tests @@ -219,7 +224,7 @@ def get_tests(self, pattern="*"): results.append(Test(test_case)) return results - def scan_tests_from_file(self, file_name): + def scan_tests_from_file(self, file_name: str) -> None: """ Scan tests from another file than the one containing the test bench. Useful for when the top level test bench does not From 80961aae936ec4b66420d118608cf9d6c319828a Mon Sep 17 00:00:00 2001 From: Anton Schulte Date: Thu, 28 Sep 2023 11:16:02 +0200 Subject: [PATCH 2/9] fix testing --- vunit/library.py | 7 +++++-- vunit/ui/__init__.py | 8 ++++++-- vunit/ui/library.py | 8 ++++++-- vunit/ui/packagefacade.py | 7 +++++-- vunit/ui/results.py | 8 +++++--- vunit/ui/source.py | 20 +++++++++++++------- vunit/ui/testbench.py | 9 ++++++--- 7 files changed, 46 insertions(+), 21 deletions(-) diff --git a/vunit/library.py b/vunit/library.py index af0f49957..68e75b40e 100644 --- a/vunit/library.py +++ b/vunit/library.py @@ -13,7 +13,10 @@ import logging from typing import cast from vunit.design_unit import Entity, VHDLDesignUnit -from vunit.source_file import SourceFile, VHDLSourceFile, VerilogSourceFile +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from vunit.source_file import SourceFile, VHDLSourceFile, VerilogSourceFile from vunit.vhdl_standard import VHDLStandard LOGGER = logging.getLogger(__name__) @@ -49,7 +52,7 @@ def __init__(self, name: str, directory: str, vhdl_standard: VHDLStandard, is_ex self._is_external = is_external - def add_source_file(self, source_file: SourceFile) -> SourceFile: + def add_source_file(self, source_file: "SourceFile") -> "SourceFile": """ Add source file to library unless it exists diff --git a/vunit/ui/__init__.py b/vunit/ui/__init__.py index bb6d4a3f8..3599bf072 100644 --- a/vunit/ui/__init__.py +++ b/vunit/ui/__init__.py @@ -23,7 +23,6 @@ from vunit.test.list import TestList from vunit.ui.preprocessor import Preprocessor -from vunit.source_file import SourceFile as Source_File from ..database import PickledDataBase, DataBase from .. import ostools @@ -48,6 +47,11 @@ from .library import Library, LibraryList from .results import Results +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from vunit.source_file import SourceFile as Source_File + class VUnit(object): # pylint: disable=too-many-instance-attributes, too-many-public-methods """ @@ -943,7 +947,7 @@ def _compile(self, simulator_if: SimulatorInterface) -> None: target_files=target_files, ) - def _get_testbench_files(self, simulator_if: Union[None, SimulatorInterface]) -> list[Source_File]: + def _get_testbench_files(self, simulator_if: Union[None, SimulatorInterface]) -> list["Source_File"]: """ Return the list of all test bench files for the currently selected tests to run """ diff --git a/vunit/ui/library.py b/vunit/ui/library.py index c882b91a9..e355d21ad 100644 --- a/vunit/ui/library.py +++ b/vunit/ui/library.py @@ -14,7 +14,6 @@ from vunit.sim_if import OptionType from vunit.test.bench_list import TestBenchList -from vunit.ui import VUnit from vunit.ui.preprocessor import Preprocessor from ..vhdl_standard import VHDL, VHDLStandard from ..project import Project @@ -25,13 +24,18 @@ from .testbench import TestBench from .packagefacade import PackageFacade +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from vunit.ui import VUnit + class Library(object): """ User interface of a library """ - def __init__(self, library_name: str, parent: VUnit, project: Project, test_bench_list: TestBenchList) -> None: + def __init__(self, library_name: str, parent: "VUnit", project: Project, test_bench_list: TestBenchList) -> None: self._library_name = library_name self._parent = parent self._project = project diff --git a/vunit/ui/packagefacade.py b/vunit/ui/packagefacade.py index ea1decc96..bc2a7aeae 100644 --- a/vunit/ui/packagefacade.py +++ b/vunit/ui/packagefacade.py @@ -12,9 +12,12 @@ from typing import Optional, Union from vunit.design_unit import DesignUnit -from vunit.ui import VUnit from vunit.ui.source import SourceFileList from ..com import codec_generator +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from vunit.ui import VUnit class PackageFacade(object): @@ -22,7 +25,7 @@ class PackageFacade(object): User interface of a Package """ - def __init__(self, parent: VUnit, library_name: str, package_name: str, design_unit: DesignUnit) -> None: + def __init__(self, parent: "VUnit", library_name: str, package_name: str, design_unit: DesignUnit) -> None: self._parent = parent self._library_name = library_name self._package_name = package_name diff --git a/vunit/ui/results.py b/vunit/ui/results.py index 0570f7a45..d9aca51e1 100644 --- a/vunit/ui/results.py +++ b/vunit/ui/results.py @@ -10,9 +10,11 @@ from pathlib import Path from typing import Any, Dict, Optional, Union +from typing import TYPE_CHECKING -from vunit.sim_if import SimulatorInterface -from vunit.test.report import TestReport +if TYPE_CHECKING: + from vunit.sim_if import SimulatorInterface + from vunit.test.report import TestReport from .common import TEST_OUTPUT_PATH @@ -21,7 +23,7 @@ class Results(object): Gives access to results after running tests """ - def __init__(self, output_path: str, simulator_if: SimulatorInterface, report: TestReport) -> None: + def __init__(self, output_path: str, simulator_if: "SimulatorInterface", report: "TestReport") -> None: self._output_path = output_path self._simulator_if = simulator_if self._report = report diff --git a/vunit/ui/source.py b/vunit/ui/source.py index b2b88984e..228292b48 100644 --- a/vunit/ui/source.py +++ b/vunit/ui/source.py @@ -12,10 +12,13 @@ from vunit.project import Project from vunit.sim_if import OptionType -from vunit.ui import VUnit -from vunit.ui.library import Library from .. import ostools -from vunit.source_file import SourceFile as Source_File, VHDLSourceFile +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from vunit.source_file import SourceFile as Source_File + from vunit.ui import VUnit + from vunit.ui.library import Library class SourceFile(object): @@ -23,7 +26,7 @@ class SourceFile(object): A single file """ - def __init__(self, source_file: Source_File, project: Project, ui: VUnit) -> None: + def __init__(self, source_file: "Source_File", project: Project, ui: "VUnit") -> None: self._source_file = source_file self._project = project self._ui = ui @@ -41,13 +44,16 @@ def vhdl_standard(self) -> Optional[str]: The VHDL standard applicable to the file, None if not a VHDL file """ + # Import here to avoid circular import problems + from vunit.source_file import VHDLSourceFile + if isinstance(self._source_file, VHDLSourceFile): return str(self._source_file.get_vhdl_standard()) return None @property - def library(self) -> Library: + def library(self) -> "Library": """ The library of the source file """ @@ -85,7 +91,7 @@ def get_compile_option(self, name: str) -> OptionType: """ return self._source_file.get_compile_option(name) - def add_dependency_on(self, source_file: Union[Iterable[Source_File], Source_File]) -> None: + def add_dependency_on(self, source_file: Union[Iterable["Source_File"], "Source_File"]) -> None: """ Add manual dependency of this file other file(s) @@ -142,7 +148,7 @@ def add_compile_option(self, name: str, value: OptionType) -> None: for source_file in self: source_file.add_compile_option(name, value) - def add_dependency_on(self, source_file: Source_File) -> None: + def add_dependency_on(self, source_file: "Source_File") -> None: """ Add manual dependency of these files on other file(s) diff --git a/vunit/ui/testbench.py b/vunit/ui/testbench.py index cca617560..343e39d05 100644 --- a/vunit/ui/testbench.py +++ b/vunit/ui/testbench.py @@ -12,10 +12,13 @@ from typing import Any, Callable, Optional, cast from vunit.sim_if import OptionType -from vunit.ui.library import Library from .common import lower_generics from .test import Test from vunit.test.bench import TestBench as Test_Bench +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from vunit.ui.library import Library class TestBench(object): @@ -25,7 +28,7 @@ class TestBench(object): bench will apply that option to all test cases belonging to that test bench. """ - def __init__(self, test_bench: Test_Bench, library: Library) -> None: + def __init__(self, test_bench: Test_Bench, library: "Library") -> None: self._test_bench = test_bench self._library = library @@ -37,7 +40,7 @@ def name(self) -> str: return self._test_bench.name @property - def library(self) -> Library: + def library(self) -> "Library": """ :returns: The library that contains this test bench """ From 12780fb26546c386aedff054143c67a8d98594a4 Mon Sep 17 00:00:00 2001 From: Anton Schulte Date: Thu, 28 Sep 2023 16:35:42 +0200 Subject: [PATCH 3/9] Fix Linter Messages --- vunit/library.py | 5 ++--- vunit/project.py | 4 +++- vunit/sim_if/__init__.py | 2 +- vunit/source_file.py | 2 +- vunit/ui/__init__.py | 3 +-- vunit/ui/common.py | 4 +--- vunit/ui/library.py | 14 +++++--------- vunit/ui/packagefacade.py | 3 +-- vunit/ui/preprocessor.py | 2 +- vunit/ui/results.py | 5 ++--- vunit/ui/source.py | 18 +++++++----------- vunit/ui/test.py | 1 - vunit/ui/testbench.py | 7 +++---- 13 files changed, 28 insertions(+), 42 deletions(-) diff --git a/vunit/library.py b/vunit/library.py index 68e75b40e..192e740e8 100644 --- a/vunit/library.py +++ b/vunit/library.py @@ -11,13 +11,12 @@ """ import logging -from typing import cast +from typing import cast, TYPE_CHECKING from vunit.design_unit import Entity, VHDLDesignUnit -from typing import TYPE_CHECKING +from vunit.vhdl_standard import VHDLStandard if TYPE_CHECKING: from vunit.source_file import SourceFile, VHDLSourceFile, VerilogSourceFile -from vunit.vhdl_standard import VHDLStandard LOGGER = logging.getLogger(__name__) diff --git a/vunit/project.py b/vunit/project.py index 3671094bc..3f8079e25 100644 --- a/vunit/project.py +++ b/vunit/project.py @@ -515,7 +515,9 @@ def _get_files_to_recompile(self, files, dependency_graph, incremental): result_list.append(source_file) return result_list - def get_dependencies_in_compile_order(self, target_files=None, implementation_dependencies=False) -> list[SourceFile]: + def get_dependencies_in_compile_order( + self, target_files=None, implementation_dependencies=False + ) -> list[SourceFile]: """ Get a list of dependencies of target files including the target files. diff --git a/vunit/sim_if/__init__.py b/vunit/sim_if/__init__.py index 2358c8f5f..ee63ed928 100644 --- a/vunit/sim_if/__init__.py +++ b/vunit/sim_if/__init__.py @@ -186,7 +186,7 @@ def supports_coverage(): """ return False - def merge_coverage(self, file_name, args): # pylint: disable=unused-argument + def merge_coverage(self, file_name, args): # pylint: disable=unused-argument,no-self-use """ Hook for simulator interface to creating coverage reports """ diff --git a/vunit/source_file.py b/vunit/source_file.py index 4ee7b11fe..987fbaf86 100644 --- a/vunit/source_file.py +++ b/vunit/source_file.py @@ -120,7 +120,7 @@ def content_hash(self): return hash_string(self._content_hash + self._compile_options_hash()) def add_to_library(self, library: Library): - raise NotImplemented + raise NotImplementedError class VerilogSourceFile(SourceFile): diff --git a/vunit/ui/__init__.py b/vunit/ui/__init__.py index 3599bf072..61357529f 100644 --- a/vunit/ui/__init__.py +++ b/vunit/ui/__init__.py @@ -17,7 +17,7 @@ import logging import json import os -from typing import Any, Callable, Literal, Optional, Set, Union, cast +from typing import Any, Callable, Literal, Optional, Set, Union, cast, TYPE_CHECKING from pathlib import Path from fnmatch import fnmatch from vunit.test.list import TestList @@ -47,7 +47,6 @@ from .library import Library, LibraryList from .results import Results -from typing import TYPE_CHECKING if TYPE_CHECKING: from vunit.source_file import SourceFile as Source_File diff --git a/vunit/ui/common.py b/vunit/ui/common.py index 1f8865620..186cf52da 100644 --- a/vunit/ui/common.py +++ b/vunit/ui/common.py @@ -12,10 +12,8 @@ from glob import glob from os import environ from logging import getLogger -from typing import Any, Iterable, Optional, List, TypeVar, Union +from typing import Iterable, Optional, List, TypeVar, Union -from vunit.ui.source import SourceFile -from ..sim_if import is_string_not_iterable from ..vhdl_standard import VHDL, VHDLStandard LOGGER = getLogger(__name__) diff --git a/vunit/ui/library.py b/vunit/ui/library.py index e355d21ad..af0188fca 100644 --- a/vunit/ui/library.py +++ b/vunit/ui/library.py @@ -11,10 +11,11 @@ from pathlib import Path from fnmatch import fnmatch from typing import Any, List, Literal, Optional, Union -from vunit.sim_if import OptionType +from typing import TYPE_CHECKING -from vunit.test.bench_list import TestBenchList -from vunit.ui.preprocessor import Preprocessor +from ..sim_if import OptionType +from ..test.bench_list import TestBenchList +from .preprocessor import Preprocessor from ..vhdl_standard import VHDL, VHDLStandard from ..project import Project from ..source_file import file_type_of, FILE_TYPES, VERILOG_FILE_TYPES @@ -24,8 +25,6 @@ from .testbench import TestBench from .packagefacade import PackageFacade -from typing import TYPE_CHECKING - if TYPE_CHECKING: from vunit.ui import VUnit @@ -196,7 +195,7 @@ def add_source_files( # pylint: disable=too-many-arguments """ return SourceFileList( - source_files=[ + [ self.add_source_file( file_name, preprocessors, @@ -362,9 +361,6 @@ class LibraryList(List[Library]): A list of :class:`.Library` """ - def __init__(self, libraries: "list[Library]"): - list.__init__(self, libraries) - def get_test_benches(self, pattern: str = "*", allow_empty: bool = False) -> list[TestBench]: """ Get a list of test benches diff --git a/vunit/ui/packagefacade.py b/vunit/ui/packagefacade.py index bc2a7aeae..04fa4d63d 100644 --- a/vunit/ui/packagefacade.py +++ b/vunit/ui/packagefacade.py @@ -9,12 +9,11 @@ """ from pathlib import Path -from typing import Optional, Union +from typing import Optional, Union, TYPE_CHECKING from vunit.design_unit import DesignUnit from vunit.ui.source import SourceFileList from ..com import codec_generator -from typing import TYPE_CHECKING if TYPE_CHECKING: from vunit.ui import VUnit diff --git a/vunit/ui/preprocessor.py b/vunit/ui/preprocessor.py index 0701a8dcb..615a5b160 100644 --- a/vunit/ui/preprocessor.py +++ b/vunit/ui/preprocessor.py @@ -22,7 +22,7 @@ def __init__(self, order: int = 0) -> None: """ self.order = order - def run(self, code: str, file_name: str) -> str: # pylint: disable=unused-argument + def run(self, code: str, file_name: str) -> str: # pylint: disable=unused-argument,no-self-use """ Preprocess code. diff --git a/vunit/ui/results.py b/vunit/ui/results.py index d9aca51e1..a277b02bd 100644 --- a/vunit/ui/results.py +++ b/vunit/ui/results.py @@ -9,13 +9,12 @@ """ from pathlib import Path -from typing import Any, Dict, Optional, Union -from typing import TYPE_CHECKING +from typing import Any, Dict, Optional, Union, TYPE_CHECKING +from .common import TEST_OUTPUT_PATH if TYPE_CHECKING: from vunit.sim_if import SimulatorInterface from vunit.test.report import TestReport -from .common import TEST_OUTPUT_PATH class Results(object): diff --git a/vunit/ui/source.py b/vunit/ui/source.py index 228292b48..468d051e9 100644 --- a/vunit/ui/source.py +++ b/vunit/ui/source.py @@ -8,17 +8,16 @@ UI classes SourceFile and SourceFileList """ -from typing import Iterable, List, Optional, Union +from typing import Iterable, List, Optional, Union, TYPE_CHECKING -from vunit.project import Project -from vunit.sim_if import OptionType +from ..project import Project +from ..sim_if import OptionType from .. import ostools -from typing import TYPE_CHECKING if TYPE_CHECKING: - from vunit.source_file import SourceFile as Source_File - from vunit.ui import VUnit - from vunit.ui.library import Library + from ..source_file import SourceFile as Source_File + from . import VUnit + from .library import Library class SourceFile(object): @@ -45,7 +44,7 @@ def vhdl_standard(self) -> Optional[str]: None if not a VHDL file """ # Import here to avoid circular import problems - from vunit.source_file import VHDLSourceFile + from vunit.source_file import VHDLSourceFile # pylint: disable=import-outside-toplevel if isinstance(self._source_file, VHDLSourceFile): return str(self._source_file.get_vhdl_standard()) @@ -119,9 +118,6 @@ class SourceFileList(List[SourceFile]): A list of :class:`.SourceFile` """ - def __init__(self, source_files: Iterable[SourceFile]): - list.__init__(self, source_files) - def set_compile_option(self, name: str, value: OptionType) -> None: """ Set compile option for all files in the list diff --git a/vunit/ui/test.py b/vunit/ui/test.py index 635d30c31..86b952c6c 100644 --- a/vunit/ui/test.py +++ b/vunit/ui/test.py @@ -11,7 +11,6 @@ from typing import Any, Callable, Optional, cast from vunit.sim_if import OptionType from vunit.test.bench import TestConfigurationVisitor -from vunit.ui.results import Results from .common import lower_generics diff --git a/vunit/ui/testbench.py b/vunit/ui/testbench.py index 343e39d05..2f331c18f 100644 --- a/vunit/ui/testbench.py +++ b/vunit/ui/testbench.py @@ -9,13 +9,12 @@ """ from fnmatch import fnmatch -from typing import Any, Callable, Optional, cast +from typing import Any, Callable, Optional, cast, TYPE_CHECKING -from vunit.sim_if import OptionType +from ..sim_if import OptionType +from ..test.bench import TestBench as Test_Bench from .common import lower_generics from .test import Test -from vunit.test.bench import TestBench as Test_Bench -from typing import TYPE_CHECKING if TYPE_CHECKING: from vunit.ui.library import Library From 3185146cee4059771ddfcfc5aac31de621b7864a Mon Sep 17 00:00:00 2001 From: Anton Schulte Date: Fri, 29 Sep 2023 11:47:23 +0200 Subject: [PATCH 4/9] Fixed for python 3.7 --- tests/common.py | 2 +- vunit/com/codec_vhdl_package.py | 4 ++-- vunit/configuration.py | 8 ++++---- vunit/library.py | 4 ++-- vunit/project.py | 9 ++++----- vunit/sim_if/__init__.py | 2 +- vunit/sim_if/factory.py | 10 ++++----- vunit/source_file.py | 6 +++--- vunit/test/bench.py | 7 +++---- vunit/test/bench_list.py | 6 +++--- vunit/ui/__init__.py | 36 ++++++++++++++++----------------- vunit/ui/common.py | 8 ++++---- vunit/ui/library.py | 18 ++++++++--------- vunit/ui/packagefacade.py | 4 ++-- vunit/ui/results.py | 4 ++-- vunit/ui/test.py | 4 ++-- vunit/ui/testbench.py | 12 +++++------ 17 files changed, 71 insertions(+), 73 deletions(-) diff --git a/tests/common.py b/tests/common.py index a6b35df36..e092e2386 100644 --- a/tests/common.py +++ b/tests/common.py @@ -72,7 +72,7 @@ def set_env(**environ): >>> "PLUGINS_DIR" in os.environ False - :type environ: dict[str, unicode] + :type environ: Dict[str, unicode] :param environ: Environment variables to set """ old_environ = dict(os.environ) diff --git a/vunit/com/codec_vhdl_package.py b/vunit/com/codec_vhdl_package.py index dd6d0c8b3..7299993e9 100644 --- a/vunit/com/codec_vhdl_package.py +++ b/vunit/com/codec_vhdl_package.py @@ -148,7 +148,7 @@ def _create_enumeration_of_all_msg_types(self): msg_type_enumeration_types = [] for record in self.record_types: - if record.elements[0].identifier_list[0] == "msg_type": + if record.elements[0].identifier_List[0] == "msg_type": msg_type_enumeration_types.append(record.elements[0].subtype_indication.code) msg_type_enumeration_literals = [] @@ -276,7 +276,7 @@ def _get_records_with_an_initial_msg_type_element(self): msg_type_record_types = [] for record in self.record_types: - if record.elements[0].identifier_list[0] == "msg_type": + if record.elements[0].identifier_List[0] == "msg_type": msg_type_record_types.append(record) return msg_type_record_types diff --git a/vunit/configuration.py b/vunit/configuration.py index 473024883..a300511ef 100644 --- a/vunit/configuration.py +++ b/vunit/configuration.py @@ -12,7 +12,7 @@ import inspect from pathlib import Path from copy import copy -from typing import Any, Callable, OrderedDict, Union +from typing import Any, Callable, List, OrderedDict, Union from vunit.sim_if.factory import SIMULATOR_FACTORY @@ -129,7 +129,7 @@ def set_generic(self, name: str, value: Any) -> None: else: self.generics[name] = value - def set_sim_option(self, name: str, value: Union[str, list[str], bool]): + def set_sim_option(self, name: str, value: Union[str, List[str], bool]): """ Set sim option """ @@ -196,7 +196,7 @@ class ConfigurationVisitor(object): def _check_enabled(self): pass - def get_configuration_dicts(self) -> list[OrderedDict[Any, Configuration]]: + def get_configuration_dicts(self) -> List[OrderedDict[Any, Configuration]]: raise NotImplementedError def set_attribute(self, name: str, value: Any): @@ -226,7 +226,7 @@ def set_vhdl_configuration_name(self, value: str): for config in configs.values(): config.set_vhdl_configuration_name(value) - def set_sim_option(self, name: str, value: Union[str, list[str], bool], overwrite=True) -> None: + def set_sim_option(self, name: str, value: Union[str, List[str], bool], overwrite=True) -> None: """ Set sim option diff --git a/vunit/library.py b/vunit/library.py index 192e740e8..86cee4f75 100644 --- a/vunit/library.py +++ b/vunit/library.py @@ -11,7 +11,7 @@ """ import logging -from typing import cast, TYPE_CHECKING +from typing import List, cast, TYPE_CHECKING from vunit.design_unit import Entity, VHDLDesignUnit from vunit.vhdl_standard import VHDLStandard @@ -109,7 +109,7 @@ def _check_duplication(self, dictionary, design_unit): if design_unit.name in dictionary: self._warning_on_duplication(design_unit, dictionary[design_unit.name].source_file.name) - def add_vhdl_design_units(self, design_units: list[VHDLDesignUnit]): + def add_vhdl_design_units(self, design_units: List[VHDLDesignUnit]): """ Add VHDL design units to the library """ diff --git a/vunit/project.py b/vunit/project.py index 3f8079e25..4a1c0e85a 100644 --- a/vunit/project.py +++ b/vunit/project.py @@ -9,10 +9,9 @@ """ Functionality to represent and operate on a HDL code project """ -from typing import Optional, Union +from typing import List, Optional, Union, OrderedDict from pathlib import Path import logging -from collections import OrderedDict from vunit.hashing import hash_string from vunit.dependency_graph import DependencyGraph, CircularDependencyException from vunit.vhdl_parser import VHDLParser @@ -48,7 +47,7 @@ def __init__(self, depend_on_package_body=False, database=None): self._libraries: OrderedDict[str, Library] = OrderedDict() # Mapping between library lower case name and real library name self._lower_library_names_dict = {} - self._source_files_in_order: list[SourceFile] = [] + self._source_files_in_order: List[SourceFile] = [] self._manual_dependencies = [] self._depend_on_package_body = depend_on_package_body self._builtin_libraries = set(["ieee", "std"]) @@ -517,7 +516,7 @@ def _get_files_to_recompile(self, files, dependency_graph, incremental): def get_dependencies_in_compile_order( self, target_files=None, implementation_dependencies=False - ) -> list[SourceFile]: + ) -> List[SourceFile]: """ Get a list of dependencies of target files including the target files. @@ -593,7 +592,7 @@ def comparison_key(source_file): return sorted(files, key=comparison_key) - def get_source_files_in_order(self) -> list[SourceFile]: + def get_source_files_in_order(self) -> List[SourceFile]: """ Get a list of source files in the order they were added to the project """ diff --git a/vunit/sim_if/__init__.py b/vunit/sim_if/__init__.py index ee63ed928..4b518591e 100644 --- a/vunit/sim_if/__init__.py +++ b/vunit/sim_if/__init__.py @@ -18,7 +18,7 @@ from ..exceptions import CompileError from ..color_printer import NO_COLOR_PRINTER -OptionType = Union[str, list[str], bool] +OptionType = Union[str, List[str], bool] class Option(object): diff --git a/vunit/sim_if/factory.py b/vunit/sim_if/factory.py index b9b49cace..8d30db279 100644 --- a/vunit/sim_if/factory.py +++ b/vunit/sim_if/factory.py @@ -9,7 +9,7 @@ """ import os -from typing import Union +from typing import Dict, List, Union from .activehdl import ActiveHDLInterface from .ghdl import GHDLInterface from .incisive import IncisiveInterface @@ -38,7 +38,7 @@ def supported_simulators(): NVCInterface, ] - def _extract_compile_options(self) -> dict[str, Option]: + def _extract_compile_options(self) -> Dict[str, Option]: """ Return all supported compile options """ @@ -52,7 +52,7 @@ def _extract_compile_options(self) -> dict[str, Option]: result[opt.name] = opt return result - def _extract_sim_options(self) -> dict[str, Option]: + def _extract_sim_options(self) -> Dict[str, Option]: """ Return all supported sim options """ @@ -76,7 +76,7 @@ def _extract_sim_options(self) -> dict[str, Option]: return result - def check_sim_option(self, name: str, value: Union[str, list[str], bool]): + def check_sim_option(self, name: str, value: Union[str, List[str], bool]): """ Check that sim_option has legal name and value """ @@ -95,7 +95,7 @@ def check_compile_option_name(self, name): if name not in known_options: raise ValueError(f"Unknown compile_option {name!r}, expected one of {known_options!r}") - def check_compile_option(self, name: str, value: Union[str, list[str], bool]) -> None: + def check_compile_option(self, name: str, value: Union[str, List[str], bool]) -> None: """ Check that the compile option is valid """ diff --git a/vunit/source_file.py b/vunit/source_file.py index 987fbaf86..dedd94400 100644 --- a/vunit/source_file.py +++ b/vunit/source_file.py @@ -8,7 +8,7 @@ Functionality to represent and operate on VHDL and Verilog source files """ from pathlib import Path -from typing import Literal, Union +from typing import Dict, Union import logging from copy import copy import traceback @@ -36,7 +36,7 @@ def __init__(self, name, library, file_type): self.file_type = file_type self.design_units = [] self._content_hash = None - self._compile_options: dict[str, OptionType] = {} + self._compile_options: Dict[str, OptionType] = {} # The file name before preprocessing self.original_name = name @@ -351,7 +351,7 @@ def add_to_library(self, library): FILE_TYPES = ("vhdl",) + VERILOG_FILE_TYPES -def file_type_of(file_name: Union[str, Path]) -> Literal["vhdl", "verilog", "systemverilog"]: +def file_type_of(file_name: Union[str, Path]) -> str: """ Return the file type of file_name based on the file ending """ diff --git a/vunit/test/bench.py b/vunit/test/bench.py index 3e03c2f32..ba07a5118 100644 --- a/vunit/test/bench.py +++ b/vunit/test/bench.py @@ -13,8 +13,7 @@ import re import bisect import collections -from collections import OrderedDict -from typing import Any, Iterable, Union +from typing import Any, Iterable, List, Union, OrderedDict from ..ostools import file_exists from ..cached import cached from ..vhdl_parser import remove_comments as remove_vhdl_comments @@ -143,7 +142,7 @@ def get_test_case(self, name): return test_case raise KeyError(name) - def get_configuration_dicts(self) -> list[OrderedDict[str, Configuration]]: # pylint: disable=arguments-differ + def get_configuration_dicts(self) -> "List[OrderedDict[str, Configuration]]": # pylint: disable=arguments-differ """ Get all configurations within the test bench @@ -359,7 +358,7 @@ def _check_enabled(self): if not self._enable_configuration: raise RuntimeError("Individual test configuration is not possible with run_all_in_same_sim") - def get_configuration_dicts(self) -> list[OrderedDict[Any, Configuration]]: # pylint: disable=arguments-differ + def get_configuration_dicts(self) -> List[OrderedDict[Any, Configuration]]: # pylint: disable=arguments-differ """ Get all configurations of this test """ diff --git a/vunit/test/bench_list.py b/vunit/test/bench_list.py index a1f91ee13..b8447b4a8 100644 --- a/vunit/test/bench_list.py +++ b/vunit/test/bench_list.py @@ -10,7 +10,7 @@ import re import logging -from collections import OrderedDict +from typing import List, OrderedDict from vunit.source_file import SourceFile from .list import TestList @@ -49,10 +49,10 @@ def _add_test_bench(self, test_bench: TestBench) -> None: def get_test_bench(self, library_name, name) -> TestBench: return self._libraries[library_name][name] - def get_test_benches_in_library(self, library_name: str) -> list[TestBench]: + def get_test_benches_in_library(self, library_name: str) -> List[TestBench]: return list(self._libraries.get(library_name, {}).values()) - def get_test_benches(self) -> list[TestBench]: + def get_test_benches(self) -> List[TestBench]: """ Get all test benches """ diff --git a/vunit/ui/__init__.py b/vunit/ui/__init__.py index 61357529f..05c1527d8 100644 --- a/vunit/ui/__init__.py +++ b/vunit/ui/__init__.py @@ -17,7 +17,7 @@ import logging import json import os -from typing import Any, Callable, Literal, Optional, Set, Union, cast, TYPE_CHECKING +from typing import Any, Callable, Dict, List, Optional, Set, Union, cast, TYPE_CHECKING from pathlib import Path from fnmatch import fnmatch from vunit.test.list import TestList @@ -332,7 +332,7 @@ def get_libraries( :param allow_empty: To disable an error if no labraries matched the pattern :returns: A :class:`.LibraryList` object """ - results: list[Library] = [] + results: List[Library] = [] for library in self._project.get_libraries(): if not fnmatch(library.name, pattern): @@ -534,13 +534,13 @@ def add_source_files( # pylint: disable=too-many-arguments self, pattern: Union[str, Path], library_name: str, - preprocessors: Optional[list[Preprocessor]] = None, + preprocessors: Optional[List[Preprocessor]] = None, include_dirs: Optional[list] = None, defines: Optional[dict] = None, allow_empty: bool = False, vhdl_standard: Optional[str] = None, no_parse: bool = False, - file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + file_type: Optional[str] = None, ) -> SourceFileList: """ Add source files matching wildcard pattern to library @@ -579,12 +579,12 @@ def add_source_file( # pylint: disable=too-many-arguments self, file_name: Union[str, Path], library_name: str, - preprocessors: Optional[list[Preprocessor]] = None, - include_dirs: Optional[list[Any]] = None, + preprocessors: Optional[List[Preprocessor]] = None, + include_dirs: Optional[List[Any]] = None, defines: Optional[dict] = None, vhdl_standard: Optional[str] = None, no_parse: bool = False, - file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + file_type: Optional[str] = None, ) -> SourceFile: """ Add source file to library @@ -618,7 +618,7 @@ def add_source_file( # pylint: disable=too-many-arguments ) def _preprocess( - self, library_name: str, file_name: Union[str, Path], preprocessors: Optional[list[Preprocessor]] + self, library_name: str, file_name: Union[str, Path], preprocessors: Optional[List[Preprocessor]] ) -> str: """ Preprocess file_name within library_name using explicit preprocessors @@ -672,8 +672,8 @@ def add_preprocessor(self, preprocessor: Preprocessor) -> None: def enable_location_preprocessing( self, - additional_subprograms: Optional[list[str]] = None, - exclude_subprograms: Optional[list[str]] = None, + additional_subprograms: Optional[List[str]] = None, + exclude_subprograms: Optional[List[str]] = None, order: int = 100, ) -> None: """ @@ -823,7 +823,7 @@ def _main_run(self, post_run: Optional[Callable[[Results], None]]) -> bool: return report.all_ok() - def _main_list_only(self) -> Literal[True]: + def _main_list_only(self) -> bool: """ Main function when only listing test cases """ @@ -833,7 +833,7 @@ def _main_list_only(self) -> Literal[True]: print(f"Listed {test_list.num_tests} tests") return True - def _main_export_json(self, json_file_name: Union[str, Path]) -> Literal[True]: # pylint: disable=too-many-locals + def _main_export_json(self, json_file_name: Union[str, Path]) -> bool: # pylint: disable=too-many-locals """ Main function when exporting to JSON """ @@ -888,7 +888,7 @@ def _main_export_json(self, json_file_name: Union[str, Path]) -> Literal[True]: return True - def _main_list_files_only(self) -> Literal[True]: + def _main_list_files_only(self) -> bool: """ Main function when only listing files """ @@ -898,7 +898,7 @@ def _main_list_files_only(self) -> Literal[True]: print(f"Listed {len(files)} files") return True - def _main_compile_only(self) -> Literal[True]: + def _main_compile_only(self) -> bool: """ Main function when only compiling """ @@ -946,7 +946,7 @@ def _compile(self, simulator_if: SimulatorInterface) -> None: target_files=target_files, ) - def _get_testbench_files(self, simulator_if: Union[None, SimulatorInterface]) -> list["Source_File"]: + def _get_testbench_files(self, simulator_if: Union[None, SimulatorInterface]) -> List["Source_File"]: """ Return the list of all test bench files for the currently selected tests to run """ @@ -992,7 +992,7 @@ def add_verilog_builtins(self) -> None: self._builtins.add_verilog_builtins() def add_vhdl_builtins( - self, external: Optional[dict[str, list[str]]] = None, use_external_log: Optional[Union[str, Path]] = None + self, external: Optional[Dict[str, List[str]]] = None, use_external_log: Optional[Union[str, Path]] = None ) -> None: """ Add VUnit VHDL builtin libraries. @@ -1053,7 +1053,7 @@ def add_json4vhdl(self) -> None: """ self._builtins.add("json4vhdl") - def get_compile_order(self, source_files: Optional[list[SourceFile]] = None) -> SourceFileList: + def get_compile_order(self, source_files: Optional[List[SourceFile]] = None) -> SourceFileList: """ Get the compile order of all or specific source files and their dependencies. @@ -1077,7 +1077,7 @@ def get_compile_order(self, source_files: Optional[list[SourceFile]] = None) -> source_files_ordered = self._project.get_dependencies_in_compile_order(target_files) return SourceFileList([SourceFile(source_file, self._project, self) for source_file in source_files_ordered]) - def get_implementation_subset(self, source_files: list[SourceFile]) -> SourceFileList: + def get_implementation_subset(self, source_files: List[SourceFile]) -> SourceFileList: """ Get the subset of files which are required to successfully elaborate the list of input files without any missing diff --git a/vunit/ui/common.py b/vunit/ui/common.py index 186cf52da..081141da2 100644 --- a/vunit/ui/common.py +++ b/vunit/ui/common.py @@ -12,7 +12,7 @@ from glob import glob from os import environ from logging import getLogger -from typing import Iterable, Optional, List, TypeVar, Union +from typing import Dict, Iterable, Optional, List, TypeVar, Union from ..vhdl_standard import VHDL, VHDLStandard @@ -38,7 +38,7 @@ def select_vhdl_standard(vhdl_standard: Optional[str] = None) -> VHDLStandard: T = TypeVar("T") -def lower_generics(generics: dict[str, T]) -> dict[str, T]: +def lower_generics(generics: Dict[str, T]) -> Dict[str, T]: """ Convert all generics names to lower case to match internal representation. @TODO Maybe warn in case of conflict. VHDL forbids this though so the user will notice anyway. @@ -46,7 +46,7 @@ def lower_generics(generics: dict[str, T]) -> dict[str, T]: return dict((name.lower(), value) for name, value in generics.items()) -def check_not_empty(lst: list[T], allow_empty: bool, error_msg: str) -> list[T]: +def check_not_empty(lst: List[T], allow_empty: bool, error_msg: str) -> List[T]: """ Raise ValueError if the list is empty unless allow_empty is True Returns the list @@ -56,7 +56,7 @@ def check_not_empty(lst: list[T], allow_empty: bool, error_msg: str) -> list[T]: return lst -def get_checked_file_names_from_globs(pattern: Union[Iterable[str], str, Path], allow_empty: bool) -> list[str]: +def get_checked_file_names_from_globs(pattern: Union[Iterable[str], str, Path], allow_empty: bool) -> List[str]: """ Get file names from globs and check that exist """ diff --git a/vunit/ui/library.py b/vunit/ui/library.py index af0188fca..64ed7c35a 100644 --- a/vunit/ui/library.py +++ b/vunit/ui/library.py @@ -10,7 +10,7 @@ from pathlib import Path from fnmatch import fnmatch -from typing import Any, List, Literal, Optional, Union +from typing import Any, List, Optional, Union from typing import TYPE_CHECKING from ..sim_if import OptionType @@ -166,13 +166,13 @@ def get_source_files(self, pattern: str = "*", allow_empty: bool = False) -> Sou def add_source_files( # pylint: disable=too-many-arguments self, pattern: Union[str, Path], - preprocessors: Optional[list[Preprocessor]] = None, - include_dirs: Optional[list[str]] = None, + preprocessors: Optional[List[Preprocessor]] = None, + include_dirs: Optional[List[str]] = None, defines: Optional[dict] = None, allow_empty: bool = False, vhdl_standard: Optional[str] = None, no_parse: bool = False, - file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + file_type: Optional[str] = None, ) -> SourceFileList: """ Add source files matching wildcard pattern to library @@ -212,12 +212,12 @@ def add_source_files( # pylint: disable=too-many-arguments def add_source_file( # pylint: disable=too-many-arguments self, file_name: Union[str, Path], - preprocessors: Optional[list[Preprocessor]] = None, - include_dirs: Optional[list[str]] = None, + preprocessors: Optional[List[Preprocessor]] = None, + include_dirs: Optional[List[str]] = None, defines: Optional[dict] = None, vhdl_standard: Optional[str] = None, no_parse: bool = False, - file_type: Optional[Literal["vhdl", "verilog", "systemverilog"]] = None, + file_type: Optional[str] = None, ) -> SourceFile: """ Add source file to library @@ -324,7 +324,7 @@ def test_bench(self, name: str) -> TestBench: return TestBench(self._test_bench_list.get_test_bench(self._library_name, name), self) - def get_test_benches(self, pattern: str = "*", allow_empty: bool = False) -> list[TestBench]: + def get_test_benches(self, pattern: str = "*", allow_empty: bool = False) -> List[TestBench]: """ Get a list of test benches @@ -361,7 +361,7 @@ class LibraryList(List[Library]): A list of :class:`.Library` """ - def get_test_benches(self, pattern: str = "*", allow_empty: bool = False) -> list[TestBench]: + def get_test_benches(self, pattern: str = "*", allow_empty: bool = False) -> List[TestBench]: """ Get a list of test benches diff --git a/vunit/ui/packagefacade.py b/vunit/ui/packagefacade.py index 04fa4d63d..afa71ca67 100644 --- a/vunit/ui/packagefacade.py +++ b/vunit/ui/packagefacade.py @@ -9,7 +9,7 @@ """ from pathlib import Path -from typing import Optional, Union, TYPE_CHECKING +from typing import List, Optional, Union, TYPE_CHECKING from vunit.design_unit import DesignUnit from vunit.ui.source import SourceFileList @@ -33,7 +33,7 @@ def __init__(self, parent: "VUnit", library_name: str, package_name: str, design def generate_codecs( self, codec_package_name: Optional[str] = None, - used_packages: Optional[list[str]] = None, + used_packages: Optional[List[str]] = None, output_file_name: Optional[Union[str, Path]] = None, ) -> SourceFileList: """ diff --git a/vunit/ui/results.py b/vunit/ui/results.py index a277b02bd..528b58c1a 100644 --- a/vunit/ui/results.py +++ b/vunit/ui/results.py @@ -9,7 +9,7 @@ """ from pathlib import Path -from typing import Any, Dict, Optional, Union, TYPE_CHECKING +from typing import Any, Dict, List, Optional, Union, TYPE_CHECKING from .common import TEST_OUTPUT_PATH if TYPE_CHECKING: @@ -27,7 +27,7 @@ def __init__(self, output_path: str, simulator_if: "SimulatorInterface", report: self._simulator_if = simulator_if self._report = report - def merge_coverage(self, file_name: str, args: Optional[list[str]] = None) -> None: + def merge_coverage(self, file_name: str, args: Optional[List[str]] = None) -> None: """ Create a merged coverage report from the individual coverage files diff --git a/vunit/ui/test.py b/vunit/ui/test.py index 86b952c6c..d8e8045c3 100644 --- a/vunit/ui/test.py +++ b/vunit/ui/test.py @@ -8,7 +8,7 @@ UI class Test """ -from typing import Any, Callable, Optional, cast +from typing import Any, Callable, Dict, Optional, cast from vunit.sim_if import OptionType from vunit.test.bench import TestConfigurationVisitor from .common import lower_generics @@ -37,7 +37,7 @@ def add_config( # pylint: disable=too-many-arguments parameters: Optional[dict] = None, pre_config: Optional[Callable] = None, post_check: Optional[Callable] = None, - sim_options: Optional[dict[str, OptionType]] = None, + sim_options: Optional[Dict[str, OptionType]] = None, attributes: Optional[dict] = None, vhdl_configuration_name: Optional[str] = None, ) -> None: diff --git a/vunit/ui/testbench.py b/vunit/ui/testbench.py index 2f331c18f..e0d18260a 100644 --- a/vunit/ui/testbench.py +++ b/vunit/ui/testbench.py @@ -9,7 +9,7 @@ """ from fnmatch import fnmatch -from typing import Any, Callable, Optional, cast, TYPE_CHECKING +from typing import Any, Callable, Dict, List, Optional, cast, TYPE_CHECKING from ..sim_if import OptionType from ..test.bench import TestBench as Test_Bench @@ -140,12 +140,12 @@ def set_post_check(self, value: Callable) -> None: def add_config( # pylint: disable=too-many-arguments self, name: str, - generics: Optional[dict[str, Any]] = None, - parameters: Optional[dict[str, Any]] = None, + generics: Optional[Dict[str, Any]] = None, + parameters: Optional[Dict[str, Any]] = None, pre_config: Optional[Callable] = None, post_check: Optional[Callable] = None, - sim_options: Optional[dict[str, OptionType]] = None, - attributes: Optional[dict[str, Any]] = None, + sim_options: Optional[Dict[str, OptionType]] = None, + attributes: Optional[Dict[str, Any]] = None, vhdl_configuration_name: Optional[str] = None, ) -> None: """ @@ -211,7 +211,7 @@ def test(self, name: str) -> Test: """ return Test(self._test_bench.get_test_case(name)) - def get_tests(self, pattern: str = "*") -> list[Test]: + def get_tests(self, pattern: str = "*") -> List[Test]: """ Get a list of tests From 73cea63be1296876139ec39ce48577a2bd23aa13 Mon Sep 17 00:00:00 2001 From: Anton Schulte Date: Fri, 29 Sep 2023 13:13:54 +0200 Subject: [PATCH 5/9] make vunit argv annotion more clear --- vunit/ui/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vunit/ui/__init__.py b/vunit/ui/__init__.py index 05c1527d8..f7e6500cd 100644 --- a/vunit/ui/__init__.py +++ b/vunit/ui/__init__.py @@ -10,6 +10,7 @@ Public VUnit User Interface (UI) """ +from __future__ import annotations from argparse import Namespace import csv import sys @@ -68,7 +69,7 @@ def from_argv( cls, argv: Optional[Namespace] = None, vhdl_standard: Optional[str] = None, - ) -> "VUnit": + ) -> VUnit: """ Create VUnit instance from command line arguments. From 26daca04cb315aa822ca9dff307b53c85025589c Mon Sep 17 00:00:00 2001 From: anton schulte Date: Sun, 8 Oct 2023 09:58:03 +0200 Subject: [PATCH 6/9] address PR --- vunit/com/codec_vhdl_package.py | 4 ++-- vunit/configuration.py | 3 ++- vunit/project.py | 3 ++- vunit/test/bench.py | 3 ++- vunit/test/bench_list.py | 3 ++- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/vunit/com/codec_vhdl_package.py b/vunit/com/codec_vhdl_package.py index 7299993e9..dd6d0c8b3 100644 --- a/vunit/com/codec_vhdl_package.py +++ b/vunit/com/codec_vhdl_package.py @@ -148,7 +148,7 @@ def _create_enumeration_of_all_msg_types(self): msg_type_enumeration_types = [] for record in self.record_types: - if record.elements[0].identifier_List[0] == "msg_type": + if record.elements[0].identifier_list[0] == "msg_type": msg_type_enumeration_types.append(record.elements[0].subtype_indication.code) msg_type_enumeration_literals = [] @@ -276,7 +276,7 @@ def _get_records_with_an_initial_msg_type_element(self): msg_type_record_types = [] for record in self.record_types: - if record.elements[0].identifier_List[0] == "msg_type": + if record.elements[0].identifier_list[0] == "msg_type": msg_type_record_types.append(record) return msg_type_record_types diff --git a/vunit/configuration.py b/vunit/configuration.py index a300511ef..630c2a202 100644 --- a/vunit/configuration.py +++ b/vunit/configuration.py @@ -12,7 +12,8 @@ import inspect from pathlib import Path from copy import copy -from typing import Any, Callable, List, OrderedDict, Union +from collections import OrderedDict +from typing import Any, Callable, List, Union from vunit.sim_if.factory import SIMULATOR_FACTORY diff --git a/vunit/project.py b/vunit/project.py index 4a1c0e85a..645e18280 100644 --- a/vunit/project.py +++ b/vunit/project.py @@ -9,7 +9,8 @@ """ Functionality to represent and operate on a HDL code project """ -from typing import List, Optional, Union, OrderedDict +from collections import OrderedDict +from typing import List, Optional, Union from pathlib import Path import logging from vunit.hashing import hash_string diff --git a/vunit/test/bench.py b/vunit/test/bench.py index ba07a5118..a79148355 100644 --- a/vunit/test/bench.py +++ b/vunit/test/bench.py @@ -13,7 +13,8 @@ import re import bisect import collections -from typing import Any, Iterable, List, Union, OrderedDict +from collections import OrderedDict +from typing import Any, Iterable, List, Union from ..ostools import file_exists from ..cached import cached from ..vhdl_parser import remove_comments as remove_vhdl_comments diff --git a/vunit/test/bench_list.py b/vunit/test/bench_list.py index b8447b4a8..c127d7c7f 100644 --- a/vunit/test/bench_list.py +++ b/vunit/test/bench_list.py @@ -10,7 +10,8 @@ import re import logging -from typing import List, OrderedDict +from typing import List +from collections import OrderedDict from vunit.source_file import SourceFile from .list import TestList From 3ad46772000ae8990109c179a36b69cb81cfe515 Mon Sep 17 00:00:00 2001 From: anton schulte Date: Sun, 8 Oct 2023 12:03:13 +0200 Subject: [PATCH 7/9] formatting --- vunit/ui/packagefacade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vunit/ui/packagefacade.py b/vunit/ui/packagefacade.py index afa71ca67..0bc4e7960 100644 --- a/vunit/ui/packagefacade.py +++ b/vunit/ui/packagefacade.py @@ -10,8 +10,8 @@ from pathlib import Path from typing import List, Optional, Union, TYPE_CHECKING -from vunit.design_unit import DesignUnit +from vunit.design_unit import DesignUnit from vunit.ui.source import SourceFileList from ..com import codec_generator From 6ec252625fcaae40862891ac9f7ffc7d097e785c Mon Sep 17 00:00:00 2001 From: Anton Schulte Date: Wed, 13 Mar 2024 13:38:36 +0100 Subject: [PATCH 8/9] address PR --- mypy.ini | 3 --- pyproject.toml | 3 +++ vunit/configuration.py | 2 +- vunit/sim_if/__init__.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 mypy.ini diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index d9aa13bf2..000000000 --- a/mypy.ini +++ /dev/null @@ -1,3 +0,0 @@ -[mypy] -[mypy-vunit.ui.*] -disallow_untyped_defs = True \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 08cf64b25..09112f8dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,3 +97,6 @@ commands= vcomponents: {envpython} vunit/vhdl/verification_components/run.py --clean coverage: {envpython} -m coverage run --branch --source vunit/ -m pytest tests/ """ +[[tool.mypy.overrides]] +module = "vunit.ui.*" +disallow_untyped_defs = true \ No newline at end of file diff --git a/vunit/configuration.py b/vunit/configuration.py index 630c2a202..43a684d45 100644 --- a/vunit/configuration.py +++ b/vunit/configuration.py @@ -197,7 +197,7 @@ class ConfigurationVisitor(object): def _check_enabled(self): pass - def get_configuration_dicts(self) -> List[OrderedDict[Any, Configuration]]: + def get_configuration_dicts(self) -> "List[OrderedDict[Any, Configuration]]": raise NotImplementedError def set_attribute(self, name: str, value: Any): diff --git a/vunit/sim_if/__init__.py b/vunit/sim_if/__init__.py index 4b518591e..84955408c 100644 --- a/vunit/sim_if/__init__.py +++ b/vunit/sim_if/__init__.py @@ -186,7 +186,7 @@ def supports_coverage(): """ return False - def merge_coverage(self, file_name, args): # pylint: disable=unused-argument,no-self-use + def merge_coverage(self, file_name, args): """ Hook for simulator interface to creating coverage reports """ From 4a9fa323ac3d8b905d2d272b398b04c1e13ef2bc Mon Sep 17 00:00:00 2001 From: Anton Schulte Date: Wed, 13 Mar 2024 13:40:29 +0100 Subject: [PATCH 9/9] add newsfragment --- docs/news.d/961.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/news.d/961.feature.rst diff --git a/docs/news.d/961.feature.rst b/docs/news.d/961.feature.rst new file mode 100644 index 000000000..d3b2e886e --- /dev/null +++ b/docs/news.d/961.feature.rst @@ -0,0 +1 @@ +Added python typing for the vunit python API. \ No newline at end of file