Skip to content

Commit 9fdc124

Browse files
authored
Merge branch 'main' into slcanFD
2 parents 460d74b + 958fc64 commit 9fdc124

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+1578
-874
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ jobs:
1818
os: [ubuntu-latest, macos-latest, windows-latest]
1919
experimental: [false]
2020
python-version: [
21-
"3.8",
2221
"3.9",
2322
"3.10",
2423
"3.11",
@@ -42,6 +41,7 @@ jobs:
4241
- name: Setup SocketCAN
4342
if: ${{ matrix.os == 'ubuntu-latest' }}
4443
run: |
44+
sudo apt-get update
4545
sudo apt-get -y install linux-modules-extra-$(uname -r)
4646
sudo ./test/open_vcan.sh
4747
- name: Test with pytest via tox
@@ -80,10 +80,7 @@ jobs:
8080
- name: Install dependencies
8181
run: |
8282
python -m pip install --upgrade pip
83-
pip install -e .[lint]
84-
- name: mypy 3.8
85-
run: |
86-
mypy --python-version 3.8 .
83+
pip install --group lint -e .
8784
- name: mypy 3.9
8885
run: |
8986
mypy --python-version 3.9 .
@@ -96,6 +93,9 @@ jobs:
9693
- name: mypy 3.12
9794
run: |
9895
mypy --python-version 3.12 .
96+
- name: mypy 3.13
97+
run: |
98+
mypy --python-version 3.13 .
9999
- name: ruff
100100
run: |
101101
ruff check can
@@ -119,7 +119,7 @@ jobs:
119119
- name: Install dependencies
120120
run: |
121121
python -m pip install --upgrade pip
122-
pip install -e .[lint]
122+
pip install --group lint
123123
- name: Code Format Check with Black
124124
run: |
125125
black --check --verbose .

.readthedocs.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ build:
1010
os: ubuntu-22.04
1111
tools:
1212
python: "3.12"
13+
jobs:
14+
post_install:
15+
- pip install --group docs
1316

1417
# Build documentation in the docs/ directory with Sphinx
1518
sphinx:
@@ -23,10 +26,11 @@ formats:
2326
# Optionally declare the Python requirements required to build your docs
2427
python:
2528
install:
26-
- requirements: doc/doc-requirements.txt
2729
- method: pip
2830
path: .
2931
extra_requirements:
3032
- canalystii
31-
- gs_usb
33+
- gs-usb
3234
- mf4
35+
- remote
36+
- serial

README.rst

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ python-can
33

44
|pypi| |conda| |python_implementation| |downloads| |downloads_monthly|
55

6-
|docs| |github-actions| |coverage| |mergify| |formatter|
6+
|docs| |github-actions| |coverage| |formatter|
77

88
.. |pypi| image:: https://img.shields.io/pypi/v/python-can.svg
99
:target: https://pypi.python.org/pypi/python-can/
@@ -41,10 +41,6 @@ python-can
4141
:target: https://coveralls.io/github/hardbyte/python-can?branch=develop
4242
:alt: Test coverage reports on Coveralls.io
4343

44-
.. |mergify| image:: https://img.shields.io/endpoint.svg?url=https://api.mergify.com/v1/badges/hardbyte/python-can&style=flat
45-
:target: https://mergify.io
46-
:alt: Mergify Status
47-
4844
The **C**\ ontroller **A**\ rea **N**\ etwork is a bus standard designed
4945
to allow microcontrollers and devices to communicate with each other. It
5046
has priority based bus arbitration and reliable deterministic
@@ -64,6 +60,7 @@ Library Version Python
6460
3.x 2.7+, 3.5+
6561
4.0+ 3.7+
6662
4.3+ 3.8+
63+
4.6+ 3.9+
6764
============================== ===========
6865

6966

can/__init__.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,23 @@
88
import contextlib
99
import logging
1010
from importlib.metadata import PackageNotFoundError, version
11-
from typing import Any, Dict
11+
from typing import Any
1212

1313
__all__ = [
14+
"VALID_INTERFACES",
1415
"ASCReader",
1516
"ASCWriter",
1617
"AsyncBufferedReader",
17-
"BitTiming",
18-
"BitTimingFd",
1918
"BLFReader",
2019
"BLFWriter",
20+
"BitTiming",
21+
"BitTimingFd",
2122
"BufferedReader",
2223
"Bus",
2324
"BusABC",
2425
"BusState",
26+
"CSVReader",
27+
"CSVWriter",
2528
"CanError",
2629
"CanInitializationError",
2730
"CanInterfaceNotImplementedError",
@@ -30,30 +33,27 @@
3033
"CanTimeoutError",
3134
"CanutilsLogReader",
3235
"CanutilsLogWriter",
33-
"CSVReader",
34-
"CSVWriter",
3536
"CyclicSendTaskABC",
3637
"LimitedDurationCyclicSendTaskABC",
3738
"Listener",
38-
"Logger",
3939
"LogReader",
40-
"ModifiableCyclicTaskABC",
41-
"Message",
42-
"MessageSync",
40+
"Logger",
4341
"MF4Reader",
4442
"MF4Writer",
43+
"Message",
44+
"MessageSync",
45+
"ModifiableCyclicTaskABC",
4546
"Notifier",
4647
"Printer",
4748
"RedirectReader",
4849
"RestartableCyclicTaskABC",
4950
"SizedRotatingLogger",
5051
"SqliteReader",
5152
"SqliteWriter",
52-
"ThreadSafeBus",
5353
"TRCFileVersion",
5454
"TRCReader",
5555
"TRCWriter",
56-
"VALID_INTERFACES",
56+
"ThreadSafeBus",
5757
"bit_timing",
5858
"broadcastmanager",
5959
"bus",
@@ -64,8 +64,8 @@
6464
"interfaces",
6565
"io",
6666
"listener",
67-
"logconvert",
6867
"log",
68+
"logconvert",
6969
"logger",
7070
"message",
7171
"notifier",
@@ -130,4 +130,4 @@
130130

131131
log = logging.getLogger("can")
132132

133-
rc: Dict[str, Any] = {}
133+
rc: dict[str, Any] = {}

can/_entry_points.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
from dataclasses import dataclass
44
from importlib.metadata import entry_points
5-
from typing import Any, List
5+
from typing import Any
66

77

88
@dataclass
@@ -20,14 +20,14 @@ def load(self) -> Any:
2020
# "Compatibility Note".
2121
if sys.version_info >= (3, 10):
2222

23-
def read_entry_points(group: str) -> List[_EntryPoint]:
23+
def read_entry_points(group: str) -> list[_EntryPoint]:
2424
return [
2525
_EntryPoint(ep.name, ep.module, ep.attr) for ep in entry_points(group=group)
2626
]
2727

2828
else:
2929

30-
def read_entry_points(group: str) -> List[_EntryPoint]:
30+
def read_entry_points(group: str) -> list[_EntryPoint]:
3131
return [
3232
_EntryPoint(ep.name, *ep.value.split(":", maxsplit=1))
3333
for ep in entry_points().get(group, [])

can/bit_timing.py

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# pylint: disable=too-many-lines
22
import math
3-
from typing import TYPE_CHECKING, Iterator, List, Mapping, cast
3+
from collections.abc import Iterator, Mapping
4+
from typing import TYPE_CHECKING, cast
45

56
if TYPE_CHECKING:
67
from can.typechecking import BitTimingDict, BitTimingFdDict
@@ -155,7 +156,7 @@ def from_bitrate_and_segments(
155156
if the arguments are invalid.
156157
"""
157158
try:
158-
brp = int(round(f_clock / (bitrate * (1 + tseg1 + tseg2))))
159+
brp = round(f_clock / (bitrate * (1 + tseg1 + tseg2)))
159160
except ZeroDivisionError:
160161
raise ValueError("Invalid inputs") from None
161162

@@ -232,15 +233,15 @@ def iterate_from_sample_point(
232233
raise ValueError(f"sample_point (={sample_point}) must not be below 50%.")
233234

234235
for brp in range(1, 65):
235-
nbt = round(int(f_clock / (bitrate * brp)))
236+
nbt = int(f_clock / (bitrate * brp))
236237
if nbt < 8:
237238
break
238239

239240
effective_bitrate = f_clock / (nbt * brp)
240241
if abs(effective_bitrate - bitrate) > bitrate / 256:
241242
continue
242243

243-
tseg1 = int(round(sample_point / 100 * nbt)) - 1
244+
tseg1 = round(sample_point / 100 * nbt) - 1
244245
# limit tseg1, so tseg2 is at least 1 TQ
245246
tseg1 = min(tseg1, nbt - 2)
246247

@@ -286,7 +287,7 @@ def from_sample_point(
286287
if sample_point < 50.0:
287288
raise ValueError(f"sample_point (={sample_point}) must not be below 50%.")
288289

289-
possible_solutions: List[BitTiming] = list(
290+
possible_solutions: list[BitTiming] = list(
290291
cls.iterate_from_sample_point(f_clock, bitrate, sample_point)
291292
)
292293

@@ -312,7 +313,7 @@ def f_clock(self) -> int:
312313
@property
313314
def bitrate(self) -> int:
314315
"""Bitrate in bits/s."""
315-
return int(round(self.f_clock / (self.nbt * self.brp)))
316+
return round(self.f_clock / (self.nbt * self.brp))
316317

317318
@property
318319
def brp(self) -> int:
@@ -322,7 +323,7 @@ def brp(self) -> int:
322323
@property
323324
def tq(self) -> int:
324325
"""Time quantum in nanoseconds"""
325-
return int(round(self.brp / self.f_clock * 1e9))
326+
return round(self.brp / self.f_clock * 1e9)
326327

327328
@property
328329
def nbt(self) -> int:
@@ -433,7 +434,7 @@ def recreate_with_f_clock(self, f_clock: int) -> "BitTiming":
433434
"f_clock change failed because of sample point discrepancy."
434435
)
435436
# adapt synchronization jump width, so it has the same size relative to bit time as self
436-
sjw = int(round(self.sjw / self.nbt * bt.nbt))
437+
sjw = round(self.sjw / self.nbt * bt.nbt)
437438
sjw = max(1, min(4, bt.tseg2, sjw))
438439
bt._data["sjw"] = sjw # pylint: disable=protected-access
439440
bt._data["nof_samples"] = self.nof_samples # pylint: disable=protected-access
@@ -458,7 +459,7 @@ def __repr__(self) -> str:
458459
return f"can.{self.__class__.__name__}({args})"
459460

460461
def __getitem__(self, key: str) -> int:
461-
return cast(int, self._data.__getitem__(key))
462+
return cast("int", self._data.__getitem__(key))
462463

463464
def __len__(self) -> int:
464465
return self._data.__len__()
@@ -716,10 +717,8 @@ def from_bitrate_and_segments( # pylint: disable=too-many-arguments
716717
if the arguments are invalid.
717718
"""
718719
try:
719-
nom_brp = int(round(f_clock / (nom_bitrate * (1 + nom_tseg1 + nom_tseg2))))
720-
data_brp = int(
721-
round(f_clock / (data_bitrate * (1 + data_tseg1 + data_tseg2)))
722-
)
720+
nom_brp = round(f_clock / (nom_bitrate * (1 + nom_tseg1 + nom_tseg2)))
721+
data_brp = round(f_clock / (data_bitrate * (1 + data_tseg1 + data_tseg2)))
723722
except ZeroDivisionError:
724723
raise ValueError("Invalid inputs.") from None
725724

@@ -787,15 +786,15 @@ def iterate_from_sample_point(
787786
sync_seg = 1
788787

789788
for nom_brp in range(1, 257):
790-
nbt = round(int(f_clock / (nom_bitrate * nom_brp)))
789+
nbt = int(f_clock / (nom_bitrate * nom_brp))
791790
if nbt < 1:
792791
break
793792

794793
effective_nom_bitrate = f_clock / (nbt * nom_brp)
795794
if abs(effective_nom_bitrate - nom_bitrate) > nom_bitrate / 256:
796795
continue
797796

798-
nom_tseg1 = int(round(nom_sample_point / 100 * nbt)) - 1
797+
nom_tseg1 = round(nom_sample_point / 100 * nbt) - 1
799798
# limit tseg1, so tseg2 is at least 2 TQ
800799
nom_tseg1 = min(nom_tseg1, nbt - sync_seg - 2)
801800
nom_tseg2 = nbt - nom_tseg1 - 1
@@ -811,7 +810,7 @@ def iterate_from_sample_point(
811810
if abs(effective_data_bitrate - data_bitrate) > data_bitrate / 256:
812811
continue
813812

814-
data_tseg1 = int(round(data_sample_point / 100 * dbt)) - 1
813+
data_tseg1 = round(data_sample_point / 100 * dbt) - 1
815814
# limit tseg1, so tseg2 is at least 2 TQ
816815
data_tseg1 = min(data_tseg1, dbt - sync_seg - 2)
817816
data_tseg2 = dbt - data_tseg1 - 1
@@ -876,7 +875,7 @@ def from_sample_point(
876875
f"data_sample_point (={data_sample_point}) must not be below 50%."
877876
)
878877

879-
possible_solutions: List[BitTimingFd] = list(
878+
possible_solutions: list[BitTimingFd] = list(
880879
cls.iterate_from_sample_point(
881880
f_clock,
882881
nom_bitrate,
@@ -923,7 +922,7 @@ def f_clock(self) -> int:
923922
@property
924923
def nom_bitrate(self) -> int:
925924
"""Nominal (arbitration phase) bitrate."""
926-
return int(round(self.f_clock / (self.nbt * self.nom_brp)))
925+
return round(self.f_clock / (self.nbt * self.nom_brp))
927926

928927
@property
929928
def nom_brp(self) -> int:
@@ -933,7 +932,7 @@ def nom_brp(self) -> int:
933932
@property
934933
def nom_tq(self) -> int:
935934
"""Nominal time quantum in nanoseconds"""
936-
return int(round(self.nom_brp / self.f_clock * 1e9))
935+
return round(self.nom_brp / self.f_clock * 1e9)
937936

938937
@property
939938
def nbt(self) -> int:
@@ -969,7 +968,7 @@ def nom_sample_point(self) -> float:
969968
@property
970969
def data_bitrate(self) -> int:
971970
"""Bitrate of the data phase in bit/s."""
972-
return int(round(self.f_clock / (self.dbt * self.data_brp)))
971+
return round(self.f_clock / (self.dbt * self.data_brp))
973972

974973
@property
975974
def data_brp(self) -> int:
@@ -979,7 +978,7 @@ def data_brp(self) -> int:
979978
@property
980979
def data_tq(self) -> int:
981980
"""Data time quantum in nanoseconds"""
982-
return int(round(self.data_brp / self.f_clock * 1e9))
981+
return round(self.data_brp / self.f_clock * 1e9)
983982

984983
@property
985984
def dbt(self) -> int:
@@ -1106,10 +1105,10 @@ def recreate_with_f_clock(self, f_clock: int) -> "BitTimingFd":
11061105
"f_clock change failed because of sample point discrepancy."
11071106
)
11081107
# adapt synchronization jump width, so it has the same size relative to bit time as self
1109-
nom_sjw = int(round(self.nom_sjw / self.nbt * bt.nbt))
1108+
nom_sjw = round(self.nom_sjw / self.nbt * bt.nbt)
11101109
nom_sjw = max(1, min(bt.nom_tseg2, nom_sjw))
11111110
bt._data["nom_sjw"] = nom_sjw # pylint: disable=protected-access
1112-
data_sjw = int(round(self.data_sjw / self.dbt * bt.dbt))
1111+
data_sjw = round(self.data_sjw / self.dbt * bt.dbt)
11131112
data_sjw = max(1, min(bt.data_tseg2, data_sjw))
11141113
bt._data["data_sjw"] = data_sjw # pylint: disable=protected-access
11151114
bt._validate() # pylint: disable=protected-access
@@ -1138,7 +1137,7 @@ def __repr__(self) -> str:
11381137
return f"can.{self.__class__.__name__}({args})"
11391138

11401139
def __getitem__(self, key: str) -> int:
1141-
return cast(int, self._data.__getitem__(key))
1140+
return cast("int", self._data.__getitem__(key))
11421141

11431142
def __len__(self) -> int:
11441143
return self._data.__len__()

0 commit comments

Comments
 (0)