Skip to content

Commit 2c90f9f

Browse files
authored
improve TestBusConfig (#1804)
1 parent 478f8b8 commit 2c90f9f

File tree

2 files changed

+88
-29
lines changed

2 files changed

+88
-29
lines changed

can/util.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Utilities and configuration file parsing.
33
"""
44

5+
import contextlib
56
import copy
67
import functools
78
import json
@@ -243,33 +244,41 @@ def _create_bus_config(config: Dict[str, Any]) -> typechecking.BusConfig:
243244
if not 0 < port < 65535:
244245
raise ValueError("Port config must be inside 0-65535 range!")
245246

246-
if config.get("timing", None) is None:
247-
try:
248-
if set(typechecking.BitTimingFdDict.__annotations__).issubset(config):
249-
config["timing"] = can.BitTimingFd(
250-
**{
251-
key: int(config[key])
252-
for key in typechecking.BitTimingFdDict.__annotations__
253-
},
254-
strict=False,
255-
)
256-
elif set(typechecking.BitTimingDict.__annotations__).issubset(config):
257-
config["timing"] = can.BitTiming(
258-
**{
259-
key: int(config[key])
260-
for key in typechecking.BitTimingDict.__annotations__
261-
},
262-
strict=False,
263-
)
264-
except (ValueError, TypeError):
265-
pass
247+
if "timing" not in config:
248+
if timing := _dict2timing(config):
249+
config["timing"] = timing
266250

267251
if "fd" in config:
268252
config["fd"] = config["fd"] not in (0, False)
269253

270254
return cast(typechecking.BusConfig, config)
271255

272256

257+
def _dict2timing(data: Dict[str, Any]) -> Union[BitTiming, BitTimingFd, None]:
258+
"""Try to instantiate a :class:`~can.BitTiming` or :class:`~can.BitTimingFd` from
259+
a dictionary. Return `None` if not possible."""
260+
261+
with contextlib.suppress(ValueError, TypeError):
262+
if set(typechecking.BitTimingFdDict.__annotations__).issubset(data):
263+
return BitTimingFd(
264+
**{
265+
key: int(data[key])
266+
for key in typechecking.BitTimingFdDict.__annotations__
267+
},
268+
strict=False,
269+
)
270+
elif set(typechecking.BitTimingDict.__annotations__).issubset(data):
271+
return BitTiming(
272+
**{
273+
key: int(data[key])
274+
for key in typechecking.BitTimingDict.__annotations__
275+
},
276+
strict=False,
277+
)
278+
279+
return None
280+
281+
273282
def set_logging_level(level_name: str) -> None:
274283
"""Set the logging level for the `"can"` logger.
275284

test/test_util.py

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import pytest
77

8+
import can
89
from can import BitTiming, BitTimingFd
910
from can.exceptions import CanInitializationError
1011
from can.util import (
@@ -132,10 +133,7 @@ def _test_func3(a):
132133

133134

134135
class TestBusConfig(unittest.TestCase):
135-
base_config = dict(interface="socketcan", bitrate=500_000)
136-
port_alpha_config = dict(interface="socketcan", bitrate=500_000, port="fail123")
137-
port_to_high_config = dict(interface="socketcan", bitrate=500_000, port="999999")
138-
port_wrong_type_config = dict(interface="socketcan", bitrate=500_000, port=(1234,))
136+
base_config = {"interface": "socketcan", "bitrate": 500_000}
139137

140138
def test_timing_can_use_int(self):
141139
"""
@@ -147,17 +145,69 @@ def test_timing_can_use_int(self):
147145
_create_bus_config({**self.base_config, **timing_conf})
148146
except TypeError as e:
149147
self.fail(e)
148+
149+
def test_port_datatype(self):
150150
self.assertRaises(
151-
ValueError, _create_bus_config, {**self.port_alpha_config, **timing_conf}
151+
ValueError, _create_bus_config, {**self.base_config, "port": "fail123"}
152152
)
153153
self.assertRaises(
154-
ValueError, _create_bus_config, {**self.port_to_high_config, **timing_conf}
154+
ValueError, _create_bus_config, {**self.base_config, "port": "999999"}
155155
)
156156
self.assertRaises(
157-
TypeError,
158-
_create_bus_config,
159-
{**self.port_wrong_type_config, **timing_conf},
157+
TypeError, _create_bus_config, {**self.base_config, "port": (1234,)}
158+
)
159+
160+
try:
161+
_create_bus_config({**self.base_config, "port": "1234"})
162+
except TypeError as e:
163+
self.fail(e)
164+
165+
def test_bit_timing_cfg(self):
166+
can_cfg = _create_bus_config(
167+
{
168+
**self.base_config,
169+
"f_clock": "8000000",
170+
"brp": "1",
171+
"tseg1": "5",
172+
"tseg2": "2",
173+
"sjw": "1",
174+
"nof_samples": "1",
175+
}
176+
)
177+
timing = can_cfg["timing"]
178+
assert isinstance(timing, can.BitTiming)
179+
assert timing.f_clock == 8_000_000
180+
assert timing.brp == 1
181+
assert timing.tseg1 == 5
182+
assert timing.tseg2 == 2
183+
assert timing.sjw == 1
184+
185+
def test_bit_timing_fd_cfg(self):
186+
canfd_cfg = _create_bus_config(
187+
{
188+
**self.base_config,
189+
"f_clock": "80000000",
190+
"nom_brp": "1",
191+
"nom_tseg1": "119",
192+
"nom_tseg2": "40",
193+
"nom_sjw": "40",
194+
"data_brp": "1",
195+
"data_tseg1": "29",
196+
"data_tseg2": "10",
197+
"data_sjw": "10",
198+
}
160199
)
200+
timing = canfd_cfg["timing"]
201+
assert isinstance(timing, can.BitTimingFd)
202+
assert timing.f_clock == 80_000_000
203+
assert timing.nom_brp == 1
204+
assert timing.nom_tseg1 == 119
205+
assert timing.nom_tseg2 == 40
206+
assert timing.nom_sjw == 40
207+
assert timing.data_brp == 1
208+
assert timing.data_tseg1 == 29
209+
assert timing.data_tseg2 == 10
210+
assert timing.data_sjw == 10
161211

162212

163213
class TestChannel2Int(unittest.TestCase):

0 commit comments

Comments
 (0)