From 2f8fd2746fd43b91e737f1dc1c8d6763af979f1d Mon Sep 17 00:00:00 2001 From: Olof Kraigher Date: Wed, 27 Nov 2019 18:00:23 +0100 Subject: [PATCH] Make mypy run cleanly --- docs/contributing.rst | 3 ++ tests/lint/test_mypy.py | 24 +++++++++++ tox.ini | 1 + vunit/color_printer.py | 72 +++++++++++++++++++++------------ vunit/parsing/tokenizer.py | 6 ++- vunit/parsing/verilog/tokens.py | 5 ++- vunit/sim_if/__init__.py | 39 +++++++++--------- vunit/test/runner.py | 4 +- 8 files changed, 105 insertions(+), 49 deletions(-) create mode 100644 tests/lint/test_mypy.py diff --git a/docs/contributing.rst b/docs/contributing.rst index 0b735a7fd..6d100fb07 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -68,6 +68,9 @@ following are also required for developers to run the test suite manually: `pylint `__ Code analysis. +`mypy `__ + Optional static typing for Python. + Code coverage ~~~~~~~~~~~~~ diff --git a/tests/lint/test_mypy.py b/tests/lint/test_mypy.py new file mode 100644 index 000000000..168b5799e --- /dev/null +++ b/tests/lint/test_mypy.py @@ -0,0 +1,24 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com + +""" +MyPy check +""" + +import unittest +import sys +from subprocess import check_call +from vunit import ROOT + + +class TestMyPy(unittest.TestCase): + """ + Run MyPy static type analysis + """ + + @staticmethod + def test_pycodestyle(): + check_call([sys.executable, "-m", "mypy", "vunit"]) diff --git a/tox.ini b/tox.ini index 50be47694..5b7c021ef 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,7 @@ deps= pytest lint: pycodestyle lint: pylint + lint: mypy docs: docutils docs: sphinx docs: sphinx-argparse diff --git a/vunit/color_printer.py b/vunit/color_printer.py index b5f9ef16e..cbd26801b 100644 --- a/vunit/color_printer.py +++ b/vunit/color_printer.py @@ -15,9 +15,9 @@ from vunit.ostools import IS_WINDOWS_SYSTEM -class LinuxColorPrinter(object): +class ColorPrinter(object): """ - Print in color on linux + Base class """ BLUE = "b" @@ -29,6 +29,45 @@ class LinuxColorPrinter(object): def __init__(self): pass + @staticmethod + def write( + text, output_file=None, fg=None, bg=None + ): # pylint: disable=unused-argument + """ + Print the text in color to the output_file + uses stdout if output_file is None + """ + + +class NoColorPrinter(ColorPrinter): + """ + Dummy printer that does not print in color + """ + + def __init__(self): + ColorPrinter.__init__(self) + + @staticmethod + def write( + text, output_file=None, fg=None, bg=None + ): # pylint: disable=unused-argument + """ + Print the text in color to the output_file + uses stdout if output_file is None + """ + if output_file is None: + output_file = sys.stdout + output_file.write(text) + + +class LinuxColorPrinter(ColorPrinter): + """ + Print in color on linux + """ + + def __init__(self): + ColorPrinter.__init__(self) + def write(self, text, output_file=None, fg=None, bg=None): """ Print the text in color to the output_file @@ -110,13 +149,13 @@ class ConsoleScreenBufferInfo(Structure): ] -class Win32ColorPrinter(LinuxColorPrinter): +class Win32ColorPrinter(ColorPrinter): """ Prints in color on windows """ def __init__(self): - LinuxColorPrinter.__init__(self) + ColorPrinter.__init__(self) self._stdout_handle = ctypes.windll.kernel32.GetStdHandle(-11) self._stderr_handle = ctypes.windll.kernel32.GetStdHandle(-12) self._default_attr = self._get_text_attr(self._stdout_handle) @@ -186,32 +225,13 @@ def _decode_color(self, color_str): return code -class NoColorPrinter(object): - """ - Dummy printer that does not print in color - """ - - def __init__(self): - pass - - @staticmethod - def write( - text, output_file=None, fg=None, bg=None - ): # pylint: disable=unused-argument - """ - Print the text in color to the output_file - uses stdout if output_file is None - """ - if output_file is None: - output_file = sys.stdout - output_file.write(text) - - -NO_COLOR_PRINTER = NoColorPrinter() +NO_COLOR_PRINTER: ColorPrinter = NoColorPrinter() # On MSYS/MINGW shells (https://www.msys2.org/) with Python installed through pacman, IS_WINDOWS_SYSTEM is true. # However, regular Linux color strings are supported/required, instead of 'native' windows color format. # Environment variable MSYSTEM is checked, which should contain 'msys'|'mingw32'|'mingw64' or be unset/empty. +COLOR_PRINTER: ColorPrinter + if IS_WINDOWS_SYSTEM and ("MSYSTEM" not in os.environ): COLOR_PRINTER = Win32ColorPrinter() else: diff --git a/vunit/parsing/tokenizer.py b/vunit/parsing/tokenizer.py index 7c7c501e8..2ded4c7d6 100644 --- a/vunit/parsing/tokenizer.py +++ b/vunit/parsing/tokenizer.py @@ -19,7 +19,11 @@ def Token(kind, value="", location=None): # pylint: disable=invalid-name return TokenType(kind, value, location) -def new_token_kind(name): +class TokenKind: + pass + + +def new_token_kind(name: str) -> TokenKind: """ Create a new token kind with nice __repr__ """ diff --git a/vunit/parsing/verilog/tokens.py b/vunit/parsing/verilog/tokens.py index 64d6c5e1e..700f7ce7b 100644 --- a/vunit/parsing/verilog/tokens.py +++ b/vunit/parsing/verilog/tokens.py @@ -8,7 +8,8 @@ Verilog tokens """ -from vunit.parsing.tokenizer import new_token_kind +from typing import Dict +from vunit.parsing.tokenizer import new_token_kind, TokenKind def __token(kind): @@ -27,7 +28,7 @@ def __keyword(kind): return token_kind -KEYWORDS = {} +KEYWORDS: Dict[str, TokenKind] = {} PREPROCESSOR = __token("preprocessor") STRING = __token("string") diff --git a/vunit/sim_if/__init__.py b/vunit/sim_if/__init__.py index 502606fb5..eb4d29fff 100644 --- a/vunit/sim_if/__init__.py +++ b/vunit/sim_if/__init__.py @@ -11,21 +11,38 @@ import sys import os import subprocess +from typing import List from ..ostools import Process, simplify_path from ..exceptions import CompileError from ..color_printer import NO_COLOR_PRINTER +class Option(object): + """ + A compile or sim option + """ + + def __init__(self, name): + self._name = name + + @property + def name(self): + return self._name + + def validate(self, value): + pass + + class SimulatorInterface(object): # pylint: disable=too-many-public-methods """ Generic simulator interface """ - name = None + name: str = "none" supports_gui_flag = False package_users_depend_on_bodies = False - compile_options = [] - sim_options = [] + compile_options: List[Option] = [] + sim_options: List[Option] = [] # True if simulator supports ANSI colors in GUI mode supports_colors_in_gui = False @@ -347,22 +364,6 @@ def check_output(command, env=None): return output.decode("utf-8") -class Option(object): - """ - A compile or sim option - """ - - def __init__(self, name): - self._name = name - - @property - def name(self): - return self._name - - def validate(self, value): - pass - - class BooleanOption(Option): """ Must be a boolean diff --git a/vunit/test/runner.py b/vunit/test/runner.py index 524ddebcf..4d47c67fc 100644 --- a/vunit/test/runner.py +++ b/vunit/test/runner.py @@ -464,7 +464,9 @@ def wrap(file_obj, use_color=True): NOTE: imports colorama here to avoid dependency from setup.py importing VUnit before colorama is installed """ - from colorama import AnsiToWin32 # pylint: disable=import-outside-toplevel + from colorama import ( # type: ignore # pylint: disable=import-outside-toplevel + AnsiToWin32, + ) if use_color: return AnsiToWin32(file_obj).stream