Skip to content

Commit ab793f6

Browse files
authored
Merge pull request #887 from hardbyte/release-3.3.4
Release 3.3.4
2 parents 40c1aed + faed6e9 commit ab793f6

File tree

14 files changed

+357
-22
lines changed

14 files changed

+357
-22
lines changed

.travis.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ env:
2525
install:
2626
- if [[ "$TEST_SOCKETCAN" ]]; then sudo bash test/open_vcan.sh ; fi
2727
- travis_retry pip install .[test]
28+
- pip freeze
2829

2930
script:
3031
- |
@@ -52,6 +53,14 @@ jobs:
5253

5354
# Unit Testing Stage
5455

56+
# testing socketcan on Trusty & Python 2.7, since it is not available on Xenial
57+
- stage: test
58+
name: Socketcan
59+
os: linux
60+
dist: trusty
61+
python: "2.7"
62+
sudo: required
63+
env: TEST_SOCKETCAN=TRUE
5564
# testing socketcan on Trusty & Python 3.6, since it is not available on Xenial
5665
- stage: test
5766
name: Socketcan

CHANGELOG.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
Version 3.3.4
2+
====
3+
4+
Last call for Python2 support.
5+
6+
* #916 Vector: Skip channels without CAN support
7+
* #846 Use inter-process mutex to prevent concurrent neoVI device open.
8+
* #901 Fix iteration in Bus.stop_all_periodic_tasks
9+
* #850 Fix socket.error is a deprecated alias of OSError used on Python versions lower than 3.3.
10+
* #879 Updating incorrect api documentation.
11+
* #885 Fix recursion message in Message.__getattr__
12+
* #845 Fix socketcan issue
13+
14+
115
Version 3.3.3
216
====
317

can/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import logging
1010

11-
__version__ = "3.3.3"
11+
__version__ = "3.3.4"
1212

1313
log = logging.getLogger('can')
1414

can/bus.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,21 @@ def _send_periodic_internal(self, msg, period, duration=None):
247247
return task
248248

249249
def stop_all_periodic_tasks(self, remove_tasks=True):
250-
"""Stop sending any messages that were started using bus.send_periodic
250+
"""Stop sending any messages that were started using **bus.send_periodic**.
251+
252+
.. note::
253+
The result is undefined if a single task throws an exception while being stopped.
251254
252255
:param bool remove_tasks:
253256
Stop tracking the stopped tasks.
254257
"""
255258
for task in self._periodic_tasks:
256-
task.stop(remove_task=remove_tasks)
259+
# we cannot let `task.stop()` modify `self._periodic_tasks` while we are
260+
# iterating over it (#634)
261+
task.stop(remove_task=False)
262+
263+
if remove_tasks:
264+
self._periodic_tasks = []
257265

258266
def __iter__(self):
259267
"""Allow iteration on messages as they are received.

can/interfaces/ics_neovi/neovi_bus.py

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
"""
1212

1313
import logging
14+
import os
15+
import tempfile
1416
from collections import deque
1517

1618
from can import Message, CanError, BusABC
@@ -27,6 +29,35 @@
2729
ics = None
2830

2931

32+
try:
33+
from filelock import FileLock
34+
except ImportError as ie:
35+
36+
logger.warning(
37+
"Using ICS NeoVi can backend without the "
38+
"filelock module installed may cause some issues!: %s",
39+
ie,
40+
)
41+
42+
class FileLock:
43+
"""Dummy file lock that does not actually do anything"""
44+
45+
def __init__(self, lock_file, timeout=-1):
46+
self._lock_file = lock_file
47+
self.timeout = timeout
48+
49+
def __enter__(self):
50+
return self
51+
52+
def __exit__(self, exc_type, exc_val, exc_tb):
53+
return None
54+
55+
56+
# Use inter-process mutex to prevent concurrent device open.
57+
# When neoVI server is enabled, there is an issue with concurrent device open.
58+
open_lock = FileLock(os.path.join(tempfile.gettempdir(), "neovi.lock"))
59+
60+
3061
class ICSApiError(CanError):
3162
"""
3263
Indicates an error with the ICS API.
@@ -118,18 +149,28 @@ def __init__(self, channel, can_filters=None, **kwargs):
118149
type_filter = kwargs.get('type_filter')
119150
serial = kwargs.get('serial')
120151
self.dev = self._find_device(type_filter, serial)
121-
ics.open_device(self.dev)
122152

123-
if 'bitrate' in kwargs:
124-
for channel in self.channels:
125-
ics.set_bit_rate(self.dev, kwargs.get('bitrate'), channel)
153+
with open_lock:
154+
ics.open_device(self.dev)
126155

127-
fd = kwargs.get('fd', False)
128-
if fd:
129-
if 'data_bitrate' in kwargs:
156+
try:
157+
if "bitrate" in kwargs:
130158
for channel in self.channels:
131-
ics.set_fd_bit_rate(
132-
self.dev, kwargs.get('data_bitrate'), channel)
159+
ics.set_bit_rate(self.dev, kwargs.get("bitrate"), channel)
160+
161+
if kwargs.get("fd", False):
162+
if "data_bitrate" in kwargs:
163+
for channel in self.channels:
164+
ics.set_fd_bit_rate(
165+
self.dev, kwargs.get("data_bitrate"), channel
166+
)
167+
except ics.RuntimeError as re:
168+
logger.error(re)
169+
err = ICSApiError(*ics.get_last_api_error(self.dev))
170+
try:
171+
self.shutdown()
172+
finally:
173+
raise err
133174

134175
self._use_system_timestamp = bool(
135176
kwargs.get('use_system_timestamp', False)

can/interfaces/ixxat/canlib.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,12 @@ def __init__(self, channel, can_filters=None, **kwargs):
328328
else:
329329
raise VCIDeviceNotFoundError("Unique HW ID {} not connected or not available.".format(UniqueHardwareId))
330330
else:
331-
if (UniqueHardwareId is None) or (self._device_info.UniqueHardwareId.AsChar == bytes(UniqueHardwareId, 'ascii')):
331+
if (UniqueHardwareId is None) or (
332+
self._device_info.UniqueHardwareId.AsChar == UniqueHardwareId.encode("ascii")):
332333
break
333334
else:
334-
log.debug("Ignoring IXXAT with hardware id '%s'.", self._device_info.UniqueHardwareId.AsChar.decode("ascii"))
335+
log.debug("Ignoring IXXAT with hardware id '%s'.",
336+
self._device_info.UniqueHardwareId.AsChar.decode("ascii"))
335337
_canlib.vciEnumDeviceClose(self._device_handle)
336338
_canlib.vciDeviceOpen(ctypes.byref(self._device_info.VciObjectId), ctypes.byref(self._device_handle))
337339
log.info("Using unique HW ID %s", self._device_info.UniqueHardwareId.AsChar)

can/interfaces/socketcan/socketcan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ def _tx_setup(self, message):
363363
)
364364
try:
365365
self.bcm_socket.send(check_header)
366-
except OSError as e:
366+
except (socket.error, OSError) as e:
367367
if e.errno != errno.EINVAL:
368368
raise e
369369
else:

can/interfaces/vector/canlib.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,8 @@ def _detect_available_configs():
387387
channel_configs = get_channel_configs()
388388
LOG.info('Found %d channels', len(channel_configs))
389389
for channel_config in channel_configs:
390+
if not channel_config.channelBusCapabilities & vxlapi.XL_BUS_ACTIVE_CAP_CAN:
391+
continue
390392
LOG.info('Channel index %d: %s',
391393
channel_config.channelIndex,
392394
channel_config.name.decode('ascii'))

can/interfaces/vector/vxlapi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
XL_INTERFACE_VERSION = 3
6464
XL_INTERFACE_VERSION_V4 = 4
6565

66+
XL_BUS_ACTIVE_CAP_CAN = XL_BUS_TYPE_CAN << 16
6667
XL_CHANNEL_FLAG_CANFD_ISO_SUPPORT = 0x80000000
6768

6869
# structure for XL_RECEIVE_MSG, XL_TRANSMIT_MSG

can/message.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ def __getattr__(self, key):
5353
# TODO keep this for a version, in order to not break old code
5454
# this entire method (as well as the _dict attribute in __slots__ and the __setattr__ method)
5555
# can be removed in 4.0
56-
# this method is only called if the attribute was not found elsewhere, like in __slots__
56+
# this method is only called if the attribute was not found elsewhere, like in __slots_
57+
if key not in self.__slots__:
58+
raise AttributeError
5759
try:
5860
warnings.warn("Custom attributes of messages are deprecated and will be removed in 4.0", DeprecationWarning)
5961
return self._dict[key]
@@ -110,6 +112,7 @@ def __init__(self, timestamp=0.0, arbitration_id=0, is_extended_id=None,
110112
if is_extended_id is not None:
111113
self.is_extended_id = is_extended_id
112114
else:
115+
# Default behaviour is to create extended id messages
113116
self.is_extended_id = True if extended_id is None else extended_id
114117

115118
self.is_remote_frame = is_remote_frame

0 commit comments

Comments
 (0)