Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ env:
install:
- if [[ "$TEST_SOCKETCAN" ]]; then sudo bash test/open_vcan.sh ; fi
- travis_retry pip install .[test]
- pip freeze

script:
- |
Expand Down Expand Up @@ -52,6 +53,14 @@ jobs:

# Unit Testing Stage

# testing socketcan on Trusty & Python 2.7, since it is not available on Xenial
- stage: test
name: Socketcan
os: linux
dist: trusty
python: "2.7"
sudo: required
env: TEST_SOCKETCAN=TRUE
# testing socketcan on Trusty & Python 3.6, since it is not available on Xenial
- stage: test
name: Socketcan
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
Version 3.3.4
====

Last call for Python2 support.

* #916 Vector: Skip channels without CAN support
* #846 Use inter-process mutex to prevent concurrent neoVI device open.
* #901 Fix iteration in Bus.stop_all_periodic_tasks
* #850 Fix socket.error is a deprecated alias of OSError used on Python versions lower than 3.3.
* #879 Updating incorrect api documentation.
* #885 Fix recursion message in Message.__getattr__
* #845 Fix socketcan issue


Version 3.3.3
====

Expand Down
2 changes: 1 addition & 1 deletion can/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import logging

__version__ = "3.3.3"
__version__ = "3.3.4"

log = logging.getLogger('can')

Expand Down
12 changes: 10 additions & 2 deletions can/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,21 @@ def _send_periodic_internal(self, msg, period, duration=None):
return task

def stop_all_periodic_tasks(self, remove_tasks=True):
"""Stop sending any messages that were started using bus.send_periodic
"""Stop sending any messages that were started using **bus.send_periodic**.

.. note::
The result is undefined if a single task throws an exception while being stopped.

:param bool remove_tasks:
Stop tracking the stopped tasks.
"""
for task in self._periodic_tasks:
task.stop(remove_task=remove_tasks)
# we cannot let `task.stop()` modify `self._periodic_tasks` while we are
# iterating over it (#634)
task.stop(remove_task=False)

if remove_tasks:
self._periodic_tasks = []

def __iter__(self):
"""Allow iteration on messages as they are received.
Expand Down
59 changes: 50 additions & 9 deletions can/interfaces/ics_neovi/neovi_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"""

import logging
import os
import tempfile
from collections import deque

from can import Message, CanError, BusABC
Expand All @@ -27,6 +29,35 @@
ics = None


try:
from filelock import FileLock
except ImportError as ie:

logger.warning(
"Using ICS NeoVi can backend without the "
"filelock module installed may cause some issues!: %s",
ie,
)

class FileLock:
"""Dummy file lock that does not actually do anything"""

def __init__(self, lock_file, timeout=-1):
self._lock_file = lock_file
self.timeout = timeout

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
return None


# Use inter-process mutex to prevent concurrent device open.
# When neoVI server is enabled, there is an issue with concurrent device open.
open_lock = FileLock(os.path.join(tempfile.gettempdir(), "neovi.lock"))


class ICSApiError(CanError):
"""
Indicates an error with the ICS API.
Expand Down Expand Up @@ -118,18 +149,28 @@ def __init__(self, channel, can_filters=None, **kwargs):
type_filter = kwargs.get('type_filter')
serial = kwargs.get('serial')
self.dev = self._find_device(type_filter, serial)
ics.open_device(self.dev)

if 'bitrate' in kwargs:
for channel in self.channels:
ics.set_bit_rate(self.dev, kwargs.get('bitrate'), channel)
with open_lock:
ics.open_device(self.dev)

fd = kwargs.get('fd', False)
if fd:
if 'data_bitrate' in kwargs:
try:
if "bitrate" in kwargs:
for channel in self.channels:
ics.set_fd_bit_rate(
self.dev, kwargs.get('data_bitrate'), channel)
ics.set_bit_rate(self.dev, kwargs.get("bitrate"), channel)

if kwargs.get("fd", False):
if "data_bitrate" in kwargs:
for channel in self.channels:
ics.set_fd_bit_rate(
self.dev, kwargs.get("data_bitrate"), channel
)
except ics.RuntimeError as re:
logger.error(re)
err = ICSApiError(*ics.get_last_api_error(self.dev))
try:
self.shutdown()
finally:
raise err

self._use_system_timestamp = bool(
kwargs.get('use_system_timestamp', False)
Expand Down
6 changes: 4 additions & 2 deletions can/interfaces/ixxat/canlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,12 @@ def __init__(self, channel, can_filters=None, **kwargs):
else:
raise VCIDeviceNotFoundError("Unique HW ID {} not connected or not available.".format(UniqueHardwareId))
else:
if (UniqueHardwareId is None) or (self._device_info.UniqueHardwareId.AsChar == bytes(UniqueHardwareId, 'ascii')):
if (UniqueHardwareId is None) or (
self._device_info.UniqueHardwareId.AsChar == UniqueHardwareId.encode("ascii")):
break
else:
log.debug("Ignoring IXXAT with hardware id '%s'.", self._device_info.UniqueHardwareId.AsChar.decode("ascii"))
log.debug("Ignoring IXXAT with hardware id '%s'.",
self._device_info.UniqueHardwareId.AsChar.decode("ascii"))
_canlib.vciEnumDeviceClose(self._device_handle)
_canlib.vciDeviceOpen(ctypes.byref(self._device_info.VciObjectId), ctypes.byref(self._device_handle))
log.info("Using unique HW ID %s", self._device_info.UniqueHardwareId.AsChar)
Expand Down
2 changes: 1 addition & 1 deletion can/interfaces/socketcan/socketcan.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def _tx_setup(self, message):
)
try:
self.bcm_socket.send(check_header)
except OSError as e:
except (socket.error, OSError) as e:
if e.errno != errno.EINVAL:
raise e
else:
Expand Down
2 changes: 2 additions & 0 deletions can/interfaces/vector/canlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,8 @@ def _detect_available_configs():
channel_configs = get_channel_configs()
LOG.info('Found %d channels', len(channel_configs))
for channel_config in channel_configs:
if not channel_config.channelBusCapabilities & vxlapi.XL_BUS_ACTIVE_CAP_CAN:
continue
LOG.info('Channel index %d: %s',
channel_config.channelIndex,
channel_config.name.decode('ascii'))
Expand Down
1 change: 1 addition & 0 deletions can/interfaces/vector/vxlapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
XL_INTERFACE_VERSION = 3
XL_INTERFACE_VERSION_V4 = 4

XL_BUS_ACTIVE_CAP_CAN = XL_BUS_TYPE_CAN << 16
XL_CHANNEL_FLAG_CANFD_ISO_SUPPORT = 0x80000000

# structure for XL_RECEIVE_MSG, XL_TRANSMIT_MSG
Expand Down
5 changes: 4 additions & 1 deletion can/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ def __getattr__(self, key):
# TODO keep this for a version, in order to not break old code
# this entire method (as well as the _dict attribute in __slots__ and the __setattr__ method)
# can be removed in 4.0
# this method is only called if the attribute was not found elsewhere, like in __slots__
# this method is only called if the attribute was not found elsewhere, like in __slots_
if key not in self.__slots__:
raise AttributeError
try:
warnings.warn("Custom attributes of messages are deprecated and will be removed in 4.0", DeprecationWarning)
return self._dict[key]
Expand Down Expand Up @@ -110,6 +112,7 @@ def __init__(self, timestamp=0.0, arbitration_id=0, is_extended_id=None,
if is_extended_id is not None:
self.is_extended_id = is_extended_id
else:
# Default behaviour is to create extended id messages
self.is_extended_id = True if extended_id is None else extended_id

self.is_remote_frame = is_remote_frame
Expand Down
2 changes: 1 addition & 1 deletion doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ the **interface** and **channel** before importing from ``can.interfaces``.
can.rc['interface'] = 'socketcan'
can.rc['channel'] = 'vcan0'
can.rc['bitrate'] = 500000
from can.interfaces.interface import Bus
from can.interface import Bus

bus = Bus()

Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from __future__ import absolute_import

import platform
from os import listdir
from os.path import isfile, join
import re
Expand All @@ -26,12 +27,12 @@
# Dependencies
extras_require = {
'serial': ['pyserial~=3.0'],
'neovi': ['python-ics>=2.12']
'neovi': ['python-ics>=2.12', 'filelock']
}

tests_require = [
'mock~=2.0',
'pytest~=4.3',
'pytest~=4.6',
'pytest-timeout~=1.3',
'pytest-cov~=2.8',
# coveragepy==5.0 fails with `Safety level may not be changed inside a transaction`
Expand All @@ -53,7 +54,6 @@
needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv)
pytest_runner = ["pytest-runner"] if needs_pytest else []


setup(
# Description
name="python-can",
Expand Down
Loading