Skip to content

Commit 51e8c4f

Browse files
authored
Fix possible problems in Bus constructor (hardbyte#319)
* small changes to listener tests * fix duplicate constructor arguments * made all interfaces and the __new__ constructor accept the channel attribute only as a positional argument and resolved errors for handling that correctly * change channel argument in __new__ to a keyword argument
1 parent 3da5bd9 commit 51e8c4f

7 files changed

Lines changed: 48 additions & 40 deletions

File tree

can/bus.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class BusABC(object):
2828
channel_info = 'unknown'
2929

3030
@abstractmethod
31-
def __init__(self, channel=None, can_filters=None, **config):
31+
def __init__(self, channel, can_filters=None, **config):
3232
"""Construct and open a CAN bus instance of the specified type.
3333
3434
Subclasses should call though this method with all given parameters

can/interface.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import sys
1313
import importlib
1414
import logging
15+
import re
1516

1617
import can
1718
from .bus import BusABC
@@ -72,14 +73,21 @@ def _get_class_for_interface(interface):
7273

7374
class Bus(BusABC):
7475
"""
75-
Instantiates a CAN Bus of the given `bustype`, falls back to reading a
76+
Instantiates a CAN Bus of the given ``interface``, falls back to reading a
7677
configuration file from default locations.
7778
"""
7879

7980
@staticmethod
80-
def __new__(cls, *args, **config):
81+
def __new__(cls, channel=None, *args, **config):
8182
"""
82-
Takes the same arguments as :class:`can.BusABC.__init__` with the addition of:
83+
Takes the same arguments as :class:`can.BusABC.__init__`.
84+
Some might have a special meaning, see below.
85+
86+
:param channel:
87+
Set to ``None`` to let it be reloved automatically from the default
88+
configuration. That might fail, see below.
89+
90+
Expected type is backend dependent.
8391
8492
:param dict config:
8593
Should contain an ``interface`` key with a valid interface name. If not,
@@ -93,6 +101,8 @@ def __new__(cls, *args, **config):
93101
"""
94102

95103
# figure out the rest of the configuration; this might raise an error
104+
if channel is not None:
105+
config['channel'] = channel
96106
config = load_config(config=config)
97107

98108
# resolve the bus class to use for that interface
@@ -101,12 +111,14 @@ def __new__(cls, *args, **config):
101111
# remove the 'interface' key so it doesn't get passed to the backend
102112
del config['interface']
103113

104-
# make sure the bus can handle this config
114+
# make sure the bus can handle this config format
105115
if 'channel' not in config:
106-
raise ValueError("channel argument missing")
116+
raise ValueError("'channel' argument missing")
117+
else:
118+
channel = config['channel']
119+
del config['channel']
107120

108-
# the channel attribute should be present in **config
109-
return cls(*args, **config)
121+
return cls(channel, *args, **config)
110122

111123

112124
def detect_available_configs(interfaces=None):

can/interfaces/ics_neovi/neovi_bus.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class NeoViBus(BusABC):
8282
https://github.com/intrepidcs/python_ics
8383
"""
8484

85-
def __init__(self, channel=None, can_filters=None, **config):
85+
def __init__(self, channel, can_filters=None, **config):
8686
"""
8787
:param int channel:
8888
The Channel id to create this bus with.

can/interfaces/nican.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ class NicanBus(BusABC):
130130
131131
"""
132132

133-
def __init__(self, channel, can_filters=None, bitrate=None, log_errors=True,
134-
**kwargs):
133+
def __init__(self, channel, can_filters=None, bitrate=None, log_errors=True, **kwargs):
135134
"""
136135
:param str channel:
137136
Name of the object to open (e.g. 'CAN0')

can/interfaces/socketcan/socketcan_ctypes.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ class SocketcanCtypes_Bus(BusABC):
4545
Implements :meth:`can.BusABC._detect_available_configs`.
4646
"""
4747

48-
def __init__(self,
49-
channel='vcan0',
50-
receive_own_messages=False,
51-
*args, **kwargs):
48+
def __init__(self, channel, receive_own_messages=False, *args, **kwargs):
5249
"""
5350
:param str channel:
5451
The can interface name with which to create this bus. An example channel

test/back2back_test.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
TIMEOUT = 0.1
2424

2525
INTERFACE_1 = 'virtual'
26-
CHANNEL_1 = 'vcan0'
26+
CHANNEL_1 = 'virtual_channel_0'
2727
INTERFACE_2 = 'virtual'
28-
CHANNEL_2 = 'vcan0'
28+
CHANNEL_2 = 'virtual_channel_0'
2929

3030

3131
class Back2BackTestCase(unittest.TestCase):
@@ -35,16 +35,16 @@ class Back2BackTestCase(unittest.TestCase):
3535
"""
3636

3737
def setUp(self):
38-
self.bus1 = can.interface.Bus(channel=CHANNEL_1,
39-
bustype=INTERFACE_1,
40-
bitrate=BITRATE,
41-
fd=TEST_CAN_FD,
42-
single_handle=True)
43-
self.bus2 = can.interface.Bus(channel=CHANNEL_2,
44-
bustype=INTERFACE_2,
45-
bitrate=BITRATE,
46-
fd=TEST_CAN_FD,
47-
single_handle=True)
38+
self.bus1 = can.Bus(channel=CHANNEL_1,
39+
bustype=INTERFACE_1,
40+
bitrate=BITRATE,
41+
fd=TEST_CAN_FD,
42+
single_handle=True)
43+
self.bus2 = can.Bus(channel=CHANNEL_2,
44+
bustype=INTERFACE_2,
45+
bitrate=BITRATE,
46+
fd=TEST_CAN_FD,
47+
single_handle=True)
4848

4949
def tearDown(self):
5050
self.bus1.shutdown()
@@ -146,14 +146,14 @@ def setUp(self):
146146
print("testing python-can's socketcan version:",
147147
socketcan_version)
148148

149-
self.bus1 = can.interface.Bus(channel="vcan0",
150-
bustype=socketcan_version,
151-
bitrate=250000,
152-
fd=TEST_CAN_FD)
153-
self.bus2 = can.interface.Bus(channel="vcan0",
154-
bustype=socketcan_version,
155-
bitrate=250000,
156-
fd=TEST_CAN_FD)
149+
self.bus1 = can.Bus(channel="vcan0",
150+
bustype=socketcan_version,
151+
bitrate=250000,
152+
fd=TEST_CAN_FD)
153+
self.bus2 = can.Bus(channel="vcan0",
154+
bustype=socketcan_version,
155+
bitrate=250000,
156+
fd=TEST_CAN_FD)
157157

158158
def tearDown(self):
159159
self.bus1.shutdown()

test/listener_test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55
"""
66

7-
from __future__ import absolute_import
7+
from __future__ import absolute_import, print_function
88

99
from time import sleep
1010
import unittest
@@ -18,12 +18,12 @@
1818

1919
from .data.example_data import generate_message
2020

21-
channel = 'vcan0'
21+
channel = 'virtual_channel_0'
2222
can.rc['interface'] = 'virtual'
2323

2424
logging.getLogger('').setLevel(logging.DEBUG)
2525

26-
# make tests more reproducible
26+
# makes the random number generator deterministic
2727
random.seed(13339115)
2828

2929

@@ -54,7 +54,7 @@ def testClassesImportable(self):
5454

5555
self.assertTrue(hasattr(can, 'LogReader'))
5656

57-
self.assertTrue(hasattr(can.io.player, 'MessageSync'))
57+
self.assertTrue(hasattr(can, 'MessageSync'))
5858

5959

6060
class BusTest(unittest.TestCase):
@@ -106,7 +106,7 @@ def test_filetype_to_instance(extension, klass):
106106
# test file extensions that are not supported
107107
with self.assertRaisesRegexp(NotImplementedError, "xyz_42"):
108108
test_filetype_to_instance("xyz_42", can.Printer)
109-
with self.assertRaises(BaseException):
109+
with self.assertRaises(Exception):
110110
test_filetype_to_instance(None, can.Printer)
111111

112112
def testLoggerTypeResolution(self):

0 commit comments

Comments
 (0)