From 2a30f2519873b80909b1bb6c415e69d184d42501 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Sat, 18 May 2019 08:46:52 +1000 Subject: [PATCH 01/53] update wheel package before deploy --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index b45e17d95..bcd18033a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -88,6 +88,8 @@ jobs: - stage: deploy name: "PyPi Deployment" python: "3.7" + before_install: + - travis_retry pip install -U wheel setuptools deploy: provider: pypi user: hardbyte From ad3f830d6057d037a80f24e5ba25a9c3cf794529 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Sat, 18 May 2019 09:14:08 +1000 Subject: [PATCH 02/53] Minor version bump and doc update --- can/__init__.py | 2 +- doc/development.rst | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/can/__init__.py b/can/__init__.py index a612363ae..4057322dd 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.2.0" +__version__ = "3.2.1-alpha.2" log = logging.getLogger('can') diff --git a/doc/development.rst b/doc/development.rst index 602e4e347..fdb5bcf25 100644 --- a/doc/development.rst +++ b/doc/development.rst @@ -73,8 +73,10 @@ The modules in ``python-can`` are: +---------------------------------+------------------------------------------------------+ -Creating a new Release ----------------------- +Process for creating a new Release +---------------------------------- + +Note many of these steps are carried out by the CI system on creating a tag in git. - Release from the ``master`` branch. - Update the library version in ``__init__.py`` using `semantic versioning `__. @@ -84,8 +86,9 @@ Creating a new Release - For larger changes update ``doc/history.rst``. - Sanity check that documentation has stayed inline with code. - Create a temporary virtual environment. Run ``python setup.py install`` and ``python setup.py test``. +- Ensure the ``setuptools`` and ``wheel`` tools are up to date: ``pip install -U setuptools wheel``. - Create and upload the distribution: ``python setup.py sdist bdist_wheel``. -- Sign the packages with gpg ``gpg --detach-sign -a dist/python_can-X.Y.Z-py3-none-any.whl``. +- [Optionally] Sign the packages with gpg ``gpg --detach-sign -a dist/python_can-X.Y.Z-py3-none-any.whl``. - Upload with twine ``twine upload dist/python-can-X.Y.Z*``. - In a new virtual env check that the package can be installed with pip: ``pip install python-can==X.Y.Z``. - Create a new tag in the repository. From a91ca251a63c7eb70dbc2c2109bed9faad16e4ab Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Tue, 25 Jun 2019 09:45:42 +1000 Subject: [PATCH 03/53] Minor version bump to v3.2.1 --- can/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/__init__.py b/can/__init__.py index 4057322dd..d2ca9208c 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.2.1-alpha.2" +__version__ = "3.2.1" log = logging.getLogger('can') From 667278ece35edf6460996e6f9186db59d8692ccb Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Tue, 25 Jun 2019 09:48:03 +1000 Subject: [PATCH 04/53] Update changelog for v3.2.1 --- CHANGELOG.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2f50dca8d..a69ddf91c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,12 @@ -Version 3.2.0 +Version 3.2.1 ==== +* CAN FD 64 frame support to blf reader +* Minor fix to use latest tools when building wheels on travis. +* Updates links in documentation. + +Version 3.2.0 +==== Major features -------------- From a0f0ea750fe36df01261486e9b11db5e9a7a3f9a Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 27 Jun 2019 11:11:36 +1000 Subject: [PATCH 05/53] Update version to v3.3.0 Add notes to changelog. --- CHANGELOG.txt | 7 ++++--- can/__init__.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a69ddf91c..8d15e2170 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,9 +1,10 @@ -Version 3.2.1 +Version 3.3.0 ==== -* CAN FD 64 frame support to blf reader +* Adding CAN FD 64 frame support to blf reader +* Updates to installation instructions +* Clean up bits generator in PCAN interface #588 * Minor fix to use latest tools when building wheels on travis. -* Updates links in documentation. Version 3.2.0 ==== diff --git a/can/__init__.py b/can/__init__.py index d2ca9208c..10245b220 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.2.1" +__version__ = "3.3.0" log = logging.getLogger('can') From 591967c45233abf906950bbd59af914550007815 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Tue, 23 Jul 2019 21:50:56 +1000 Subject: [PATCH 06/53] Backport pytest-runner fix from #633 --- setup.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c600b7215..27121b61a 100644 --- a/setup.py +++ b/setup.py @@ -11,6 +11,7 @@ from os.path import isfile, join import re import logging +import sys from setuptools import setup, find_packages logging.basicConfig(level=logging.WARNING) @@ -41,6 +42,14 @@ extras_require['test'] = tests_require +# Check for 'pytest-runner' only if setup.py was invoked with 'test'. +# This optimizes setup.py for cases when pytest-runner is not needed, +# using the approach that is suggested upstream. +# +# See https://pypi.org/project/pytest-runner/#conditional-requirement +needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) +pytest_runner = ["pytest-runner"] if needs_pytest else [] + setup( # Description @@ -104,7 +113,7 @@ 'typing;python_version<"3.5"', 'windows-curses;platform_system=="Windows"', ], - setup_requires=["pytest-runner"], + setup_requires=pytest_runner, extras_require=extras_require, tests_require=tests_require ) From 1f0fb8b680a24e727a6995949c4f41d6251abd56 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Tue, 23 Jul 2019 21:52:59 +1000 Subject: [PATCH 07/53] Bump version to 3.3.1 --- CHANGELOG.txt | 5 +++++ can/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8d15e2170..5c492d19f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,8 @@ +Version 3.3.1 +==== + +Minor fix to setup.py to only require pytest-runner when necessary. + Version 3.3.0 ==== diff --git a/can/__init__.py b/can/__init__.py index 10245b220..e00e7dd53 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.0" +__version__ = "3.3.1" log = logging.getLogger('can') From 9bf4c0d8108cdbb5e9b1e3fd91126363f237452b Mon Sep 17 00:00:00 2001 From: Colin Rafferty Date: Mon, 29 Jul 2019 10:19:19 -0400 Subject: [PATCH 08/53] Do not incorrectly reset CANMsg.MSGTYPE on remote frame. In `PcanBus.send()`, we initially set `msgType` based on all the flags of `msg`, including RTR. In the if/else for `self.fd`, we are incorrectly resetting it if rtr. We should not, and so we are no longer doing it. --- can/interfaces/pcan/pcan.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 864308bab..f062d62aa 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -385,9 +385,7 @@ def send(self, msg, timeout=None): CANMsg.MSGTYPE = msgType # if a remote frame will be sent, data bytes are not important. - if msg.is_remote_frame: - CANMsg.MSGTYPE = msgType.value | PCAN_MESSAGE_RTR.value - else: + if not msg.is_remote_frame: # copy data for i in range(CANMsg.LEN): CANMsg.DATA[i] = msg.data[i] From 4405bc5d3c815f6f5535ba9360acb90936a04a76 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 15 Aug 2019 21:00:39 +1000 Subject: [PATCH 09/53] Bump version to 3.3.2 --- CHANGELOG.txt | 5 +++++ can/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5c492d19f..933318a66 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,8 @@ +Version 3.3.2 +==== + +Minor bug fix release addressing issue in PCAN RTR. + Version 3.3.1 ==== diff --git a/can/__init__.py b/can/__init__.py index e00e7dd53..44aa90e4a 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.1" +__version__ = "3.3.2" log = logging.getLogger('can') From 1d4c6a78265412a303df807babefcd5e29577a24 Mon Sep 17 00:00:00 2001 From: Colin Rafferty Date: Mon, 29 Jul 2019 10:19:19 -0400 Subject: [PATCH 10/53] Do not incorrectly reset CANMsg.MSGTYPE on remote frame. In `PcanBus.send()`, we initially set `msgType` based on all the flags of `msg`, including RTR. In the if/else for `self.fd`, we are incorrectly resetting it if rtr. We should not, and so we are no longer doing it. --- can/interfaces/pcan/pcan.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 864308bab..f062d62aa 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -385,9 +385,7 @@ def send(self, msg, timeout=None): CANMsg.MSGTYPE = msgType # if a remote frame will be sent, data bytes are not important. - if msg.is_remote_frame: - CANMsg.MSGTYPE = msgType.value | PCAN_MESSAGE_RTR.value - else: + if not msg.is_remote_frame: # copy data for i in range(CANMsg.LEN): CANMsg.DATA[i] = msg.data[i] From 29a235bc6e51002b243126b778bd9bc318652be9 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 15 Aug 2019 21:00:39 +1000 Subject: [PATCH 11/53] Bump version to 3.3.2 --- CHANGELOG.txt | 5 +++++ can/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5c492d19f..933318a66 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,8 @@ +Version 3.3.2 +==== + +Minor bug fix release addressing issue in PCAN RTR. + Version 3.3.1 ==== diff --git a/can/__init__.py b/can/__init__.py index e00e7dd53..44aa90e4a 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.1" +__version__ = "3.3.2" log = logging.getLogger('can') From fbe11048f5c0a5801ed330a880d7709bb75d814f Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 24 Oct 2019 21:23:00 +1100 Subject: [PATCH 12/53] Backport #713 - RTR bug fix in canutils.py --- can/io/canutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/io/canutils.py b/can/io/canutils.py index 69c0227a4..b5cec0cb5 100644 --- a/can/io/canutils.py +++ b/can/io/canutils.py @@ -62,7 +62,7 @@ def __iter__(self): else: isExtended = False canId = int(canId, 16) - + dataBin = None if data and data[0].lower() == 'r': isRemoteFrame = True if len(data) > 1: From 7505d21aa032735a25e2b12e9ac95500c21e6968 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 24 Oct 2019 21:42:07 +1100 Subject: [PATCH 13/53] Bump version to 3.3.3 --- can/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/__init__.py b/can/__init__.py index 44aa90e4a..481dc29e3 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.2" +__version__ = "3.3.3" log = logging.getLogger('can') From f69b162766e014ee9a56671092075a0d73e1542d Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Sun, 29 Dec 2019 09:19:17 +1300 Subject: [PATCH 14/53] Backport fix to ASCReader #701 Skip J1939TP messages --- can/io/asc.py | 8 ++++++-- test/data/logfile.asc | 46 ++++++++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/can/io/asc.py b/can/io/asc.py index 3ed50f04a..4f1115e98 100644 --- a/can/io/asc.py +++ b/can/io/asc.py @@ -28,7 +28,8 @@ class ASCReader(BaseIOHandler): """ - Iterator of CAN messages from a ASC logging file. + Iterator of CAN messages from a ASC logging file. Meta data (comments, + bus statistics, J1939 Transport Protocol messages) is ignored. TODO: turn relative timestamps back to absolute form """ @@ -77,7 +78,10 @@ def __iter__(self): channel=channel) yield msg - elif not isinstance(channel, int) or dummy.strip()[0:10].lower() == 'statistic:': + elif (not isinstance(channel, int) + or dummy.strip()[0:10].lower() == 'statistic:' + or dummy.split(None, 1)[0] == "J1939TP" + ): pass elif dummy[-1:].lower() == 'r': diff --git a/test/data/logfile.asc b/test/data/logfile.asc index 4b7c64363..b855811a2 100644 --- a/test/data/logfile.asc +++ b/test/data/logfile.asc @@ -1,18 +1,28 @@ -date Sam Sep 30 15:06:13.191 2017 -base hex timestamps absolute -internal events logged -// version 9.0.0 -Begin Triggerblock Sam Sep 30 15:06:13.191 2017 - 0.000000 Start of measurement - 0.015991 CAN 1 Status:chip status error passive - TxErr: 132 RxErr: 0 - 0.015991 CAN 2 Status:chip status error active - 1.015991 1 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% - 1.015991 2 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% - 2.015992 1 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% - 17.876707 CAN 1 Status:chip status error passive - TxErr: 131 RxErr: 0 - 17.876708 1 6F9 Rx d 8 05 0C 00 00 00 00 00 00 Length = 240015 BitCount = 124 ID = 1785 - 17.876976 1 6F8 Rx d 8 FF 00 0C FE 00 00 00 00 Length = 239910 BitCount = 124 ID = 1784 - 18.015997 1 Statistic: D 2 R 0 XD 0 XR 0 E 0 O 0 B 0.04% - 113.016026 1 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% - 113.016026 2 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% -End TriggerBlock +date Sam Sep 30 15:06:13.191 2017 +base hex timestamps absolute +internal events logged +// version 9.0.0 +Begin Triggerblock Sam Sep 30 15:06:13.191 2017 + 0.000000 Start of measurement + 0.015991 CAN 1 Status:chip status error passive - TxErr: 132 RxErr: 0 + 0.015991 CAN 2 Status:chip status error active + 1.015991 1 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% + 1.015991 2 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% + 2.015992 1 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% + 3.098426 1 18EBFF00x Rx d 8 01 A0 0F A6 60 3B D1 40 Length = 273910 BitCount = 141 ID = 418119424x + 3.148421 1 18EBFF00x Rx d 8 02 1F DE 80 25 DF C0 2B Length = 271910 BitCount = 140 ID = 418119424x + 3.197693 1 18EBFF00x Rx d 8 03 E1 00 4B FF FF 3C 0F Length = 283910 BitCount = 146 ID = 418119424x + 3.248765 1 18EBFF00x Rx d 8 04 00 4B FF FF FF FF FF Length = 283910 BitCount = 146 ID = 418119424x + 3.297743 1 J1939TP FEE3p 6 0 0 - Rx d 23 A0 0F A6 60 3B D1 40 1F DE 80 25 DF C0 2B E1 00 4B FF FF 3C 0F 00 4B FF FF FF FF FF FF FF FF FF FF FF FF + 17.876707 CAN 1 Status:chip status error passive - TxErr: 131 RxErr: 0 + 17.876708 1 6F9 Rx d 8 05 0C 00 00 00 00 00 00 Length = 240015 BitCount = 124 ID = 1785 + 17.876976 1 6F8 Rx d 8 FF 00 0C FE 00 00 00 00 Length = 239910 BitCount = 124 ID = 1784 + 18.015997 1 Statistic: D 2 R 0 XD 0 XR 0 E 0 O 0 B 0.04% + 20.105214 2 18EBFF00x Rx d 8 01 A0 0F A6 60 3B D1 40 Length = 273925 BitCount = 141 ID = 418119424x + 20.155119 2 18EBFF00x Rx d 8 02 1F DE 80 25 DF C0 2B Length = 272152 BitCount = 140 ID = 418119424x + 20.204671 2 18EBFF00x Rx d 8 03 E1 00 4B FF FF 3C 0F Length = 283910 BitCount = 146 ID = 418119424x + 20.248887 2 18EBFF00x Rx d 8 04 00 4B FF FF FF FF FF Length = 283925 BitCount = 146 ID = 418119424x + 20.305233 2 J1939TP FEE3p 6 0 0 - Rx d 23 A0 0F A6 60 3B D1 40 1F DE 80 25 DF C0 2B E1 00 4B FF FF 3C 0F 00 4B FF FF FF FF FF FF FF FF FF FF FF FF + 113.016026 1 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% + 113.016026 2 Statistic: D 0 R 0 XD 0 XR 0 E 0 O 0 B 0.00% +End TriggerBlock From 250d290792d865dd06e422ed1a97b6b391062a20 Mon Sep 17 00:00:00 2001 From: Christian Sandberg Date: Sun, 29 Dec 2019 09:24:50 +1300 Subject: [PATCH 15/53] Backport fix to can.player #690 Expose options to send or skip error frame messages --- can/player.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/can/player.py b/can/player.py index c712f1714..2b1864a36 100644 --- a/can/player.py +++ b/can/player.py @@ -47,6 +47,12 @@ def main(): help='''Ignore timestamps (send all frames immediately with minimum gap between frames)''', action='store_false') + parser.add_argument( + "--error-frames", + help="Also send error frames to the interface.", + action="store_true", + ) + parser.add_argument('-g', '--gap', type=float, help=''' minimum time between replayed frames''', default=0.0001) parser.add_argument('-s', '--skip', type=float, default=60*60*24, @@ -68,6 +74,8 @@ def main(): logging_level_name = ['critical', 'error', 'warning', 'info', 'debug', 'subdebug'][min(5, verbosity)] can.set_logging_level(logging_level_name) + error_frames = results.error_frames + config = {"single_handle": True} if results.interface: config["interface"] = results.interface @@ -84,6 +92,8 @@ def main(): try: for m in in_sync: + if m.is_error_frame and not error_frames: + continue if verbosity >= 3: print(m) bus.send(m) From 0e3812d218f03947d5fc7db59c61981b53e5b6e1 Mon Sep 17 00:00:00 2001 From: Karl Date: Fri, 12 Jul 2019 05:00:11 +1200 Subject: [PATCH 16/53] Backport socketcan fix: Read the BCM status before creating a Task Currently bus.send_periodic blindly wraps the BCM socket API, and sends a BCM operation with the TX_SETUP opcode. However, the semantics that the kernel driver provides are an "upsert". As such, when one attempts to create two Tasks with the same CAN Arbitration ID, it ends up silently modifying the periodic messages, which is contrary to what our API implies. This fixes the problem by first sending a TX_READ opcode with the CAN Arbitration ID that we wish to create. The kernel driver will return -EINVAL if a periodic transmission with the given Arbitration ID does not exist. If this is the case, then we can continue creating the Task, otherwise we error and notify the user. #605 --- can/interfaces/socketcan/constants.py | 5 ++-- can/interfaces/socketcan/socketcan.py | 35 +++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/can/interfaces/socketcan/constants.py b/can/interfaces/socketcan/constants.py index b56eaae64..1fa6fdf72 100644 --- a/can/interfaces/socketcan/constants.py +++ b/can/interfaces/socketcan/constants.py @@ -9,8 +9,9 @@ CAN_EFF_FLAG = 0x80000000 # BCM opcodes -CAN_BCM_TX_SETUP = 1 -CAN_BCM_TX_DELETE = 2 +CAN_BCM_TX_SETUP = 1 +CAN_BCM_TX_DELETE = 2 +CAN_BCM_TX_READ = 3 # BCM flags SETTIMER = 0x0001 diff --git a/can/interfaces/socketcan/socketcan.py b/can/interfaces/socketcan/socketcan.py index 633c87b22..b69b2636f 100644 --- a/can/interfaces/socketcan/socketcan.py +++ b/can/interfaces/socketcan/socketcan.py @@ -346,8 +346,39 @@ def _tx_setup(self, message): count = 0 ival1 = 0 ival2 = self.period - header = build_bcm_transmit_header(self.can_id_with_flags, count, ival1, - ival2, self.flags) + + # First do a TX_READ before creating a new task, and check if we get + # EINVAL. If so, then we are referring to a CAN message with the same + # ID + check_header = build_bcm_header( + opcode=CAN_BCM_TX_READ, + flags=0, + count=0, + ival1_seconds=0, + ival1_usec=0, + ival2_seconds=0, + ival2_usec=0, + can_id=self.can_id_with_flags, + nframes=0, + ) + try: + self.bcm_socket.send(check_header) + except OSError as e: + assert e.errno == errno.EINVAL + else: + raise ValueError( + "A periodic Task for Arbitration ID {} has already been created".format( + message.arbitration_id + ) + ) + + header = build_bcm_transmit_header( + self.can_id_with_flags, + count, + ival1, + ival2, + self.flags + ) frame = build_can_frame(message) log.debug("Sending BCM command") send_bcm(self.bcm_socket, header + frame) From cee9d642cc57b64ad62914391cab40cd14de87e6 Mon Sep 17 00:00:00 2001 From: Karl Date: Sat, 13 Jul 2019 14:38:59 -0700 Subject: [PATCH 17/53] Raise Exception instead of using assert on EINVAL --- can/interfaces/socketcan/socketcan.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/can/interfaces/socketcan/socketcan.py b/can/interfaces/socketcan/socketcan.py index b69b2636f..b671f926a 100644 --- a/can/interfaces/socketcan/socketcan.py +++ b/can/interfaces/socketcan/socketcan.py @@ -364,7 +364,8 @@ def _tx_setup(self, message): try: self.bcm_socket.send(check_header) except OSError as e: - assert e.errno == errno.EINVAL + if e.errno != errno.EINVAL: + raise e else: raise ValueError( "A periodic Task for Arbitration ID {} has already been created".format( From a479d7f2fb609f21d2e15439ce595af38a1103ab Mon Sep 17 00:00:00 2001 From: nick black Date: Sun, 9 Jun 2019 03:32:42 +1200 Subject: [PATCH 18/53] Backport canalystii fix to init #617 Pass kwargs through to BusABC's initializer. Doesn't backport changing baud to bitrate to avoid changing the API --- can/interfaces/canalystii.py | 6 ++++-- doc/configuration.rst | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/can/interfaces/canalystii.py b/can/interfaces/canalystii.py index 35f240a66..6a2fd51a9 100644 --- a/can/interfaces/canalystii.py +++ b/can/interfaces/canalystii.py @@ -66,7 +66,9 @@ class VCI_CAN_OBJ(Structure): class CANalystIIBus(BusABC): - def __init__(self, channel, device=0, baud=None, Timing0=None, Timing1=None, can_filters=None): + def __init__( + self, channel, device=0, baud=None, Timing0=None, Timing1=None, can_filters=None, **kwargs + ): """ :param channel: channel number @@ -76,7 +78,7 @@ def __init__(self, channel, device=0, baud=None, Timing0=None, Timing1=None, can :param Timing1: :param can_filters: filters for packet """ - super(CANalystIIBus, self).__init__(channel, can_filters) + super(CANalystIIBus, self).__init__(channel, can_filters, **kwargs) if isinstance(channel, (list, tuple)): self.channels = channel diff --git a/doc/configuration.rst b/doc/configuration.rst index dda2ace2a..142e816da 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -126,3 +126,7 @@ Lookup table of interface names: +---------------------+-------------------------------------+ | ``"virtual"`` | :doc:`interfaces/virtual` | +---------------------+-------------------------------------+ +| ``"canalystii"`` | :doc:`interfaces/canalystii` | ++---------------------+-------------------------------------+ +| ``"systec"`` | :doc:`interfaces/systec` | ++---------------------+-------------------------------------+ From 1587c3639bbb5c1227ebd7b35139934f24e5c13a Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 23 Dec 2019 22:18:19 +1300 Subject: [PATCH 19/53] Backport updating test deps (#745) * pin versions of testing dependencies including coverage --- setup.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 27121b61a..29c7478f7 100644 --- a/setup.py +++ b/setup.py @@ -33,11 +33,14 @@ 'mock~=2.0', 'pytest~=4.3', 'pytest-timeout~=1.3', - 'pytest-cov~=2.6', + 'pytest-cov~=2.8', + # coveragepy==5.0 fails with `Safety level may not be changed inside a transaction` + # on python 3.6 on MACOS + 'coverage<5', 'codecov~=2.0', 'future', 'six', - 'hypothesis' + 'hypothesis~=4.56' ] + extras_require['serial'] extras_require['test'] = tests_require From f9198f3f30c2a9c57d44d6e1f4b61a50ac5b3042 Mon Sep 17 00:00:00 2001 From: chrisoro <4160557+chrisoro@users.noreply.github.com> Date: Tue, 24 Dec 2019 07:16:31 +0100 Subject: [PATCH 20/53] Exclude all test packages, not just toplevel (#740) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 29c7478f7..e5b05e8dc 100644 --- a/setup.py +++ b/setup.py @@ -90,7 +90,7 @@ # Code version=version, - packages=find_packages(exclude=["test", "doc", "scripts", "examples"]), + packages=find_packages(exclude=["test*", "doc", "scripts", "examples"]), scripts=list(filter(isfile, (join("scripts/", f) for f in listdir("scripts/")))), # Author From 6d44fd0ecac17cee7085ad7019ea7f123bf78bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Sch=C3=A4rlund?= Date: Sat, 22 Jun 2019 10:14:05 +0200 Subject: [PATCH 21/53] Avoid padding CAN_FD_MESSAGE_64 objects to 4 bytes --- can/io/blf.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/can/io/blf.py b/can/io/blf.py index d162fdebc..a17a6b6a7 100644 --- a/can/io/blf.py +++ b/can/io/blf.py @@ -195,8 +195,13 @@ def __iter__(self): raise BLFParseError() obj_size = header[3] + obj_type = header[4] # Calculate position of next object - next_pos = pos + obj_size + (obj_size % 4) + if obj_size % 4 and obj_type != CAN_FD_MESSAGE_64: + next_pos = pos + obj_size + (obj_size % 4) + else: + # CAN_FD_MESSAGE_64 objects are not padded to 4 bytes. + next_pos = pos + obj_size if next_pos > len(data): # Object continues in next log container break @@ -222,7 +227,6 @@ def __iter__(self): factor = 1e-9 timestamp = timestamp * factor + self.start_timestamp - obj_type = header[4] # Both CAN message types have the same starting content if obj_type in (CAN_MESSAGE, CAN_MESSAGE2): (channel, flags, dlc, can_id, From ba4c6761286150c5ea3de39a74c73e076b293ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Sch=C3=A4rlund?= Date: Sun, 23 Jun 2019 13:55:21 +0200 Subject: [PATCH 22/53] Refactor to save calculations --- can/io/blf.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/can/io/blf.py b/can/io/blf.py index a17a6b6a7..91f2945c9 100644 --- a/can/io/blf.py +++ b/can/io/blf.py @@ -197,11 +197,9 @@ def __iter__(self): obj_size = header[3] obj_type = header[4] # Calculate position of next object - if obj_size % 4 and obj_type != CAN_FD_MESSAGE_64: - next_pos = pos + obj_size + (obj_size % 4) - else: - # CAN_FD_MESSAGE_64 objects are not padded to 4 bytes. - next_pos = pos + obj_size + next_pos = pos + obj_size + if obj_type != CAN_FD_MESSAGE_64: + next_pos += obj_size % 4 if next_pos > len(data): # Object continues in next log container break From 9fb3c23f3b167630ae3ae2ab2137c496c7ec2def Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 17 Feb 2020 22:12:50 +1300 Subject: [PATCH 23/53] Backport accepting bitrate instead of baud in CANalystIIBus Backported from #617 --- can/interfaces/canalystii.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/can/interfaces/canalystii.py b/can/interfaces/canalystii.py index 6a2fd51a9..859fdca9a 100644 --- a/can/interfaces/canalystii.py +++ b/can/interfaces/canalystii.py @@ -1,3 +1,4 @@ +import warnings from ctypes import * import logging import platform @@ -67,13 +68,13 @@ class VCI_CAN_OBJ(Structure): class CANalystIIBus(BusABC): def __init__( - self, channel, device=0, baud=None, Timing0=None, Timing1=None, can_filters=None, **kwargs + self, channel, device=0, bitrate=None, baud=None, Timing0=None, Timing1=None, can_filters=None, **kwargs ): """ :param channel: channel number :param device: device number - :param baud: baud rate + :param baud: baud rate. Renamed to bitrate in next release. :param Timing0: customize the timing register if baudrate is not specified :param Timing1: :param can_filters: filters for packet @@ -93,10 +94,15 @@ def __init__( self.channel_info = "CANalyst-II: device {}, channels {}".format(self.device, self.channels) if baud is not None: + warnings.warn('Argument baud will be deprecated in version 4, use bitrate instead', + PendingDeprecationWarning) + bitrate = baud + + if bitrate is not None: try: - Timing0, Timing1 = TIMING_DICT[baud] + Timing0, Timing1 = TIMING_DICT[bitrate] except KeyError: - raise ValueError("Baudrate is not supported") + raise ValueError("Bitrate is not supported") if Timing0 is None or Timing1 is None: raise ValueError("Timing registers are not set") From 6041bbcf37a588d0e7e6d96578ebee1d56db2f3d Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Sun, 19 Apr 2020 12:17:35 +1200 Subject: [PATCH 24/53] Add changelog for release 3.3.3 and append alpha 0 tag for testing. --- CHANGELOG.txt | 16 ++++++++++++++++ can/__init__.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 933318a66..c22c5bad6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,19 @@ +Version 3.3.3 +==== + +Backported fixes from Python 3 only 4.x development. + +* Exclude test packages from distribution. #740 +* RTR crash fix in canutils log reader parsing RTR frames. #713 +* Skip J1939 messages in ASC Reader. #701 +* Exposes a configuration option to allow the CAN message player to send error frames + (and sets the default to not send error frames). #690 +* Fixes the semantics provided by periodic tasks in SocketCAN interface. #638 +* Avoid padding CAN_FD_MESSAGE_64 objects to 4 bytes. #628 +* Fixes the broken CANalyst-II interface. #617 +* Socketcan BCM status fix. #605 + + Version 3.3.2 ==== diff --git a/can/__init__.py b/can/__init__.py index 481dc29e3..c467396c8 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.3" +__version__ = "3.3.3-alpha.0" log = logging.getLogger('can') From e45c8cc93202ad19d4024daf066867b94adcbb83 Mon Sep 17 00:00:00 2001 From: Karl Date: Sun, 19 Apr 2020 19:30:15 +1200 Subject: [PATCH 25/53] Fix Vector CANlib treatment of empty app name In Python 2, the str type was used for text and bytes, whereas in Python 3, these are separate and incompatible types. This broke instantiation of a VectorBus when the app_name parameter in __init__ was set to None. This correctly sets it to a bytes object. Fixes #796 --- can/interfaces/vector/canlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index 251b9fa56..65af0147b 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -87,7 +87,7 @@ def __init__(self, channel, can_filters=None, poll_interval=0.01, else: # Assume comma separated string of channels self.channels = [int(ch.strip()) for ch in channel.split(',')] - self._app_name = app_name.encode() if app_name is not None else '' + self._app_name = app_name.encode() if app_name is not None else b'' self.channel_info = 'Application %s: %s' % ( app_name, ', '.join('CAN %d' % (ch + 1) for ch in self.channels)) From e36e37612131001dcd8398a55f55b4a5714646c5 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 20 Apr 2020 09:49:49 +1200 Subject: [PATCH 26/53] 3.3.3-a.1 --- can/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/__init__.py b/can/__init__.py index c467396c8..8aa111be7 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.3-alpha.0" +__version__ = "3.3.3-alpha.1" log = logging.getLogger('can') From 2ae3de5efa7254bb4132ec3af332a63c81726de9 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Tue, 21 Apr 2020 08:52:15 +1200 Subject: [PATCH 27/53] Backport fix for handling empty csv file #771 Bump pre-release version to 3.3.3-a.2 --- can/__init__.py | 2 +- can/io/csv.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/can/__init__.py b/can/__init__.py index 8aa111be7..43996ff4f 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.3-alpha.1" +__version__ = "3.3.3-alpha.2" log = logging.getLogger('can') diff --git a/can/io/csv.py b/can/io/csv.py index 92f841f8f..32e34d0fb 100644 --- a/can/io/csv.py +++ b/can/io/csv.py @@ -91,7 +91,11 @@ def __init__(self, file): def __iter__(self): # skip the header line - next(self.file) + try: + next(self.file) + except StopIteration: + # don't crash on a file with only a header + return for line in self.file: From 5180591a2721c8a26b8adc1fb1e43f1adcdcfd49 Mon Sep 17 00:00:00 2001 From: pierreluctg Date: Mon, 23 Mar 2020 16:11:25 -0400 Subject: [PATCH 28/53] Backport caching msg.data value in neovi interface (#798) --- can/interfaces/ics_neovi/neovi_bus.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/can/interfaces/ics_neovi/neovi_bus.py b/can/interfaces/ics_neovi/neovi_bus.py index 4baee6177..530d7c524 100644 --- a/can/interfaces/ics_neovi/neovi_bus.py +++ b/can/interfaces/ics_neovi/neovi_bus.py @@ -334,11 +334,12 @@ def send(self, msg, timeout=None): flag3 |= ics.SPY_STATUS3_CANFD_ESI message.ArbIDOrHeader = msg.arbitration_id - message.NumberBytesData = len(msg.data) - message.Data = tuple(msg.data[:8]) - if msg.is_fd and len(msg.data) > 8: + msg_data = msg.data + message.NumberBytesData = len(msg_data) + message.Data = tuple(msg_data[:8]) + if msg.is_fd and len(msg_data) > 8: message.ExtraDataPtrEnabled = 1 - message.ExtraDataPtr = tuple(msg.data) + message.ExtraDataPtr = tuple(msg_data) message.StatusBitField = flag0 message.StatusBitField2 = 0 message.StatusBitField3 = flag3 From 390ff1cd8cf2b766a38215711d5bba5f2ebdb07f Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Tue, 21 Apr 2020 08:58:51 +1200 Subject: [PATCH 29/53] Update changelog with more backported fixes for 3.3.3 release --- CHANGELOG.txt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index c22c5bad6..3399feb65 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,15 +3,18 @@ Version 3.3.3 Backported fixes from Python 3 only 4.x development. -* Exclude test packages from distribution. #740 -* RTR crash fix in canutils log reader parsing RTR frames. #713 -* Skip J1939 messages in ASC Reader. #701 -* Exposes a configuration option to allow the CAN message player to send error frames - (and sets the default to not send error frames). #690 -* Fixes the semantics provided by periodic tasks in SocketCAN interface. #638 -* Avoid padding CAN_FD_MESSAGE_64 objects to 4 bytes. #628 -* Fixes the broken CANalyst-II interface. #617 -* Socketcan BCM status fix. #605 +* #798 Backport caching msg.data value in neovi interface +* #796 Fix Vector CANlib treatment of empty app name +* #771 Handle empty CSV file +* #740 Exclude test packages from distribution. +* #713 RTR crash fix in canutils log reader parsing RTR frames. +* #701 Skip J1939 messages in ASC Reader. +* #690 Exposes a configuration option to allow the CAN message player to send error frames + (and sets the default to not send error frames). +* #638 Fixes the semantics provided by periodic tasks in SocketCAN interface. +* #628 Avoid padding CAN_FD_MESSAGE_64 objects to 4 bytes. +* #617 Fixes the broken CANalyst-II interface. +* #605 Socketcan BCM status fix. Version 3.3.2 From 16d89bc8fc210fd423d34c4dfbb9952b92418722 Mon Sep 17 00:00:00 2001 From: Syed Date: Fri, 31 Jan 2020 04:53:11 +1300 Subject: [PATCH 30/53] Backport #741 - Fixing ASCII reader unable to read FD frames --- can/io/asc.py | 35 +++++++++++++++++++++++++++++------ test/logformats_test.py | 2 +- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/can/io/asc.py b/can/io/asc.py index 4f1115e98..60f845bd0 100644 --- a/can/io/asc.py +++ b/can/io/asc.py @@ -59,9 +59,13 @@ def __iter__(self): temp = line.strip() if not temp or not temp[0].isdigit(): continue - + is_fd = False try: timestamp, channel, dummy = temp.split(None, 2) # , frameType, dlc, frameData + if channel == "CANFD": + timestamp, _, channel, _, dummy = temp.split(None, 4) + is_fd = True + except ValueError: # we parsed an empty comment continue @@ -95,16 +99,32 @@ def __iter__(self): yield msg else: + brs = None + esi = None + data_length = 0 try: - # this only works if dlc > 0 and thus data is availabe - can_id_str, _, _, dlc, data = dummy.split(None, 4) + # this only works if dlc > 0 and thus data is available + if not is_fd: + can_id_str, _, _, dlc, data = dummy.split(None, 4) + else: + can_id_str, frame_name, brs, esi, dlc, data_length, data = dummy.split( + None, 6 + ) + if frame_name.isdigit(): + # Empty frame_name + can_id_str, brs, esi, dlc, data_length, data = dummy.split( + None, 5 + ) except ValueError: # but if not, we only want to get the stuff up to the dlc can_id_str, _, _, dlc = dummy.split(None, 3) # and we set data to an empty sequence manually data = '' - - dlc = int(dlc) + dlc = int(dlc, 16) + if is_fd: + # For fd frames, dlc and data length might not be equal and + # data_length is the actual size of the data + dlc = int(data_length) frame = bytearray() data = data.split() for byte in data[0:dlc]: @@ -119,7 +139,10 @@ def __iter__(self): is_remote_frame=False, dlc=dlc, data=frame, - channel=channel + is_fd=is_fd, + channel=channel, + bitrate_switch=is_fd and brs == "1", + error_state_indicator=is_fd and esi == "1", ) self.stop() diff --git a/test/logformats_test.py b/test/logformats_test.py index d9551e5d6..41bf2e9c4 100644 --- a/test/logformats_test.py +++ b/test/logformats_test.py @@ -315,7 +315,7 @@ class TestAscFileFormat(ReaderWriterTest): def _setup_instance(self): super(TestAscFileFormat, self)._setup_instance_helper( can.ASCWriter, can.ASCReader, - check_fd=False, + check_fd=True, check_comments=True, preserves_channel=False, adds_default_channel=0 ) From d2d701269dcbba6d945ad1e4b33ba1ab448fb161 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 7 May 2020 09:08:55 +1200 Subject: [PATCH 31/53] 3.3.3-a.3 --- CHANGELOG.txt | 9 +++++---- can/__init__.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3399feb65..c2a6ea38a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,11 +1,12 @@ Version 3.3.3 ==== -Backported fixes from Python 3 only 4.x development. +Backported fixes from 4.x development branch which targets Python 3. -* #798 Backport caching msg.data value in neovi interface -* #796 Fix Vector CANlib treatment of empty app name -* #771 Handle empty CSV file +* #798 Backport caching msg.data value in neovi interface. +* #796 Fix Vector CANlib treatment of empty app name. +* #771 Handle empty CSV file. +* #741 ASCII reader can now handle FD frames. * #740 Exclude test packages from distribution. * #713 RTR crash fix in canutils log reader parsing RTR frames. * #701 Skip J1939 messages in ASC Reader. diff --git a/can/__init__.py b/can/__init__.py index 43996ff4f..0e30f1c18 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.3-alpha.2" +__version__ = "3.3.3-alpha.3" log = logging.getLogger('can') From 8b76232e283c9fab05515d96cb6bc5b32d7d0684 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 18 May 2020 10:16:58 +1200 Subject: [PATCH 32/53] Set version to 3.3.3 --- can/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/__init__.py b/can/__init__.py index 0e30f1c18..481dc29e3 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.3-alpha.3" +__version__ = "3.3.3" log = logging.getLogger('can') From cdf1e5a4c7ec1caa74a0abba575d8ea3ae197aae Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 18 Jun 2020 21:28:30 +1200 Subject: [PATCH 33/53] Start 3.3.4 release notes --- CHANGELOG.txt | 8 ++++++++ can/__init__.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index c2a6ea38a..1584ef235 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,11 @@ +Version 3.3.4 +==== + +Last call for Python2 support. + +* #850 Fix socket.error is a deprecated alias of OSError used on Python versions lower than 3.3. + + Version 3.3.3 ==== diff --git a/can/__init__.py b/can/__init__.py index 481dc29e3..45886435d 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.3" +__version__ = "3.3.4-dev0" log = logging.getLogger('can') From ea142fdb9a35091f83ae6617fa829422b3cdd2b2 Mon Sep 17 00:00:00 2001 From: karl ding Date: Thu, 18 Jun 2020 02:43:18 -0700 Subject: [PATCH 34/53] Fix SocketCAN periodic Tasks on Python 2 (#850) socket.error is a deprecated alias of OSError used on Python versions lower than 3.3. Also cherry pick over the relevant cyclic SocketCAN tests and enable Travis CI for SocketCAN tests on Python 2. Fixes #845 --- .travis.yml | 8 ++ can/interfaces/socketcan/socketcan.py | 2 +- test/test_cyclic_socketcan.py | 176 ++++++++++++++++++++++++++ 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 test/test_cyclic_socketcan.py diff --git a/.travis.yml b/.travis.yml index bcd18033a..3683f5fbc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,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 diff --git a/can/interfaces/socketcan/socketcan.py b/can/interfaces/socketcan/socketcan.py index b671f926a..4bb989dd7 100644 --- a/can/interfaces/socketcan/socketcan.py +++ b/can/interfaces/socketcan/socketcan.py @@ -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: diff --git a/test/test_cyclic_socketcan.py b/test/test_cyclic_socketcan.py new file mode 100644 index 000000000..43a763c79 --- /dev/null +++ b/test/test_cyclic_socketcan.py @@ -0,0 +1,176 @@ +""" +This module tests multiple message cyclic send tasks. +""" +import unittest + +import time +import can + +from .config import TEST_INTERFACE_SOCKETCAN + + +@unittest.skipUnless(TEST_INTERFACE_SOCKETCAN, "skip testing of socketcan") +class CyclicSocketCan(unittest.TestCase): + BITRATE = 500000 + TIMEOUT = 0.1 + + INTERFACE_1 = "socketcan" + CHANNEL_1 = "vcan0" + INTERFACE_2 = "socketcan" + CHANNEL_2 = "vcan0" + + PERIOD = 1.0 + + DELTA = 0.01 + + def _find_start_index(self, tx_messages, message): + """ + :param tx_messages: + The list of messages that were passed to the periodic backend + :param message: + The message whose data we wish to match and align to + + :returns: start index in the tx_messages + """ + start_index = -1 + for index, tx_message in enumerate(tx_messages): + if tx_message.data == message.data: + start_index = index + break + return start_index + + def setUp(self): + self._send_bus = can.Bus( + interface=self.INTERFACE_1, channel=self.CHANNEL_1, bitrate=self.BITRATE + ) + self._recv_bus = can.Bus( + interface=self.INTERFACE_2, channel=self.CHANNEL_2, bitrate=self.BITRATE + ) + + def tearDown(self): + self._send_bus.shutdown() + self._recv_bus.shutdown() + + def test_cyclic_initializer_message(self): + message = can.Message( + arbitration_id=0x401, + data=[0x11, 0x11, 0x11, 0x11, 0x11, 0x11], + is_extended_id=False, + ) + + task = self._send_bus.send_periodic(message, self.PERIOD) + self.assertIsInstance(task, can.broadcastmanager.CyclicSendTaskABC) + + # Take advantage of kernel's queueing mechanisms + time.sleep(4 * self.PERIOD) + task.stop() + + for _ in range(4): + tx_message = message + rx_message = self._recv_bus.recv(self.TIMEOUT) + + self.assertIsNotNone(rx_message) + self.assertEqual(tx_message.arbitration_id, rx_message.arbitration_id) + self.assertEqual(tx_message.dlc, rx_message.dlc) + self.assertEqual(tx_message.data, rx_message.data) + self.assertEqual(tx_message.is_extended_id, rx_message.is_extended_id) + self.assertEqual(tx_message.is_remote_frame, rx_message.is_remote_frame) + self.assertEqual(tx_message.is_error_frame, rx_message.is_error_frame) + self.assertEqual(tx_message.is_fd, rx_message.is_fd) + + def test_create_same_id_raises_exception(self): + messages_a = can.Message( + arbitration_id=0x401, + data=[0x11, 0x11, 0x11, 0x11, 0x11, 0x11], + is_extended_id=False, + ) + + messages_b = can.Message( + arbitration_id=0x401, + data=[0x22, 0x22, 0x22, 0x22, 0x22, 0x22], + is_extended_id=False, + ) + + task_a = self._send_bus.send_periodic(messages_a, 1) + self.assertIsInstance(task_a, can.broadcastmanager.CyclicSendTaskABC) + + # The second one raises a ValueError when we attempt to create a new + # Task, since it has the same arbitration ID. + with self.assertRaises(ValueError): + task_b = self._send_bus.send_periodic(messages_b, 1) + + def test_modify_data_message(self): + message_odd = can.Message( + arbitration_id=0x401, + data=[0x11, 0x11, 0x11, 0x11, 0x11, 0x11], + is_extended_id=False, + ) + message_even = can.Message( + arbitration_id=0x401, + data=[0x22, 0x22, 0x22, 0x22, 0x22, 0x22], + is_extended_id=False, + ) + task = self._send_bus.send_periodic(message_odd, self.PERIOD) + self.assertIsInstance(task, can.broadcastmanager.ModifiableCyclicTaskABC) + + results_odd = [] + results_even = [] + for _ in range(1 * 4): + result = self._recv_bus.recv(self.PERIOD * 2) + if result: + results_odd.append(result) + + task.modify_data(message_even) + for _ in range(1 * 4): + result = self._recv_bus.recv(self.PERIOD * 2) + if result: + results_even.append(result) + + task.stop() + + # Now go through the partitioned results and assert that they're equal + for rx_index, rx_message in enumerate(results_even): + tx_message = message_even + + self.assertEqual(tx_message.arbitration_id, rx_message.arbitration_id) + self.assertEqual(tx_message.dlc, rx_message.dlc) + self.assertEqual(tx_message.data, rx_message.data) + self.assertEqual(tx_message.is_extended_id, rx_message.is_extended_id) + self.assertEqual(tx_message.is_remote_frame, rx_message.is_remote_frame) + self.assertEqual(tx_message.is_error_frame, rx_message.is_error_frame) + self.assertEqual(tx_message.is_fd, rx_message.is_fd) + + if rx_index != 0: + prev_rx_message = results_even[rx_index - 1] + # Assert timestamps are within the expected period + self.assertTrue( + abs( + (rx_message.timestamp - prev_rx_message.timestamp) - self.PERIOD + ) + <= self.DELTA + ) + + for rx_index, rx_message in enumerate(results_odd): + tx_message = message_odd + + self.assertEqual(tx_message.arbitration_id, rx_message.arbitration_id) + self.assertEqual(tx_message.dlc, rx_message.dlc) + self.assertEqual(tx_message.data, rx_message.data) + self.assertEqual(tx_message.is_extended_id, rx_message.is_extended_id) + self.assertEqual(tx_message.is_remote_frame, rx_message.is_remote_frame) + self.assertEqual(tx_message.is_error_frame, rx_message.is_error_frame) + self.assertEqual(tx_message.is_fd, rx_message.is_fd) + + if rx_index != 0: + prev_rx_message = results_odd[rx_index - 1] + # Assert timestamps are within the expected period + self.assertTrue( + abs( + (rx_message.timestamp - prev_rx_message.timestamp) - self.PERIOD + ) + <= self.DELTA + ) + + +if __name__ == "__main__": + unittest.main() From ed58372c66a5c53297781e0b10e75093e7aa012e Mon Sep 17 00:00:00 2001 From: Johan Brus <69041456+johanbrus@users.noreply.github.com> Date: Tue, 4 Aug 2020 10:19:45 +0200 Subject: [PATCH 35/53] Update configuration.rst (#879) the line can.interfaces.interface gave the error "ModuleNotFoundError: No module named 'can.interfaces.interface' Hence propose to remove 'interfaces' --- doc/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/configuration.rst b/doc/configuration.rst index 142e816da..230eec1bd 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -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() From 0c34e5070ccaa3c89d6c1893370083943f0d5390 Mon Sep 17 00:00:00 2001 From: Karl Date: Mon, 3 Aug 2020 22:14:45 -0700 Subject: [PATCH 36/53] Fix RecursionError in Message.__getattr__ __getattr__ incorrectly assumes that self._dict always exists. However, if self._dict doesn't exist, the function attempts to call __getattr__ again, which results in infinite recursion when serializing the object via pickle. This fixes the implementation of __getattr__ and adds a test to exercise pickling/unpickling the Message. Fixes #804 --- can/message.py | 4 +++- test/test_message_class.py | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/can/message.py b/can/message.py index f85218fc0..9002cc625 100644 --- a/can/message.py +++ b/can/message.py @@ -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] diff --git a/test/test_message_class.py b/test/test_message_class.py index 85dbe8560..05ed14b2a 100644 --- a/test/test_message_class.py +++ b/test/test_message_class.py @@ -5,12 +5,15 @@ import sys from math import isinf, isnan from copy import copy, deepcopy +import pickle from hypothesis import given, settings, reproduce_failure import hypothesis.strategies as st from can import Message +from .message_helper import ComparingMessagesTestCase + class TestMessageClass(unittest.TestCase): """ @@ -70,7 +73,7 @@ def test_methods(self, **kwargs): # check copies and equalities if is_valid: - self.assertEqual(message, message) + self.assertEqual(message, message) normal_copy = copy(message) deep_copy = deepcopy(message) for other in (normal_copy, deep_copy, message): @@ -79,5 +82,31 @@ def test_methods(self, **kwargs): self.assertTrue(message.equals(other, timestamp_delta=0)) -if __name__ == '__main__': +class MessageSerialization(unittest.TestCase, ComparingMessagesTestCase): + def __init__(self, *args, **kwargs): + unittest.TestCase.__init__(self, *args, **kwargs) + ComparingMessagesTestCase.__init__( + self, allowed_timestamp_delta=0.016, preserves_channel=True + ) + + def test_serialization(self): + message = Message( + timestamp=1.0, + arbitration_id=0x401, + is_extended_id=False, + is_remote_frame=False, + is_error_frame=False, + channel=1, + dlc=6, + data=bytearray([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]), + is_fd=False, + ) + + serialized = pickle.dumps(message, -1) + deserialized = pickle.loads(serialized) + + self.assertMessageEqual(message, deserialized) + + +if __name__ == "__main__": unittest.main() From 23cf849f1bbdd1aa40576220d2583f625e8aeb66 Mon Sep 17 00:00:00 2001 From: zhupumpkin <11852827@qq.com> Date: Fri, 6 Mar 2020 10:31:43 +0800 Subject: [PATCH 37/53] fix issue 787 --- can/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/message.py b/can/message.py index 9002cc625..2246f1d05 100644 --- a/can/message.py +++ b/can/message.py @@ -112,7 +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: - self.is_extended_id = True if extended_id is None else extended_id + self.is_extended_id = False if extended_id is None else extended_id self.is_remote_frame = is_remote_frame self.is_error_frame = is_error_frame From 9682d6a916be2d9dbe61857636de20c99e723204 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 6 Aug 2020 12:01:22 +1200 Subject: [PATCH 38/53] Update changelog and bump to alpha version --- CHANGELOG.txt | 5 +++++ can/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1584ef235..70b865475 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,11 @@ Version 3.3.4 Last call for Python2 support. * #850 Fix socket.error is a deprecated alias of OSError used on Python versions lower than 3.3. +* #846 Use inter-process mutex to prevent concurrent neoVI device open. +* #879 Updating incorrect api documentation. +* #885 Fix recursion message in Message.__getattr__ +* #845 Fix socketcan issue +* #788 Fix issue with extended_id Version 3.3.3 diff --git a/can/__init__.py b/can/__init__.py index 45886435d..d3c824cad 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.4-dev0" +__version__ = "3.3.4-alpha0" log = logging.getLogger('can') From 0988fba52446e18c35fe1ebc3e5db11749fd0db9 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 6 Aug 2020 16:05:58 +1200 Subject: [PATCH 39/53] Revert change of Message extended id default behaviour. --- CHANGELOG.txt | 1 - can/__init__.py | 2 +- can/message.py | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 70b865475..9aa2d95db 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -8,7 +8,6 @@ Last call for Python2 support. * #879 Updating incorrect api documentation. * #885 Fix recursion message in Message.__getattr__ * #845 Fix socketcan issue -* #788 Fix issue with extended_id Version 3.3.3 diff --git a/can/__init__.py b/can/__init__.py index d3c824cad..e68fcd743 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.4-alpha0" +__version__ = "3.3.4-alpha1" log = logging.getLogger('can') diff --git a/can/message.py b/can/message.py index 2246f1d05..84f675183 100644 --- a/can/message.py +++ b/can/message.py @@ -112,7 +112,8 @@ 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: - self.is_extended_id = False if extended_id is None else extended_id + # 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 self.is_error_frame = is_error_frame From 254514178a7e602687fe22beeef8672628794165 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 6 Aug 2020 16:22:16 +1200 Subject: [PATCH 40/53] Upgrade version of pytest --- .travis.yml | 1 + setup.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3683f5fbc..cca71b50e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: - | diff --git a/setup.py b/setup.py index e5b05e8dc..797409c81 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ from __future__ import absolute_import +import platform from os import listdir from os.path import isfile, join import re @@ -31,7 +32,7 @@ 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` @@ -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", From b47ca2fae4fb15771b519b572f91bfdf171874f3 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Thu, 6 Aug 2020 19:48:34 +1200 Subject: [PATCH 41/53] Tag version 3.3.4-beta.0 --- can/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/__init__.py b/can/__init__.py index e68fcd743..cfce6f0a0 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.4-alpha1" +__version__ = "3.3.4-beta.0" log = logging.getLogger('can') From 5c7810f65e2935ffea30054a3b4ac350da1e844e Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Sun, 16 Aug 2020 15:54:35 +1200 Subject: [PATCH 42/53] Change ascii conversion to be compatible with Python2.7 in ixxat backend. Contributed by @wkemps --- can/interfaces/ixxat/canlib.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 84c8751c1..eac867344 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -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) From bdf46cd16ba8edf70199baa564d1f2139118a68f Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Sun, 16 Aug 2020 15:55:07 +1200 Subject: [PATCH 43/53] Version 3.3.4 --- can/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/__init__.py b/can/__init__.py index cfce6f0a0..2704efc3d 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.4-beta.0" +__version__ = "3.3.4" log = logging.getLogger('can') From d271323b9bf565fc500acaae774892c3d79ad075 Mon Sep 17 00:00:00 2001 From: karl ding Date: Wed, 26 Aug 2020 03:38:27 -0700 Subject: [PATCH 44/53] Fix iteration in Bus.stop_all_periodic_tasks (#901) Fix iteration in Bus.stop_all_periodic_tasks so tasks are properly stopped. In addition, add a test in order to verify that Cyclic Tasks are correctly stopped when multiple tasks are active on a particular bus. The test is carried out via the SocketCAN interface. Note: This is a squashed cherry pick of the following commits from develop: - 8112d13ceb4493067174be899d4f014131cd4114 - 1aa0bc64033b5fff6bc88474e7d1afb52e81ee7a Addresses #634 --- can/bus.py | 12 +++++++-- test/test_cyclic_socketcan.py | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/can/bus.py b/can/bus.py index 2b36b3c57..2b3044cf1 100644 --- a/can/bus.py +++ b/can/bus.py @@ -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. diff --git a/test/test_cyclic_socketcan.py b/test/test_cyclic_socketcan.py index 43a763c79..831264bf4 100644 --- a/test/test_cyclic_socketcan.py +++ b/test/test_cyclic_socketcan.py @@ -171,6 +171,56 @@ def test_modify_data_message(self): <= self.DELTA ) + def test_stop_all_periodic_tasks_and_remove_task(self): + message_a = can.Message( + arbitration_id=0x401, + data=[0x11, 0x11, 0x11, 0x11, 0x11, 0x11], + is_extended_id=False, + ) + message_b = can.Message( + arbitration_id=0x402, + data=[0x22, 0x22, 0x22, 0x22, 0x22, 0x22], + is_extended_id=False, + ) + message_c = can.Message( + arbitration_id=0x403, + data=[0x33, 0x33, 0x33, 0x33, 0x33, 0x33], + is_extended_id=False, + ) + + # Start Tasks + task_a = self._send_bus.send_periodic(message_a, self.PERIOD) + task_b = self._send_bus.send_periodic(message_b, self.PERIOD) + task_c = self._send_bus.send_periodic(message_c, self.PERIOD) + + self.assertIsInstance(task_a, can.broadcastmanager.ModifiableCyclicTaskABC) + self.assertIsInstance(task_b, can.broadcastmanager.ModifiableCyclicTaskABC) + self.assertIsInstance(task_c, can.broadcastmanager.ModifiableCyclicTaskABC) + + for _ in range(6): + _ = self._recv_bus.recv(self.PERIOD) + + # Stop all tasks and delete + self._send_bus.stop_all_periodic_tasks(remove_tasks=True) + + # Now wait for a few periods, after which we should definitely not + # receive any CAN messages + time.sleep(4 * self.PERIOD) + + # If we successfully deleted everything, then we will eventually read + # 0 messages. + successfully_stopped = False + for _ in range(6): + rx_message = self._recv_bus.recv(self.PERIOD) + + if rx_message is None: + successfully_stopped = True + break + self.assertTrue(successfully_stopped, "Still received messages after stopping") + + # None of the tasks should still be associated with the bus + self.assertEqual(0, len(self._send_bus._periodic_tasks)) + if __name__ == "__main__": unittest.main() From 57b1a341103a52fa6db848fe15b40b3fb6e7a5c3 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Wed, 26 Aug 2020 22:42:16 +1200 Subject: [PATCH 45/53] Update CHANGELOG.txt --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9aa2d95db..1e63e0d4b 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,8 +3,8 @@ Version 3.3.4 Last call for Python2 support. +* #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. -* #846 Use inter-process mutex to prevent concurrent neoVI device open. * #879 Updating incorrect api documentation. * #885 Fix recursion message in Message.__getattr__ * #845 Fix socketcan issue From 9452b54ef3200e8fe296b046b4fb78ecd3c9abff Mon Sep 17 00:00:00 2001 From: pierreluctg Date: Fri, 28 Aug 2020 09:15:20 -0400 Subject: [PATCH 46/53] Backport Neovi features for release 3.3.4 (#903) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use inter-process mutex to prevent concurrent neoVI device open When neoVI server is enabled, there is an issue with concurrent device open. * Move neoVI open lock to module level * Adding dummy file lock when importing FileLock fails * Grammar fix * Raising more precise API error when set bitrate fails Also calling shutdown before raising exception from the init if the device is opened * Simplified if fd condition in init * Moving filelock to neovi extras_require * Adding comma back * Update CHANGELOG.txt Co-authored-by: Pierre-Luc Tessier Gagné --- CHANGELOG.txt | 1 + can/interfaces/ics_neovi/neovi_bus.py | 59 +++++++++++++++++++++++---- setup.py | 2 +- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1e63e0d4b..1f8cf82bf 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -15,6 +15,7 @@ Version 3.3.3 Backported fixes from 4.x development branch which targets Python 3. +* #846 Use inter-process mutex to prevent concurrent neoVI device open. * #798 Backport caching msg.data value in neovi interface. * #796 Fix Vector CANlib treatment of empty app name. * #771 Handle empty CSV file. diff --git a/can/interfaces/ics_neovi/neovi_bus.py b/can/interfaces/ics_neovi/neovi_bus.py index 530d7c524..314967708 100644 --- a/can/interfaces/ics_neovi/neovi_bus.py +++ b/can/interfaces/ics_neovi/neovi_bus.py @@ -11,6 +11,8 @@ """ import logging +import os +import tempfile from collections import deque from can import Message, CanError, BusABC @@ -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. @@ -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) diff --git a/setup.py b/setup.py index 797409c81..8f270378b 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ # Dependencies extras_require = { 'serial': ['pyserial~=3.0'], - 'neovi': ['python-ics>=2.12'] + 'neovi': ['python-ics>=2.12', 'filelock'] } tests_require = [ From 551cc946fe70cd3aa95d2d8b758604aeeb28a3e7 Mon Sep 17 00:00:00 2001 From: pierreluctg Date: Fri, 28 Aug 2020 09:16:52 -0400 Subject: [PATCH 47/53] Update CHANGELOG.txt --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1f8cf82bf..d11885fc0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,6 +3,7 @@ Version 3.3.4 Last call for Python2 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. @@ -15,7 +16,6 @@ Version 3.3.3 Backported fixes from 4.x development branch which targets Python 3. -* #846 Use inter-process mutex to prevent concurrent neoVI device open. * #798 Backport caching msg.data value in neovi interface. * #796 Fix Vector CANlib treatment of empty app name. * #771 Handle empty CSV file. From 453a4b7112e1de2ff07999a86c013c02c7f4684f Mon Sep 17 00:00:00 2001 From: Karl Date: Wed, 30 Sep 2020 21:33:37 -0700 Subject: [PATCH 48/53] vector: Skip channels without CAN support Skip any channels that don't have support for CAN (ex. LIN, Digital/Analog IO) instead of accepting everything when using auto-detection. Note: This is a backport of #641 to 3.3.4 Addresses #908 --- can/interfaces/vector/canlib.py | 2 ++ can/interfaces/vector/vxlapi.py | 1 + 2 files changed, 3 insertions(+) diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index 65af0147b..0864ecefe 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -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')) diff --git a/can/interfaces/vector/vxlapi.py b/can/interfaces/vector/vxlapi.py index ae87706c4..461a62197 100644 --- a/can/interfaces/vector/vxlapi.py +++ b/can/interfaces/vector/vxlapi.py @@ -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 From 14c016272136c66c3737c0fe33aeca9e3ec72915 Mon Sep 17 00:00:00 2001 From: zariiii9003 <52598363+zariiii9003@users.noreply.github.com> Date: Sat, 3 Oct 2020 13:37:37 +0200 Subject: [PATCH 49/53] Update CHANGELOG.txt --- CHANGELOG.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d11885fc0..7899d50b6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,6 +3,7 @@ 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. From d3ee3285b55571cc076b32d3d8c0bf7a7f44c792 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Sun, 4 Oct 2020 16:44:20 +1300 Subject: [PATCH 50/53] Remove usused import from setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8f270378b..898f54c16 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,6 @@ from __future__ import absolute_import -import platform from os import listdir from os.path import isfile, join import re @@ -67,6 +66,7 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", From dab4a9f114ad309f4def64f3a43516db4716b343 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 12 Oct 2020 08:56:01 +1300 Subject: [PATCH 51/53] Update wheel on travis before publishing package. Tag version 3.3.5-dev0 --- .travis.yml | 3 ++- can/__init__.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cca71b50e..72a94632a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ python: - "2.7" - "3.6" - "3.7" - - 3.8-dev + - "3.8" - nightly # PyPy: - pypy # Python 2.7 @@ -24,6 +24,7 @@ env: install: - if [[ "$TEST_SOCKETCAN" ]]; then sudo bash test/open_vcan.sh ; fi + - travis_retry pip install -U pip wheel setuptools - travis_retry pip install .[test] - pip freeze diff --git a/can/__init__.py b/can/__init__.py index 2704efc3d..b7f3c4d2a 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.4" +__version__ = "3.3.5-dev0" log = logging.getLogger('can') From 86684ac60f11e0d502839eb82ebda233a2914950 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 12 Oct 2020 09:08:33 +1300 Subject: [PATCH 52/53] Update pip first --- .travis.yml | 1 + can/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 72a94632a..9770764cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ env: install: - if [[ "$TEST_SOCKETCAN" ]]; then sudo bash test/open_vcan.sh ; fi + - travis_retry pip install -U pip - travis_retry pip install -U pip wheel setuptools - travis_retry pip install .[test] - pip freeze diff --git a/can/__init__.py b/can/__init__.py index b7f3c4d2a..0d310e436 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -8,7 +8,7 @@ import logging -__version__ = "3.3.5-dev0" +__version__ = "3.3.5-dev1" log = logging.getLogger('can') From 14bb954275ccde68b4d650395c22953f4dac3759 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 12 Oct 2020 09:56:33 +1300 Subject: [PATCH 53/53] Travis debugging --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9770764cf..6525cea2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,6 @@ env: install: - if [[ "$TEST_SOCKETCAN" ]]; then sudo bash test/open_vcan.sh ; fi - - travis_retry pip install -U pip - - travis_retry pip install -U pip wheel setuptools - travis_retry pip install .[test] - pip freeze @@ -100,6 +98,7 @@ jobs: name: "PyPi Deployment" python: "3.7" before_install: + - travis_retry pip install -U pip - travis_retry pip install -U wheel setuptools deploy: provider: pypi