Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type hints to 'parsing/' package #939

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ passenv=ALDEC_LICENSE_FILE

deps=
fmt: black
typing-extensions
pytest
lint: pycodestyle
lint: pylint
Expand Down
44 changes: 44 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[metadata]
name = vunit_hdl
version = attr: vunit.about.version
author = Lars Asplund
author_email = [email protected]
license = Mozilla Public License 2.0 (MPL 2.0)
description = VUnit is an open source unit testing framework for VHDL/SystemVerilog.
long_description = attr: vunit.about.doc
url = https://github.com/VUnit/vunit
classifiers =
Development Status :: 5 - Production/Stable
License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
Natural Language :: English
Intended Audience :: Developers
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Operating System :: Microsoft :: Windows
Operating System :: MacOS :: MacOS X
Operating System :: POSIX :: Linux
Topic :: Software Development :: Testing
Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)

[options]
zip_safe = False
include_package_data = True
python_requires = >=3.7
packages =
tests
tests.lint
tests.unit
tests.acceptance
vunit
vunit.com
vunit.parsing
vunit.parsing.verilog
vunit.sim_if
vunit.test
vunit.ui
vunit.vivado
install_requires =
colorama
typing-extensions
60 changes: 13 additions & 47 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,29 @@

import os
import sys
from pathlib import Path
from glob import glob
from logging import warning
from pathlib import Path
from typing import List, Optional

from setuptools import setup

# Ensure that the source tree is on the sys path
sys.path.insert(0, str(Path(__file__).parent.resolve()))

from vunit.about import version, doc # pylint: disable=wrong-import-position
from vunit.builtins import osvvm_is_installed # pylint: disable=wrong-import-position

def osvvm_is_installed() -> bool:
"""
Checks if OSVVM is installed within the VUnit directory structure
"""
return len(glob(str(Path(__file__) / "vunit" / "vhdl" / "osvvm" / "*.vhd"))) != 0


def find_all_files(directory, endings=None):
def find_all_files(directory: str, endings: Optional[List[str]] = None) -> List[str]:
"""
Recursively find all files within directory
"""
result = []
result: List[str] = []
for root, _, filenames in os.walk(directory):
for filename in filenames:
ending = os.path.splitext(filename)[-1]
Expand All @@ -34,55 +41,14 @@ def find_all_files(directory, endings=None):
return result


DATA_FILES = []
DATA_FILES: List[str] = []
DATA_FILES += find_all_files("vunit", endings=[".tcl"])
DATA_FILES += find_all_files(str(Path("vunit") / "vhdl"))
DATA_FILES += find_all_files(str(Path("vunit") / "verilog"), endings=[".v", ".sv", ".svh"])
DATA_FILES = [os.path.relpath(file_name, "vunit") for file_name in DATA_FILES]

setup(
name="vunit_hdl",
version=version(),
packages=[
"tests",
"tests.lint",
"tests.unit",
"tests.acceptance",
"vunit",
"vunit.com",
"vunit.parsing",
"vunit.parsing.verilog",
"vunit.sim_if",
"vunit.test",
"vunit.ui",
"vunit.vivado",
],
package_data={"vunit": DATA_FILES},
zip_safe=False,
url="https://github.com/VUnit/vunit",
classifiers=[
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
"Natural Language :: English",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Operating System :: Microsoft :: Windows",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX :: Linux",
"Topic :: Software Development :: Testing",
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
],
python_requires=">=3.6",
install_requires=["colorama"],
requires=["colorama"],
license="Mozilla Public License 2.0 (MPL 2.0)",
author="Lars Asplund",
author_email="[email protected]",
description="VUnit is an open source unit testing framework for VHDL/SystemVerilog.",
long_description=doc(),
)

if not osvvm_is_installed():
Expand Down
8 changes: 6 additions & 2 deletions tests/unit/test_verilog_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
Test of the Verilog parser
"""

from typing import Optional
from unittest import TestCase, mock
import os
from pathlib import Path
import time
import shutil
from vunit.ostools import renew_path
from vunit.parsing.verilog.parser import VerilogParser
from vunit.parsing.verilog.preprocess import Defines, IncludePaths


class TestVerilogParser(TestCase): # pylint: disable=too-many-public-methods
Expand Down Expand Up @@ -377,7 +379,7 @@ def test_cached_parsing_updated_by_other_defines(self):
self.assertEqual(len(result.modules), 1)
self.assertEqual(result.modules[0].name, "mod2")

def write_file(self, file_name, contents):
def write_file(self, file_name: str, contents: str) -> None:
"""
Write file with contents into output path
"""
Expand All @@ -388,7 +390,9 @@ def write_file(self, file_name, contents):
with full_name.open("w") as fptr:
fptr.write(contents)

def parse(self, code, include_paths=None, cache=None, defines=None):
def parse(
self, code: str, include_paths: Optional[IncludePaths] = None, cache=None, defines: Optional[Defines] = None
):
"""
Helper function to parse
"""
Expand Down
45 changes: 27 additions & 18 deletions tests/unit/test_verilog_preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@

from pathlib import Path
import os
from typing import Dict, List, Optional
from unittest import TestCase, mock
import shutil
from vunit.ostools import renew_path, write_file
from vunit.parsing.verilog.preprocess import VerilogPreprocessor, Macro
from vunit.parsing.verilog.preprocess import Defines, IncludePaths, IncludedFiles, VerilogPreprocessor, Macro
from vunit.parsing.verilog.tokenizer import VerilogTokenizer
from vunit.parsing.tokenizer import Token

Expand Down Expand Up @@ -811,16 +812,18 @@ def test_ignores_protected_region(self):
result.assert_has_tokens("keep_before\n\nkeep_end")
result.assert_no_log()

def preprocess(self, code, file_name="fn.v", include_paths=None):
def preprocess(
self, code: str, file_name: str = "fn.v", include_paths: Optional[IncludePaths] = None
) -> "PreprocessResult":
"""
Tokenize & Preprocess
"""
tokenizer = VerilogTokenizer()
preprocessor = VerilogPreprocessor(tokenizer)
write_file(file_name, code)
tokens = tokenizer.tokenize(code, file_name=file_name)
defines = {}
included_files = []
defines: Defines = {}
included_files: IncludedFiles = []
with mock.patch("vunit.parsing.verilog.preprocess.LOGGER", autospec=True) as logger:
tokens = preprocessor.preprocess(tokens, defines, include_paths, included_files)
return PreprocessResult(
Expand All @@ -831,7 +834,7 @@ def preprocess(self, code, file_name="fn.v", include_paths=None):
logger,
)

def write_file(self, file_name, contents):
def write_file(self, file_name: str, contents: str) -> None:
"""
Write file with contents into output path
"""
Expand All @@ -843,26 +846,32 @@ def write_file(self, file_name, contents):
fptr.write(contents)


class PreprocessResult(object):
class PreprocessResult:
"""
Helper object to test preprocessing
"""

test: TestCase
tokens: List[Token]
defines: Dict[str, Macro]
included_files: List[str]
logger: mock.Mock

def __init__(
self, # pylint: disable=too-many-arguments
test,
tokens,
defines,
included_files,
logger,
test: TestCase,
tokens: List[Token],
defines: Defines,
included_files: List[str],
logger: mock.Mock,
):
self.test = test
self.tokens = tokens
self.defines = defines
self.included_files = included_files
self.logger = logger

def assert_has_tokens(self, code, noloc=True):
def assert_has_tokens(self, code: str, noloc: bool = True):
"""
Check that tokens are the same as code
"""
Expand All @@ -880,19 +889,19 @@ def assert_no_defines(self):
"""
self.test.assertEqual(self.defines, {})

def assert_included_files(self, included_files):
def assert_included_files(self, included_files: List[str]) -> None:
"""
Assert that these files where included
"""
self.test.assertEqual(self.included_files, included_files)

def assert_has_defines(self, defines):
def assert_has_defines(self, defines: Defines) -> None:
"""
Assert that these defines were made
"""
self.test.assertEqual(self.defines.keys(), defines.keys())

def macro_strip_loc(define):
def macro_strip_loc(define: Macro) -> None:
"""
Strip location information from a Macro
"""
Expand All @@ -903,7 +912,7 @@ def macro_strip_loc(define):
for key in self.defines:
self.test.assertEqual(macro_strip_loc(self.defines[key]), macro_strip_loc(defines[key]))

def assert_no_log(self):
def assert_no_log(self) -> None:
"""
Assert that no log call were made
"""
Expand All @@ -913,15 +922,15 @@ def assert_no_log(self):
self.test.assertEqual(self.logger.error.mock_calls, [])


def tokenize(code, file_name="fn.v"):
def tokenize(code: str, file_name: str = "fn.v") -> List[Token]:
"""
Tokenize
"""
tokenizer = VerilogTokenizer()
return tokenizer.tokenize(code, file_name=file_name)


def strip_loc(tokens):
def strip_loc(tokens: List[Token]) -> List[Token]:
"""
Strip location information
"""
Expand Down
Loading