diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6364ce7..c3d3e6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,7 @@ jobs: python -m pip install -e .[dev] - name: Code Format Check with Black run: | - black --check --verbose . + black --check --verbose ./src build: name: Build artifacts diff --git a/pyproject.toml b/pyproject.toml index a33c7dd..b6f5e96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,16 +53,13 @@ version = {attr = "pycanape.__version__"} "py.typed", ] -[tool.black] -include = '^/((docs|src)/.*|setup)\.pyi?$' - [tool.mypy] show_error_codes = true ignore_missing_imports = false disallow_untyped_defs = false -disallow_incomplete_defs = false +disallow_incomplete_defs = true check_untyped_defs = true -warn_unused_ignores = false +warn_unused_ignores = true warn_redundant_casts = true disallow_any_generics = true disallow_subclassing_any = true @@ -90,13 +87,16 @@ select = [ "ISC", # flake8-implicit-str-concat "PIE", # flake8-pie "RSE", # flake8-raise + "RUF", # Ruff-specific rules "S", # flake8-bandit "SIM", # flake8-simplify + "TCH", # flake8-type-checking "UP", # pyupgrade "W", # pycodestyle ] ignore = [ "E501", # line too long + "RUF012", # mutable-class-default ] [tool.ruff.isort] diff --git a/src/pycanape/calibration_object.py b/src/pycanape/calibration_object.py index c264740..a82893e 100644 --- a/src/pycanape/calibration_object.py +++ b/src/pycanape/calibration_object.py @@ -149,9 +149,9 @@ def __str__(self) -> str: def __repr__(self) -> str: return ( f"{self.__class__.__name__}(" - f"asap3_handle={repr(self._asap3_handle)}, " - f"module_handle={repr(self._module_handle)}, " - f"name={repr(self._name)}, " + f"asap3_handle={self._asap3_handle!r}, " + f"module_handle={self._module_handle!r}, " + f"name={self._name!r}, " f"object_info)" ) diff --git a/src/pycanape/cnp_api/cnp_class.py b/src/pycanape/cnp_api/cnp_class.py index 44035aa..cdf4496 100644 --- a/src/pycanape/cnp_api/cnp_class.py +++ b/src/pycanape/cnp_api/cnp_class.py @@ -4,6 +4,7 @@ import ctypes from ctypes import wintypes +from typing import ClassVar from . import cnp_constants @@ -39,7 +40,7 @@ class TTaskInfo(ctypes.Structure): """ _pack_ = 1 - _fields_ = [ + _fields_: ClassVar = [ ("description", ctypes.c_char_p), ("taskId", ctypes.c_ushort), ("taskCycle", ctypes.c_ulong), diff --git a/src/pycanape/cnp_api/cnp_prototype.py b/src/pycanape/cnp_api/cnp_prototype.py index 06a5a40..776e5e6 100644 --- a/src/pycanape/cnp_api/cnp_prototype.py +++ b/src/pycanape/cnp_api/cnp_prototype.py @@ -31,7 +31,7 @@ def get_last_error(result, function, args): if error_code > 0: error_msg = ( - f"{cnp_constants.ErrorCodes(error_code).name}: " # type: ignore[union-attr] + f"{cnp_constants.ErrorCodes(error_code).name}: " f"{ptr.contents.value.decode('ascii')}" # type: ignore[union-attr] ) raise CANapeError(error_code, error_msg, function.__name__) diff --git a/src/pycanape/utils.py b/src/pycanape/utils.py index 063b033..8196efa 100644 --- a/src/pycanape/utils.py +++ b/src/pycanape/utils.py @@ -5,16 +5,23 @@ import ctypes import logging import winreg +from collections.abc import Callable from ctypes.util import find_library from threading import Lock +from typing import Any, ParamSpec, TypeVar import psutil LOG = logging.getLogger(__name__) LOCK = Lock() +P1 = ParamSpec("P1") +T1 = TypeVar("T1") -def _synchronization_wrapper(func, func_name: str): + +def _synchronization_wrapper( + func: Callable[P1, T1], func_name: str +) -> Callable[P1, T1]: """Use locks to assure thread safety. Without synchronization it is possible that Asap3GetLastError @@ -46,7 +53,7 @@ def __init__(self, library_or_path: str) -> None: def function_type(self): return ctypes.WINFUNCTYPE - def map_symbol(self, func_name: str, restype=None, argtypes=(), errcheck=None): + def map_symbol(self, func_name: str, restype=None, argtypes=(), errcheck=None) -> Callable[..., Any]: # type: ignore[no-untyped-def] """ Map and return a symbol (function) from a C library. A reference to the mapped symbol is also held in the instance @@ -81,7 +88,7 @@ def map_symbol(self, func_name: str, restype=None, argtypes=(), errcheck=None): class CANapeError(Exception): - def __init__(self, error_code, error_string, function) -> None: + def __init__(self, error_code: int, error_string: str, function: str) -> None: #: The error code according to :class:`~pycanape.cnp_api.cnp_constants.ErrorCodes` self.error_code = error_code super().__init__(f"{function} failed ({error_string})")