diff --git a/can/bit_timing.py b/can/bit_timing.py index 285b1c302..3e8cb1bcd 100644 --- a/can/bit_timing.py +++ b/can/bit_timing.py @@ -1,8 +1,9 @@ # pylint: disable=too-many-lines import math -from typing import Iterator, List, Mapping, cast +from typing import TYPE_CHECKING, Iterator, List, Mapping, cast -from can.typechecking import BitTimingDict, BitTimingFdDict +if TYPE_CHECKING: + from can.typechecking import BitTimingDict, BitTimingFdDict class BitTiming(Mapping): diff --git a/can/interfaces/gs_usb.py b/can/interfaces/gs_usb.py index 32ad54e75..38f9fe41a 100644 --- a/can/interfaces/gs_usb.py +++ b/can/interfaces/gs_usb.py @@ -35,7 +35,7 @@ def __init__( """ if (index is not None) and ((bus or address) is not None): raise CanInitializationError( - f"index and bus/address cannot be used simultaneously" + "index and bus/address cannot be used simultaneously" ) if index is not None: diff --git a/can/interfaces/ics_neovi/neovi_bus.py b/can/interfaces/ics_neovi/neovi_bus.py index 0698c1416..9270bfc90 100644 --- a/can/interfaces/ics_neovi/neovi_bus.py +++ b/can/interfaces/ics_neovi/neovi_bus.py @@ -302,15 +302,15 @@ def _find_device(self, type_filter=None, serial=None): for device in devices: if serial is None or self.get_serial_number(device) == str(serial): return device - else: - msg = ["No device"] - - if type_filter is not None: - msg.append(f"with type {type_filter}") - if serial is not None: - msg.append(f"with serial {serial}") - msg.append("found.") - raise CanInitializationError(" ".join(msg)) + + msg = ["No device"] + + if type_filter is not None: + msg.append(f"with type {type_filter}") + if serial is not None: + msg.append(f"with serial {serial}") + msg.append("found.") + raise CanInitializationError(" ".join(msg)) def _process_msg_queue(self, timeout=0.1): try: diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 8c07508e4..f18c86acd 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -28,17 +28,17 @@ def __init__( unique_hardware_id: Optional[int] = None, extended: bool = True, fd: bool = False, - rx_fifo_size: int = None, - tx_fifo_size: int = None, + rx_fifo_size: Optional[int] = None, + tx_fifo_size: Optional[int] = None, bitrate: int = 500000, data_bitrate: int = 2000000, - sjw_abr: int = None, - tseg1_abr: int = None, - tseg2_abr: int = None, - sjw_dbr: int = None, - tseg1_dbr: int = None, - tseg2_dbr: int = None, - ssp_dbr: int = None, + sjw_abr: Optional[int] = None, + tseg1_abr: Optional[int] = None, + tseg2_abr: Optional[int] = None, + sjw_dbr: Optional[int] = None, + tseg1_dbr: Optional[int] = None, + tseg2_dbr: Optional[int] = None, + ssp_dbr: Optional[int] = None, **kwargs, ): """ diff --git a/can/interfaces/ixxat/canlib_vcinpl2.py b/can/interfaces/ixxat/canlib_vcinpl2.py index b10ac1b94..2c306c880 100644 --- a/can/interfaces/ixxat/canlib_vcinpl2.py +++ b/can/interfaces/ixxat/canlib_vcinpl2.py @@ -436,13 +436,13 @@ def __init__( tx_fifo_size: int = 128, bitrate: int = 500000, data_bitrate: int = 2000000, - sjw_abr: int = None, - tseg1_abr: int = None, - tseg2_abr: int = None, - sjw_dbr: int = None, - tseg1_dbr: int = None, - tseg2_dbr: int = None, - ssp_dbr: int = None, + sjw_abr: Optional[int] = None, + tseg1_abr: Optional[int] = None, + tseg2_abr: Optional[int] = None, + sjw_dbr: Optional[int] = None, + tseg1_dbr: Optional[int] = None, + tseg2_dbr: Optional[int] = None, + ssp_dbr: Optional[int] = None, **kwargs, ): """ diff --git a/can/interfaces/pcan/basic.py b/can/interfaces/pcan/basic.py index 7c41e2816..a57340955 100644 --- a/can/interfaces/pcan/basic.py +++ b/can/interfaces/pcan/basic.py @@ -297,73 +297,63 @@ # PCAN parameter values # -PCAN_PARAMETER_OFF = int(0x00) # The PCAN parameter is not set (inactive) -PCAN_PARAMETER_ON = int(0x01) # The PCAN parameter is set (active) -PCAN_FILTER_CLOSE = int(0x00) # The PCAN filter is closed. No messages will be received -PCAN_FILTER_OPEN = int( - 0x01 -) # The PCAN filter is fully opened. All messages will be received -PCAN_FILTER_CUSTOM = int( - 0x02 -) # The PCAN filter is custom configured. Only registered messages will be received -PCAN_CHANNEL_UNAVAILABLE = int( - 0x00 -) # The PCAN-Channel handle is illegal, or its associated hardware is not available -PCAN_CHANNEL_AVAILABLE = int( - 0x01 -) # The PCAN-Channel handle is available to be connected (PnP Hardware: it means furthermore that the hardware is plugged-in) -PCAN_CHANNEL_OCCUPIED = int( - 0x02 -) # The PCAN-Channel handle is valid, and is already being used +PCAN_PARAMETER_OFF = 0x00 # The PCAN parameter is not set (inactive) +PCAN_PARAMETER_ON = 0x01 # The PCAN parameter is set (active) +PCAN_FILTER_CLOSE = 0x00 # The PCAN filter is closed. No messages will be received +PCAN_FILTER_OPEN = ( + 0x01 # The PCAN filter is fully opened. All messages will be received +) +PCAN_FILTER_CUSTOM = 0x02 # The PCAN filter is custom configured. Only registered messages will be received +PCAN_CHANNEL_UNAVAILABLE = 0x00 # The PCAN-Channel handle is illegal, or its associated hardware is not available +PCAN_CHANNEL_AVAILABLE = 0x01 # The PCAN-Channel handle is available to be connected (PnP Hardware: it means furthermore that the hardware is plugged-in) +PCAN_CHANNEL_OCCUPIED = ( + 0x02 # The PCAN-Channel handle is valid, and is already being used +) PCAN_CHANNEL_PCANVIEW = ( PCAN_CHANNEL_AVAILABLE | PCAN_CHANNEL_OCCUPIED ) # The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect -LOG_FUNCTION_DEFAULT = int(0x00) # Logs system exceptions / errors -LOG_FUNCTION_ENTRY = int(0x01) # Logs the entries to the PCAN-Basic API functions -LOG_FUNCTION_PARAMETERS = int( - 0x02 -) # Logs the parameters passed to the PCAN-Basic API functions -LOG_FUNCTION_LEAVE = int(0x04) # Logs the exits from the PCAN-Basic API functions -LOG_FUNCTION_WRITE = int(0x08) # Logs the CAN messages passed to the CAN_Write function -LOG_FUNCTION_READ = int( - 0x10 -) # Logs the CAN messages received within the CAN_Read function -LOG_FUNCTION_ALL = int( - 0xFFFF -) # Logs all possible information within the PCAN-Basic API functions +LOG_FUNCTION_DEFAULT = 0x00 # Logs system exceptions / errors +LOG_FUNCTION_ENTRY = 0x01 # Logs the entries to the PCAN-Basic API functions +LOG_FUNCTION_PARAMETERS = ( + 0x02 # Logs the parameters passed to the PCAN-Basic API functions +) +LOG_FUNCTION_LEAVE = 0x04 # Logs the exits from the PCAN-Basic API functions +LOG_FUNCTION_WRITE = 0x08 # Logs the CAN messages passed to the CAN_Write function +LOG_FUNCTION_READ = 0x10 # Logs the CAN messages received within the CAN_Read function +LOG_FUNCTION_ALL = ( + 0xFFFF # Logs all possible information within the PCAN-Basic API functions +) -TRACE_FILE_SINGLE = int( - 0x00 -) # A single file is written until it size reaches PAN_TRACE_SIZE -TRACE_FILE_SEGMENTED = int( - 0x01 -) # Traced data is distributed in several files with size PAN_TRACE_SIZE -TRACE_FILE_DATE = int(0x02) # Includes the date into the name of the trace file -TRACE_FILE_TIME = int(0x04) # Includes the start time into the name of the trace file -TRACE_FILE_OVERWRITE = int( - 0x80 -) # Causes the overwriting of available traces (same name) +TRACE_FILE_SINGLE = ( + 0x00 # A single file is written until it size reaches PAN_TRACE_SIZE +) +TRACE_FILE_SEGMENTED = ( + 0x01 # Traced data is distributed in several files with size PAN_TRACE_SIZE +) +TRACE_FILE_DATE = 0x02 # Includes the date into the name of the trace file +TRACE_FILE_TIME = 0x04 # Includes the start time into the name of the trace file +TRACE_FILE_OVERWRITE = 0x80 # Causes the overwriting of available traces (same name) -FEATURE_FD_CAPABLE = int(0x01) # Device supports flexible data-rate (CAN-FD) -FEATURE_DELAY_CAPABLE = int( - 0x02 -) # Device supports a delay between sending frames (FPGA based USB devices) -FEATURE_IO_CAPABLE = int( - 0x04 -) # Device supports I/O functionality for electronic circuits (USB-Chip devices) +FEATURE_FD_CAPABLE = 0x01 # Device supports flexible data-rate (CAN-FD) +FEATURE_DELAY_CAPABLE = ( + 0x02 # Device supports a delay between sending frames (FPGA based USB devices) +) +FEATURE_IO_CAPABLE = ( + 0x04 # Device supports I/O functionality for electronic circuits (USB-Chip devices) +) -SERVICE_STATUS_STOPPED = int(0x01) # The service is not running -SERVICE_STATUS_RUNNING = int(0x04) # The service is running +SERVICE_STATUS_STOPPED = 0x01 # The service is not running +SERVICE_STATUS_RUNNING = 0x04 # The service is running # Other constants # -MAX_LENGTH_HARDWARE_NAME = int( - 33 -) # Maximum length of the name of a device: 32 characters + terminator -MAX_LENGTH_VERSION_STRING = int( - 256 -) # Maximum length of a version string: 255 characters + terminator +MAX_LENGTH_HARDWARE_NAME = ( + 33 # Maximum length of the name of a device: 32 characters + terminator +) +MAX_LENGTH_VERSION_STRING = ( + 256 # Maximum length of a version string: 255 characters + terminator +) # PCAN message types # diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 25610a614..01a4b1dc3 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -85,7 +85,7 @@ boottimeEpoch = 0 else: boottimeEpoch = uptime.boottime().timestamp() -except ImportError as error: +except ImportError: log.warning( "uptime library not available, timestamps are relative to boot time and not to Epoch UTC", ) @@ -283,7 +283,7 @@ def __init__( clock_param = "f_clock" if "f_clock" in kwargs else "f_clock_mhz" fd_parameters_values = [ f"{key}={kwargs[key]}" - for key in (clock_param,) + PCAN_FD_PARAMETER_LIST + for key in (clock_param, *PCAN_FD_PARAMETER_LIST) if key in kwargs ] @@ -413,7 +413,7 @@ def bits(n): def get_api_version(self): error, value = self.m_objPCANBasic.GetValue(PCAN_NONEBUS, PCAN_API_VERSION) if error != PCAN_ERROR_OK: - raise CanInitializationError(f"Failed to read pcan basic api version") + raise CanInitializationError("Failed to read pcan basic api version") # fix https://github.com/hardbyte/python-can/issues/1642 version_string = value.decode("ascii").replace(",", ".").replace(" ", "") diff --git a/can/interfaces/socketcand/socketcand.py b/can/interfaces/socketcand/socketcand.py index 183a9ba12..26ae63ca6 100644 --- a/can/interfaces/socketcand/socketcand.py +++ b/can/interfaces/socketcand/socketcand.py @@ -91,7 +91,7 @@ def __init__(self, channel, host, port, can_filters=None, **kwargs): ) self._tcp_send(f"< open {channel} >") self._expect_msg("< ok >") - self._tcp_send(f"< rawmode >") + self._tcp_send("< rawmode >") self._expect_msg("< ok >") super().__init__(channel=channel, can_filters=can_filters, **kwargs) diff --git a/can/interfaces/systec/ucan.py b/can/interfaces/systec/ucan.py index bbc484314..f969532d7 100644 --- a/can/interfaces/systec/ucan.py +++ b/can/interfaces/systec/ucan.py @@ -409,7 +409,7 @@ def init_hardware(self, serial=None, device_number=ANY_MODULE): Initializes the device with the corresponding serial or device number. :param int or None serial: Serial number of the USB-CANmodul. - :param int device_number: Device number (0 – 254, or :const:`ANY_MODULE` for the first device). + :param int device_number: Device number (0 - 254, or :const:`ANY_MODULE` for the first device). """ if not self._hw_is_initialized: # initialize hardware either by device number or serial diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index 55aeb5da4..cedf25666 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -69,19 +69,17 @@ class VectorBus(BusABC): """The CAN Bus implemented for the Vector interface.""" - deprecated_args = dict( - sjwAbr="sjw_abr", - tseg1Abr="tseg1_abr", - tseg2Abr="tseg2_abr", - sjwDbr="sjw_dbr", - tseg1Dbr="tseg1_dbr", - tseg2Dbr="tseg2_dbr", - ) - @deprecated_args_alias( deprecation_start="4.0.0", deprecation_end="5.0.0", - **deprecated_args, + **{ + "sjwAbr": "sjw_abr", + "tseg1Abr": "tseg1_abr", + "tseg2Abr": "tseg2_abr", + "sjwDbr": "sjw_dbr", + "tseg1Dbr": "tseg1_dbr", + "tseg2Dbr": "tseg2_dbr", + }, ) def __init__( self, diff --git a/can/io/asc.py b/can/io/asc.py index 3114acfbe..f039cda32 100644 --- a/can/io/asc.py +++ b/can/io/asc.py @@ -64,8 +64,8 @@ def __init__( self.internal_events_logged = False def _extract_header(self) -> None: - for line in self.file: - line = line.strip() + for _line in self.file: + line = _line.strip() datetime_match = re.match( r"date\s+\w+\s+(?P.+)", line, re.IGNORECASE @@ -255,8 +255,8 @@ def _process_fd_can_frame(self, line: str, msg_kwargs: Dict[str, Any]) -> Messag def __iter__(self) -> Generator[Message, None, None]: self._extract_header() - for line in self.file: - line = line.strip() + for _line in self.file: + line = _line.strip() trigger_match = re.match( r"begin\s+triggerblock\s+\w+\s+(?P.+)", diff --git a/can/io/trc.py b/can/io/trc.py index ccf122d57..889d55196 100644 --- a/can/io/trc.py +++ b/can/io/trc.py @@ -68,8 +68,8 @@ def __init__( def _extract_header(self): line = "" - for line in self.file: - line = line.strip() + for _line in self.file: + line = _line.strip() if line.startswith(";$FILEVERSION"): logger.debug("TRCReader: Found file version '%s'", line) try: diff --git a/can/logger.py b/can/logger.py index 56f9156a8..f20965b04 100644 --- a/can/logger.py +++ b/can/logger.py @@ -3,16 +3,18 @@ import re import sys from datetime import datetime -from typing import Any, Dict, List, Sequence, Tuple, Union +from typing import TYPE_CHECKING, Any, Dict, List, Sequence, Tuple, Union import can -from can.io import BaseRotatingLogger -from can.io.generic import MessageWriter from can.util import cast_from_string from . import Bus, BusState, Logger, SizedRotatingLogger from .typechecking import CanFilter, CanFilters +if TYPE_CHECKING: + from can.io import BaseRotatingLogger + from can.io.generic import MessageWriter + def _create_base_argument_parser(parser: argparse.ArgumentParser) -> None: """Adds common options to an argument parser.""" diff --git a/can/util.py b/can/util.py index 402934379..42b1f49ac 100644 --- a/can/util.py +++ b/can/util.py @@ -190,9 +190,8 @@ def load_config( ) # Slightly complex here to only search for the file config if required - for cfg in config_sources: - if callable(cfg): - cfg = cfg(context) + for _cfg in config_sources: + cfg = _cfg(context) if callable(_cfg) else _cfg # remove legacy operator (and copy to interface if not already present) if "bustype" in cfg: if "interface" not in cfg or not cfg["interface"]: diff --git a/can/viewer.py b/can/viewer.py index be7f76b73..db19fd1f6 100644 --- a/can/viewer.py +++ b/can/viewer.py @@ -537,7 +537,7 @@ def parse_args(args: List[str]) -> Tuple: scaling.append(float(t)) if scaling: - data_structs[key] = (struct.Struct(fmt),) + tuple(scaling) + data_structs[key] = (struct.Struct(fmt), *scaling) else: data_structs[key] = struct.Struct(fmt) diff --git a/pyproject.toml b/pyproject.toml index 6ee1dbadc..e20fd2785 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,9 +59,9 @@ changelog = "https://github.com/hardbyte/python-can/blob/develop/CHANGELOG.md" [project.optional-dependencies] lint = [ "pylint==2.17.*", - "ruff==0.0.269", - "black==23.3.*", - "mypy==1.3.*", + "ruff==0.0.292", + "black==23.9.*", + "mypy==1.5.*", ] seeedstudio = ["pyserial>=3.0"] serial = ["pyserial~=3.0"] @@ -91,7 +91,7 @@ examples = ["*.py"] can = ["py.typed"] [tool.setuptools.packages.find] -include = ["can*", "scripts"] +include = ["can*"] [tool.mypy] warn_return_any = true @@ -128,14 +128,22 @@ exclude = [ [tool.ruff] select = [ - "F401", # unused-imports - "UP", # pyupgrade - "I", # isort - "E", # pycodestyle errors - "W", # pycodestyle warnings + "F", # pyflakes + "UP", # pyupgrade + "I", # isort + "E", # pycodestyle errors + "W", # pycodestyle warnings + "PL", # pylint + "RUF", # ruff-specific rules + "C4", # flake8-comprehensions + "TCH", # flake8-type-checking ] ignore = [ - "E501", # Line too long + "E501", # Line too long + "F403", # undefined-local-with-import-star + "F405", # undefined-local-with-import-star-usage + "PLR", # pylint refactor + "RUF012", # mutable-class-default ] [tool.ruff.isort] diff --git a/test/back2back_test.py b/test/back2back_test.py index 52bfaf716..cd5aca6aa 100644 --- a/test/back2back_test.py +++ b/test/back2back_test.py @@ -116,7 +116,7 @@ def test_timestamp(self): self.assertTrue( 1.75 <= delta_time <= 2.25, "Time difference should have been 2s +/- 250ms." - "But measured {}".format(delta_time), + f"But measured {delta_time}", ) def test_standard_message(self): diff --git a/test/network_test.py b/test/network_test.py index 61690c1b4..250976fb2 100644 --- a/test/network_test.py +++ b/test/network_test.py @@ -6,12 +6,15 @@ import threading import unittest +import can + logging.getLogger(__file__).setLevel(logging.WARNING) + # make a random bool: -rbool = lambda: bool(round(random.random())) +def rbool(): + return bool(round(random.random())) -import can channel = "vcan0" diff --git a/test/test_player.py b/test/test_player.py index 5ad6e774c..e5e77fe8a 100755 --- a/test/test_player.py +++ b/test/test_player.py @@ -60,14 +60,8 @@ def test_play_virtual(self): dlc=8, data=[0x5, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], ) - if sys.version_info >= (3, 8): - # The args argument was introduced with python 3.8 - self.assertTrue( - msg1.equals(self.mock_virtual_bus.send.mock_calls[0].args[0]) - ) - self.assertTrue( - msg2.equals(self.mock_virtual_bus.send.mock_calls[1].args[0]) - ) + self.assertTrue(msg1.equals(self.mock_virtual_bus.send.mock_calls[0].args[0])) + self.assertTrue(msg2.equals(self.mock_virtual_bus.send.mock_calls[1].args[0])) self.assertSuccessfulCleanup() def test_play_virtual_verbose(self): diff --git a/test/test_slcan.py b/test/test_slcan.py index a2f8f5d15..f74207b9f 100644 --- a/test/test_slcan.py +++ b/test/test_slcan.py @@ -12,8 +12,8 @@ """ Mentioned in #1010 & #1490 -> PyPy works best with pure Python applications. Whenever you use a C extension module, -> it runs much slower than in CPython. The reason is that PyPy can't optimize C extension modules since they're not fully supported. +> PyPy works best with pure Python applications. Whenever you use a C extension module, +> it runs much slower than in CPython. The reason is that PyPy can't optimize C extension modules since they're not fully supported. > In addition, PyPy has to emulate reference counting for that part of the code, making it even slower. https://realpython.com/pypy-faster-python/#it-doesnt-work-well-with-c-extensions diff --git a/test/test_socketcan.py b/test/test_socketcan.py index f756cb93a..af06b8169 100644 --- a/test/test_socketcan.py +++ b/test/test_socketcan.py @@ -9,8 +9,6 @@ import warnings from unittest.mock import patch -from .config import TEST_INTERFACE_SOCKETCAN - import can from can.interfaces.socketcan.constants import ( CAN_BCM_TX_DELETE, @@ -28,7 +26,7 @@ build_bcm_update_header, ) -from .config import IS_LINUX, IS_PYPY +from .config import IS_LINUX, IS_PYPY, TEST_INTERFACE_SOCKETCAN class SocketCANTest(unittest.TestCase): diff --git a/test/test_vector.py b/test/test_vector.py index 93aba9c7b..ab9f8a928 100644 --- a/test/test_vector.py +++ b/test/test_vector.py @@ -881,7 +881,7 @@ def _find_xl_channel_config(serial: int, channel: int) -> xlclass.XLchannelConfi raise LookupError("XLchannelConfig not found.") -@functools.lru_cache() +@functools.lru_cache def _find_virtual_can_serial() -> int: """Serial number might be 0 or 100 depending on driver version.""" xl_driver_config = xlclass.XLdriverConfig()