Skip to content

Commit 94c1701

Browse files
authored
Merge pull request #1224 from zariiii9003/move_mypy
Move Static Code Analysis to Github Actions
2 parents 803a712 + b75e214 commit 94c1701

File tree

14 files changed

+83
-45
lines changed

14 files changed

+83
-45
lines changed

.github/workflows/build.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,41 @@ jobs:
3939
with:
4040
fail_ci_if_error: true
4141

42+
static-code-analysis:
43+
runs-on: ubuntu-latest
44+
continue-on-error: true
45+
steps:
46+
- uses: actions/checkout@v2
47+
- name: Set up Python
48+
uses: actions/setup-python@v2
49+
with:
50+
python-version: "3.10"
51+
- name: Install dependencies
52+
run: |
53+
python -m pip install --upgrade pip
54+
pip install -e .
55+
pip install -r requirements-lint.txt
56+
- name: mypy 3.7
57+
run: |
58+
mypy --python-version 3.7 .
59+
- name: mypy 3.8
60+
run: |
61+
mypy --python-version 3.8 .
62+
- name: mypy 3.9
63+
run: |
64+
mypy --python-version 3.9 .
65+
- name: mypy 3.10
66+
run: |
67+
mypy --python-version 3.10 .
68+
- name: pylint
69+
run: |
70+
pylint --rcfile=.pylintrc \
71+
can/**.py \
72+
setup.py \
73+
doc.conf \
74+
scripts/**.py \
75+
examples/**.py
76+
4277
format:
4378
runs-on: ubuntu-latest
4479
steps:

.travis.yml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,23 +74,6 @@ jobs:
7474
# -a Write all files
7575
# -n nitpicky
7676
- python -m sphinx -an doc build
77-
- stage: linter
78-
name: "Linter Checks"
79-
python: "3.9"
80-
before_install:
81-
- travis_retry pip install -r requirements-lint.txt
82-
script:
83-
# -------------
84-
# pylint checking:
85-
# check the entire main codebase (except the tests)
86-
- pylint --rcfile=.pylintrc can/**.py setup.py doc.conf scripts/**.py examples/**.py
87-
# -------------
88-
# mypy checking:
89-
- mypy
90-
can/*.py
91-
can/io/**.py
92-
scripts/**.py
93-
examples/**.py
9477
- stage: deploy
9578
name: "PyPi Deployment"
9679
python: "3.9"

can/ctypesutil.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
# type: ignore
12
"""
23
This module contains common `ctypes` utils.
34
"""
4-
55
import ctypes
66
import logging
77
import sys
@@ -14,14 +14,14 @@
1414

1515

1616
try:
17-
_LibBase = ctypes.WinDLL # type: ignore
18-
_FUNCTION_TYPE = ctypes.WINFUNCTYPE # type: ignore
17+
_LibBase = ctypes.WinDLL
18+
_FUNCTION_TYPE = ctypes.WINFUNCTYPE
1919
except AttributeError:
2020
_LibBase = ctypes.CDLL
2121
_FUNCTION_TYPE = ctypes.CFUNCTYPE
2222

2323

24-
class CLibrary(_LibBase): # type: ignore
24+
class CLibrary(_LibBase):
2525
def __init__(self, library_or_path: Union[str, ctypes.CDLL]) -> None:
2626
self.func_name: Any
2727

can/exceptions.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
For example, validating typical arguments and parameters might result in a
1515
:class:`ValueError`. This should always be documented for the function at hand.
1616
"""
17-
18-
17+
import sys
1918
from contextlib import contextmanager
2019

2120
from typing import Optional
2221
from typing import Type
2322

23+
if sys.version_info >= (3, 9):
24+
from collections.abc import Generator
25+
else:
26+
from typing import Generator
27+
2428

2529
class CanError(Exception):
2630
"""Base class for all CAN related exceptions.
@@ -106,7 +110,7 @@ class CanTimeoutError(CanError, TimeoutError):
106110
def error_check(
107111
error_message: Optional[str] = None,
108112
exception_type: Type[CanError] = CanOperationError,
109-
) -> None:
113+
) -> Generator[None, None, None]:
110114
"""Catches any exceptions and turns them into the new type while preserving the stack trace."""
111115
try:
112116
yield

can/io/asc.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- under `test/data/logfile.asc`
77
"""
88
import gzip
9-
from typing import cast, Any, Generator, IO, List, Optional, Dict, Union
9+
from typing import cast, Any, Generator, IO, List, Optional, Dict, Union, TextIO
1010

1111
from datetime import datetime
1212
import time
@@ -34,6 +34,8 @@ class ASCReader(BaseIOHandler):
3434
bus statistics, J1939 Transport Protocol messages) is ignored.
3535
"""
3636

37+
file: TextIO
38+
3739
FORMAT_START_OF_FILE_DATE = "%a %b %d %I:%M:%S.%f %p %Y"
3840

3941
def __init__(
@@ -205,19 +207,18 @@ def _process_fd_can_frame(self, line: str, msg_kwargs: Dict[str, Any]) -> Messag
205207
return Message(**msg_kwargs)
206208

207209
def __iter__(self) -> Generator[Message, None, None]:
208-
# This is guaranteed to not be None since we raise ValueError in __init__
209-
self.file = cast(IO[Any], self.file)
210210
self._extract_header()
211211

212212
for line in self.file:
213213
temp = line.strip()
214214
if not temp or not temp[0].isdigit():
215215
# Could be a comment
216216
continue
217-
msg_kwargs = {}
217+
218+
msg_kwargs: Dict[str, Union[float, bool, int]] = {}
218219
try:
219-
timestamp, channel, rest_of_message = temp.split(None, 2)
220-
timestamp = float(timestamp) + self.start_time
220+
_timestamp, channel, rest_of_message = temp.split(None, 2)
221+
timestamp = float(_timestamp) + self.start_time
221222
msg_kwargs["timestamp"] = timestamp
222223
if channel == "CANFD":
223224
msg_kwargs["is_fd"] = True
@@ -250,6 +251,8 @@ class ASCWriter(FileIOMessageWriter, Listener):
250251
It the first message does not have a timestamp, it is set to zero.
251252
"""
252253

254+
file: TextIO
255+
253256
FORMAT_MESSAGE = "{channel} {id:<15} {dir:<4} {dtype} {data}"
254257
FORMAT_MESSAGE_FD = " ".join(
255258
[
@@ -319,8 +322,6 @@ def log_event(self, message: str, timestamp: Optional[float] = None) -> None:
319322
if not message: # if empty or None
320323
logger.debug("ASCWriter: ignoring empty message")
321324
return
322-
# This is guaranteed to not be None since we raise ValueError in __init__
323-
self.file = cast(IO[Any], self.file)
324325

325326
# this is the case for the very first message:
326327
if not self.header_written:

can/io/blf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import datetime
1818
import time
1919
import logging
20-
from typing import List
20+
from typing import List, BinaryIO
2121

2222
from ..message import Message
2323
from ..listener import Listener
@@ -139,6 +139,8 @@ class BLFReader(BaseIOHandler):
139139
silently ignored.
140140
"""
141141

142+
file: BinaryIO
143+
142144
def __init__(self, file: AcceptedIOType) -> None:
143145
"""
144146
:param file: a path-like object or as file-like object to read from
@@ -352,6 +354,8 @@ class BLFWriter(FileIOMessageWriter, Listener):
352354
Logs CAN data to a Binary Logging File compatible with Vector's tools.
353355
"""
354356

357+
file: BinaryIO
358+
355359
#: Max log container size of uncompressed data
356360
max_container_size = 128 * 1024
357361

can/io/canutils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ class CanutilsLogWriter(FileIOMessageWriter, Listener):
114114
It the first message does not have a timestamp, it is set to zero.
115115
"""
116116

117-
def __init__(self, file: AcceptedIOType, channel="vcan0", append=False):
117+
def __init__(
118+
self, file: AcceptedIOType, channel: str = "vcan0", append: bool = False
119+
):
118120
"""
119121
:param file: a path-like object or as file-like object to write to
120122
If this is a file-like object, is has to opened in text

can/io/csv.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"""
1111

1212
from base64 import b64encode, b64decode
13+
from typing import TextIO
1314

1415
from can.message import Message
1516
from can.listener import Listener
@@ -82,6 +83,8 @@ class CSVWriter(FileIOMessageWriter, Listener):
8283
Each line is terminated with a platform specific line separator.
8384
"""
8485

86+
file: TextIO
87+
8588
def __init__(self, file: AcceptedIOType, append: bool = False) -> None:
8689
"""
8790
:param file: a path-like object or a file-like object to write to.

can/io/generic.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ def __init__(
4545
else:
4646
# pylint: disable=consider-using-with
4747
# file is some path-like object
48-
self.file = open(cast(can.typechecking.StringPathLike, file), mode)
48+
self.file = cast(
49+
can.typechecking.FileLike,
50+
open(cast(can.typechecking.StringPathLike, file), mode),
51+
)
4952

5053
# for multiple inheritance
5154
super().__init__()
@@ -80,9 +83,7 @@ class FileIOMessageWriter(MessageWriter, metaclass=ABCMeta):
8083

8184
file: Union[TextIO, BinaryIO]
8285

83-
def __init__(
84-
self, file: Union[can.typechecking.FileLike, TextIO, BinaryIO], mode: str = "rt"
85-
) -> None:
86+
def __init__(self, file: can.typechecking.AcceptedIOType, mode: str = "rt") -> None:
8687
# Not possible with the type signature, but be verbose for user friendliness
8788
if file is None:
8889
raise ValueError("The given file cannot be None")

can/io/logger.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
)
1616
from types import TracebackType
1717

18-
18+
from typing_extensions import Literal
1919
from pkg_resources import iter_entry_points
2020

2121
from ..message import Message
@@ -95,6 +95,9 @@ def __new__( # type: ignore
9595
f'No write support for this unknown log format "{suffix}"'
9696
) from None
9797

98+
def on_message_received(self, msg: Message) -> None:
99+
pass
100+
98101

99102
class BaseRotatingLogger(Listener, BaseIOHandler, ABC):
100103
"""
@@ -232,7 +235,7 @@ def __exit__(
232235
exc_type: Optional[Type[BaseException]],
233236
exc_val: Optional[BaseException],
234237
exc_tb: Optional[TracebackType],
235-
) -> bool:
238+
) -> Literal[False]:
236239
return self._writer.__exit__(exc_type, exc_val, exc_tb)
237240

238241
@abstractmethod

0 commit comments

Comments
 (0)