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 diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2f50dca8d..d0a1278e0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,48 @@ -Version 3.2.0 +Version 3.3.4 +==== + +Removed the pkg_resources dependency by removing checks for the can.interface entry point + +Version 3.3.3 +==== + +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. +* #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. +* #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 ==== +Minor bug fix release addressing issue in PCAN RTR. + +Version 3.3.1 +==== + +Minor fix to setup.py to only require pytest-runner when necessary. + +Version 3.3.0 +==== + +* 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. + +Version 3.2.0 +==== Major features -------------- @@ -105,7 +147,7 @@ Major features * Adds support for developing `asyncio` applications with `python-can` more easily. This can be useful when implementing protocols that handles simultaneous connections to many nodes since you can write synchronous looking code without handling multiple threads and locking mechanisms. #388 -* New can viewer terminal application. (`python -m can.viewer`) #390 +* New can viewer terminal application. (`python -m pycan.viewer`) #390 * More formally adds task management responsibility to the `Bus`. By default tasks created with `bus.send_periodic` will have a reference held by the bus - this means in many cases the user doesn't need to keep the task in scope for their periodic messages to continue being sent. If @@ -127,7 +169,7 @@ Breaking changes Other notable changes --------------------- -* can.Message class updated #413 +* pycan.Message class updated #413 - Addition of a `Message.equals` method. - Deprecate id_type in favor of is_extended_id - Initializer parameter extended_id deprecated in favor of is_extended_id diff --git a/README.rst b/README.rst index affcde831..9342e7af4 100644 --- a/README.rst +++ b/README.rst @@ -70,17 +70,17 @@ Example usage .. code:: python # import the library - import can + import pycan # create a bus instance # many other interfaces are supported as well (see below) - bus = can.Bus(interface='socketcan', - channel='vcan0', - receive_own_messages=True) + bus = pycan.Bus(interface='socketcan', + channel='vcan0', + receive_own_messages=True) # send a message - message = can.Message(arbitration_id=123, is_extended_id=True, - data=[0x11, 0x22, 0x33]) + message = pycan.Message(arbitration_id=123, is_extended_id=True, + data=[0x11, 0x22, 0x33]) bus.send(message, timeout=0.2) # iterate over received messages @@ -88,7 +88,7 @@ Example usage print("{X}: {}".format(msg.arbitration_id, msg.data)) # or use an asynchronous notifier - notifier = can.Notifier(bus, [can.Logger("recorded.log"), can.Printer()]) + notifier = pycan.Notifier(bus, [pycan.Logger("recorded.log"), pycan.Printer()]) You can find more information in the documentation, online at `python-can.readthedocs.org `__. diff --git a/can/interfaces/__init__.py b/can/interfaces/__init__.py deleted file mode 100644 index ec79e51d6..000000000 --- a/can/interfaces/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -# coding: utf-8 - -""" -Interfaces contain low level implementations that interact with CAN hardware. -""" - -import warnings -from pkg_resources import iter_entry_points - - -# interface_name => (module, classname) -BACKENDS = { - 'kvaser': ('can.interfaces.kvaser', 'KvaserBus'), - 'socketcan': ('can.interfaces.socketcan', 'SocketcanBus'), - 'serial': ('can.interfaces.serial.serial_can','SerialBus'), - 'pcan': ('can.interfaces.pcan', 'PcanBus'), - 'usb2can': ('can.interfaces.usb2can', 'Usb2canBus'), - 'ixxat': ('can.interfaces.ixxat', 'IXXATBus'), - 'nican': ('can.interfaces.nican', 'NicanBus'), - 'iscan': ('can.interfaces.iscan', 'IscanBus'), - 'virtual': ('can.interfaces.virtual', 'VirtualBus'), - 'neovi': ('can.interfaces.ics_neovi', 'NeoViBus'), - 'vector': ('can.interfaces.vector', 'VectorBus'), - 'slcan': ('can.interfaces.slcan', 'slcanBus'), - 'canalystii': ('can.interfaces.canalystii', 'CANalystIIBus'), - 'systec': ('can.interfaces.systec', 'UcanBus') -} - -BACKENDS.update({ - interface.name: (interface.module_name, interface.attrs[0]) - for interface in iter_entry_points('can.interface') -}) - -# Old entry point name. May be removed >3.0. -for interface in iter_entry_points('python_can.interface'): - BACKENDS[interface.name] = (interface.module_name, interface.attrs[0]) - warnings.warn('{} is using the deprecated python_can.interface entry point. '.format(interface.name) + - 'Please change to can.interface instead.', DeprecationWarning) - -VALID_INTERFACES = frozenset(list(BACKENDS.keys()) + ['socketcan_native', 'socketcan_ctypes']) diff --git a/can/interfaces/ics_neovi/__init__.py b/can/interfaces/ics_neovi/__init__.py deleted file mode 100644 index 4426b1585..000000000 --- a/can/interfaces/ics_neovi/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# coding: utf-8 - -""" -""" - -from can.interfaces.ics_neovi.neovi_bus import NeoViBus diff --git a/can/interfaces/kvaser/__init__.py b/can/interfaces/kvaser/__init__.py deleted file mode 100644 index 5cbe63386..000000000 --- a/can/interfaces/kvaser/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# coding: utf-8 - -""" -""" - -from can.interfaces.kvaser.canlib import * diff --git a/can/interfaces/pcan/__init__.py b/can/interfaces/pcan/__init__.py deleted file mode 100644 index ceba250b5..000000000 --- a/can/interfaces/pcan/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# coding: utf-8 - -""" -""" - -from can.interfaces.pcan.pcan import PcanBus diff --git a/can/interfaces/serial/__init__.py b/can/interfaces/serial/__init__.py deleted file mode 100644 index dced63b0f..000000000 --- a/can/interfaces/serial/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# coding: utf-8 - -""" -""" - -from can.interfaces.serial.serial_can import SerialBus as Bus diff --git a/can/interfaces/socketcan/__init__.py b/can/interfaces/socketcan/__init__.py deleted file mode 100644 index 8a2105598..000000000 --- a/can/interfaces/socketcan/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# coding: utf-8 - -""" -See: https://www.kernel.org/doc/Documentation/networking/can.txt -""" - -from can.interfaces.socketcan.socketcan import SocketcanBus, CyclicSendTask, MultiRateCyclicSendTask diff --git a/can/interfaces/systec/__init__.py b/can/interfaces/systec/__init__.py deleted file mode 100644 index ed8eb8eb7..000000000 --- a/can/interfaces/systec/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# coding: utf-8 - -""" -""" - -from can.interfaces.systec.ucanbus import UcanBus diff --git a/can/interfaces/usb2can/serial_selector.py b/can/interfaces/usb2can/serial_selector.py deleted file mode 100644 index b47396876..000000000 --- a/can/interfaces/usb2can/serial_selector.py +++ /dev/null @@ -1,45 +0,0 @@ -# coding: utf-8 - -""" -""" - -from __future__ import division, print_function, absolute_import - -import logging - -try: - import win32com.client -except ImportError: - logging.warning("win32com.client module required for usb2can") - raise - - -def WMIDateStringToDate(dtmDate): - if (dtmDate[4] == 0): - strDateTime = dtmDate[5] + '/' - else: - strDateTime = dtmDate[4] + dtmDate[5] + '/' - - if (dtmDate[6] == 0): - strDateTime = strDateTime + dtmDate[7] + '/' - else: - strDateTime = strDateTime + dtmDate[6] + dtmDate[7] + '/' - strDateTime = strDateTime + dtmDate[0] + dtmDate[1] + dtmDate[2] + dtmDate[3] + ' ' + dtmDate[8] + dtmDate[9] \ - + ':' + dtmDate[10] + dtmDate[11] + ':' + dtmDate[12] + dtmDate[13] - return strDateTime - - -def find_serial_devices(serial_matcher="ED"): - """ - Finds a list of USB devices where the serial number (partially) matches the given string. - - :param str serial_matcher (optional): - only device IDs starting with this string are returned - - :rtype: List[str] - """ - objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator") - objSWbemServices = objWMIService.ConnectServer(".", "root\cimv2") - items = objSWbemServices.ExecQuery("SELECT * FROM Win32_USBControllerDevice") - ids = (item.Dependent.strip('"')[-8:] for item in items) - return [e for e in ids if e.startswith(serial_matcher)] diff --git a/doc/api.rst b/doc/api.rst index 640f61e2d..4bdbf6b37 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -1,7 +1,7 @@ Library API =========== -The main objects are the :class:`~can.BusABC` and the :class:`~can.Message`. +The main objects are the :class:`~pycan.BusABC` and the :class:`~pycan.Message`. A form of CAN interface is also required. .. hint:: @@ -24,7 +24,7 @@ Utilities --------- -.. automethod:: can.detect_available_configs +.. automethod:: pycan.detect_available_configs .. _notifier: @@ -34,10 +34,10 @@ Notifier The Notifier object is used as a message distributor for a bus. -.. autoclass:: can.Notifier +.. autoclass:: pycan.Notifier :members: Errors ------ -.. autoclass:: can.CanError +.. autoclass:: pycan.CanError diff --git a/doc/asyncio.rst b/doc/asyncio.rst index cd8d65de5..66c012baa 100644 --- a/doc/asyncio.rst +++ b/doc/asyncio.rst @@ -5,14 +5,14 @@ Asyncio support The :mod:`asyncio` module built into Python 3.4 and later can be used to write asynchronous code in a single thread. This library supports receiving messages -asynchronously in an event loop using the :class:`can.Notifier` class. +asynchronously in an event loop using the :class:`pycan.Notifier` class. There will still be one thread per CAN bus but the user application will execute entirely in the event loop, allowing simpler concurrency without worrying about threading issues. Interfaces that have a valid file descriptor will however be supported natively without a thread. -You can also use the :class:`can.AsyncBufferedReader` listener if you prefer +You can also use the :class:`pycan.AsyncBufferedReader` listener if you prefer to write coroutine based code instead of using callbacks. diff --git a/doc/bcm.rst b/doc/bcm.rst index 96e73d52d..56878b4fb 100644 --- a/doc/bcm.rst +++ b/doc/bcm.rst @@ -3,7 +3,7 @@ Broadcast Manager ================= -.. module:: can.broadcastmanager +.. module:: pycan.broadcastmanager The broadcast manager allows the user to setup periodic message jobs. For example sending a particular message at a given period. The broadcast @@ -22,13 +22,13 @@ Message Sending Tasks The class based api for the broadcast manager uses a series of `mixin classes `_. -All mixins inherit from :class:`~can.broadcastmanager.CyclicSendTaskABC` -which inherits from :class:`~can.broadcastmanager.CyclicTask`. +All mixins inherit from :class:`~pycan.broadcastmanager.CyclicSendTaskABC` +which inherits from :class:`~pycan.broadcastmanager.CyclicTask`. -.. autoclass:: can.broadcastmanager.CyclicTask +.. autoclass:: pycan.broadcastmanager.CyclicTask :members: -.. autoclass:: can.broadcastmanager.CyclicSendTaskABC +.. autoclass:: pycan.broadcastmanager.CyclicSendTaskABC :members: .. autoclass:: LimitedDurationCyclicSendTaskABC @@ -37,10 +37,10 @@ which inherits from :class:`~can.broadcastmanager.CyclicTask`. .. autoclass:: MultiRateCyclicSendTaskABC :members: -.. autoclass:: can.ModifiableCyclicTaskABC +.. autoclass:: pycan.ModifiableCyclicTaskABC :members: -.. autoclass:: can.RestartableCyclicTaskABC +.. autoclass:: pycan.RestartableCyclicTaskABC :members: @@ -48,8 +48,8 @@ Functional API -------------- .. warning:: - The functional API in :func:`can.broadcastmanager.send_periodic` is now deprecated + The functional API in :func:`pycan.broadcastmanager.send_periodic` is now deprecated and will be removed in version 4.0. - Use the object oriented API via :meth:`can.BusABC.send_periodic` instead. + Use the object oriented API via :meth:`pycan.BusABC.send_periodic` instead. -.. autofunction:: can.broadcastmanager.send_periodic +.. autofunction:: pycan.broadcastmanager.send_periodic diff --git a/doc/bus.rst b/doc/bus.rst index 5c1e95606..334a5c1c8 100644 --- a/doc/bus.rst +++ b/doc/bus.rst @@ -3,22 +3,22 @@ Bus --- -The :class:`~can.BusABC` class, as the name suggests, provides an abstraction of a CAN bus. +The :class:`~pycan.BusABC` class, as the name suggests, provides an abstraction of a CAN bus. The bus provides a wrapper around a physical or virtual CAN Bus. -An interface specific instance of the :class:`~can.BusABC` is created by the :class:`~can.Bus` +An interface specific instance of the :class:`~pycan.BusABC` is created by the :class:`~pycan.Bus` class, for example:: - vector_bus = can.Bus(interface='vector', ...) + vector_bus = pycan.Bus(interface='vector', ...) That bus is then able to handle the interface specific software/hardware interactions -and implements the :class:`~can.BusABC` API. +and implements the :class:`~pycan.BusABC` API. A thread safe bus wrapper is also available, see `Thread safe bus`_. Autoconfig Bus '''''''''''''' -.. autoclass:: can.Bus +.. autoclass:: pycan.Bus :members: :undoc-members: @@ -26,7 +26,7 @@ Autoconfig Bus API ''' -.. autoclass:: can.BusABC +.. autoclass:: pycan.BusABC :members: :undoc-members: @@ -35,21 +35,21 @@ API Transmitting '''''''''''' -Writing individual messages to the bus is done by calling the :meth:`~can.BusABC.send` method -and passing a :class:`~can.Message` instance. Periodic sending is controlled by the +Writing individual messages to the bus is done by calling the :meth:`~pycan.BusABC.send` method +and passing a :class:`~pycan.Message` instance. Periodic sending is controlled by the :ref:`broadcast manager `. Receiving ''''''''' -Reading from the bus is achieved by either calling the :meth:`~can.BusABC.recv` method or +Reading from the bus is achieved by either calling the :meth:`~pycan.BusABC.recv` method or by directly iterating over the bus:: for msg in bus: print(msg.data) -Alternatively the :class:`~can.Listener` api can be used, which is a list of :class:`~can.Listener` +Alternatively the :class:`~pycan.Listener` api can be used, which is a list of :class:`~pycan.Listener` subclasses that receive notifications when new messages arrive. @@ -63,16 +63,16 @@ out in the hardware or kernel layer - not in Python. Thread safe bus --------------- -This thread safe version of the :class:`~can.BusABC` class can be used by multiple threads at once. +This thread safe version of the :class:`~pycan.BusABC` class can be used by multiple threads at once. Sending and receiving is locked separately to avoid unnecessary delays. Conflicting calls are executed by blocking until the bus is accessible. -It can be used exactly like the normal :class:`~can.BusABC`: +It can be used exactly like the normal :class:`~pycan.BusABC`: # 'socketcan' is only an example interface, it works with all the others too - my_bus = can.ThreadSafeBus(interface='socketcan', channel='vcan0') + my_bus = pycan.ThreadSafeBus(interface='socketcan', channel='vcan0') my_bus.send(...) my_bus.recv(...) -.. autoclass:: can.ThreadSafeBus +.. autoclass:: pycan.ThreadSafeBus :members: diff --git a/doc/conf.py b/doc/conf.py index 1c409a06a..43708d676 100755 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# python-can documentation build configuration file +# pythoncan documentation build configuration file # # This file is execfile()d with the current directory set to its containing dir. @@ -10,21 +10,21 @@ import os # General information about the project. -project = u'python-can' +project = u'pythoncan' # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) -import can +import pycan # The version info for the project, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = can.__version__.split('-')[0] -release = can.__version__ +version = pycan.__version__.split('-')[0] +release = pycan.__version__ # -- General configuration ----------------------------------------------------- @@ -187,4 +187,4 @@ #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'python-can' +htmlhelp_basename = 'pythoncan' diff --git a/doc/configuration.rst b/doc/configuration.rst index dda2ace2a..afba9af48 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -5,30 +5,30 @@ Configuration Usually this library is used with a particular CAN interface, this can be specified in code, read from configuration files or environment variables. -See :func:`can.util.load_config` for implementation. +See :func:`pycan.util.load_config` for implementation. In Code ------- -The ``can`` object exposes an ``rc`` dictionary which can be used to set -the **interface** and **channel** before importing from ``can.interfaces``. +The ``pycan`` object exposes an ``rc`` dictionary which can be used to set +the **interface** and **channel** before importing from ``pycan.interfaces``. :: - import can - can.rc['interface'] = 'socketcan' - can.rc['channel'] = 'vcan0' - can.rc['bitrate'] = 500000 - from can.interfaces.interface import Bus + import pycan + pycan.rc['interface'] = 'socketcan' + pycan.rc['channel'] = 'vcan0' + pycan.rc['bitrate'] = 500000 + from pycan.interfaces.interface import Bus bus = Bus() You can also specify the interface and channel for each Bus instance:: - import can + import pycan - bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=500000) + bus = pycan.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=500000) Configuration File @@ -36,16 +36,16 @@ Configuration File On Linux systems the config file is searched in the following paths: -#. ``~/can.conf`` -#. ``/etc/can.conf`` -#. ``$HOME/.can`` -#. ``$HOME/.canrc`` +#. ``~/pycan.conf`` +#. ``/etc/pycan.conf`` +#. ``$HOME/.pycan`` +#. ``$HOME/.pycanrc`` On Windows systems the config file is searched in the following paths: -#. ``~/can.conf`` -#. ``can.ini`` (current working directory) -#. ``$APPDATA/can.ini`` +#. ``~/pycan.conf`` +#. ``pycan.ini`` (current working directory) +#. ``$APPDATA/pycan.ini`` The configuration file sets the default interface and channel: @@ -79,7 +79,7 @@ The configuration can also contain additional sections (or context): :: - from can.interfaces.interface import Bus + from pycan.interfaces.interface import Bus hs_bus = Bus(context='HS') ms_bus = Bus(context='MS') @@ -126,3 +126,7 @@ Lookup table of interface names: +---------------------+-------------------------------------+ | ``"virtual"`` | :doc:`interfaces/virtual` | +---------------------+-------------------------------------+ +| ``"canalystii"`` | :doc:`interfaces/canalystii` | ++---------------------+-------------------------------------+ +| ``"systec"`` | :doc:`interfaces/systec` | ++---------------------+-------------------------------------+ diff --git a/doc/development.rst b/doc/development.rst index 602e4e347..cd59e3ec3 100644 --- a/doc/development.rst +++ b/doc/development.rst @@ -13,7 +13,7 @@ mailing list for development discussion. Some more information about the internals of this library can be found in the chapter :ref:`internalapi`. -There is also additional information on extending the ``can.io`` module. +There is also additional information on extending the ``pycan.io`` module. @@ -38,12 +38,12 @@ Creating a new interface/backend These steps are a guideline on how to add a new backend to python-can. - Create a module (either a ``*.py`` or an entire subdirectory depending - on the complexity) inside ``can.interfaces`` + on the complexity) inside ``pycan.interfaces`` - Implement the central part of the backend: the bus class that extends - :class:`can.BusABC`. + :class:`pycan.BusABC`. See :ref:`businternals` for more info on this one! - Register your backend bus class in ``can.interface.BACKENDS`` and - ``can.interfaces.VALID_INTERFACES`` in ``can.interfaces.__init__.py``. + ``can.interfaces.VALID_INTERFACES`` in ``pycan.interfaces.__init__.py``. - Add docs where appropriate. At a minimum add to ``doc/interfaces.rst`` and add a new interface specific document in ``doc/interface/*``. - Update ``doc/scripts.rst`` accordingly. @@ -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. diff --git a/doc/installation.rst b/doc/installation.rst index 147b27b74..44e43453a 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -2,10 +2,10 @@ Installation ============ -Install ``can`` with ``pip``: +Install ``pycan`` with ``pip``: :: - $ pip install python-can + $ pip install pythoncan As most likely you will want to interface with some hardware, you may diff --git a/doc/interfaces.rst b/doc/interfaces.rst index 7c8253f9e..e31e01e7f 100644 --- a/doc/interfaces.rst +++ b/doc/interfaces.rst @@ -1,7 +1,7 @@ CAN Interface Modules --------------------- -**python-can** hides the low-level, device-specific interfaces to controller +**pythoncan** hides the low-level, device-specific interfaces to controller area network adapters in interface dependant modules. However as each hardware device is different, you should carefully go through your interface's documentation. @@ -27,15 +27,15 @@ The available interfaces are: interfaces/systec Additional interfaces can be added via a plugin interface. An external package -can register a new interface by using the ``can.interface`` entry point in its setup.py. +can register a new interface by using the ``pycan.interface`` entry point in its setup.py. The format of the entry point is ``interface_name=module:classname`` where -``classname`` is a concrete :class:`can.BusABC` implementation. +``classname`` is a concrete :class:`pycan.BusABC` implementation. :: entry_points={ - 'can.interface': [ + 'pycan.interface': [ "interface_name=module:classname", ] }, diff --git a/doc/interfaces/canalystii.rst b/doc/interfaces/canalystii.rst index 687f61fcc..591f9b953 100644 --- a/doc/interfaces/canalystii.rst +++ b/doc/interfaces/canalystii.rst @@ -8,7 +8,7 @@ CANalyst-II(+) is a USB to CAN Analyzer. The controlcan library is originally de Bus --- -.. autoclass:: can.interfaces.canalystii.CANalystIIBus +.. autoclass:: pycan.interfaces.canalystii.CANalystIIBus .. _ZLG ZHIYUAN Electronics: http://www.zlg.com/can/can/product/id/42.html diff --git a/doc/interfaces/iscan.rst b/doc/interfaces/iscan.rst index dedb76a18..0d3edd18b 100644 --- a/doc/interfaces/iscan.rst +++ b/doc/interfaces/iscan.rst @@ -7,9 +7,9 @@ Interface for isCAN from `Thorsis Technologies GmbH`_, former ifak system GmbH. Bus --- -.. autoclass:: can.interfaces.iscan.IscanBus +.. autoclass:: pycan.interfaces.iscan.IscanBus -.. autoexception:: can.interfaces.iscan.IscanError +.. autoexception:: pycan.interfaces.iscan.IscanError .. _Thorsis Technologies GmbH: https://www.thorsis.com/en/industrial-automation/usb-interfaces/can/iscan-usb-interface/ diff --git a/doc/interfaces/ixxat.rst b/doc/interfaces/ixxat.rst index 9ab79ffcf..0cb0c995f 100644 --- a/doc/interfaces/ixxat.rst +++ b/doc/interfaces/ixxat.rst @@ -8,7 +8,7 @@ Interface to `IXXAT `__ Virtual CAN Interface V3 SDK. Wor The Linux ECI SDK is currently unsupported, however on Linux some devices are supported with :doc:`socketcan`. -The :meth:`~can.interfaces.ixxat.canlib.IXXATBus.send_periodic` method is supported +The :meth:`~pycan.interfaces.ixxat.canlib.IXXATBus.send_periodic` method is supported natively through the on-board cyclic transmit list. Modifying cyclic messages is not possible. You will need to stop it, and then start a new periodic message. @@ -17,10 +17,10 @@ start a new periodic message. Bus --- -.. autoclass:: can.interfaces.ixxat.IXXATBus +.. autoclass:: pycan.interfaces.ixxat.IXXATBus :members: -.. autoclass:: can.interfaces.ixxat.canlib.CyclicSendTask +.. autoclass:: pycan.interfaces.ixxat.canlib.CyclicSendTask :members: @@ -33,7 +33,7 @@ The simplest configuration file would be:: channel = 0 Python-can will search for the first IXXAT device available and open the first channel. -``interface`` and ``channel`` parameters are interpreted by frontend ``can.interfaces.interface`` +``interface`` and ``channel`` parameters are interpreted by frontend ``pycan.interfaces.interface`` module, while the following parameters are optional and are interpreted by IXXAT implementation. * ``bitrate`` (default 500000) Channel bitrate @@ -46,7 +46,7 @@ module, while the following parameters are optional and are interpreted by IXXAT Internals --------- -The IXXAT :class:`~can.BusABC` object is a fairly straightforward interface +The IXXAT :class:`~pycan.BusABC` object is a fairly straightforward interface to the IXXAT VCI library. It can open a specific device ID or use the first one found. diff --git a/doc/interfaces/kvaser.rst b/doc/interfaces/kvaser.rst index a4a51ad09..7b5b18209 100644 --- a/doc/interfaces/kvaser.rst +++ b/doc/interfaces/kvaser.rst @@ -9,7 +9,7 @@ Linux). Bus --- -.. autoclass:: can.interfaces.kvaser.canlib.KvaserBus +.. autoclass:: pycan.interfaces.kvaser.canlib.KvaserBus :members: :exclude-members: get_stats @@ -17,7 +17,7 @@ Bus Internals --------- -The Kvaser :class:`~can.Bus` object with a physical CAN Bus can be operated in two +The Kvaser :class:`~pycan.Bus` object with a physical CAN Bus can be operated in two modes; ``single_handle`` mode with one shared bus handle used for both reading and writing to the CAN bus, or with two separate bus handles. Two separate handles are needed if receiving and sending messages are done in @@ -45,4 +45,4 @@ Custom methods This section contains Kvaser driver specific methods. -.. automethod:: can.interfaces.kvaser.canlib.KvaserBus.get_stats +.. automethod:: pycan.interfaces.kvaser.canlib.KvaserBus.get_stats diff --git a/doc/interfaces/neovi.rst b/doc/interfaces/neovi.rst index dbb753479..46deef2ab 100644 --- a/doc/interfaces/neovi.rst +++ b/doc/interfaces/neovi.rst @@ -29,7 +29,7 @@ package. Configuration ------------- -An example `can.ini` file for windows 7: +An example `pycan.ini` file for windows 7: :: @@ -41,6 +41,6 @@ An example `can.ini` file for windows 7: Bus --- -.. autoclass:: can.interfaces.ics_neovi.NeoViBus +.. autoclass:: pycan.interfaces.ics_neovi.NeoViBus diff --git a/doc/interfaces/nican.rst b/doc/interfaces/nican.rst index b2214371f..ed242b62f 100644 --- a/doc/interfaces/nican.rst +++ b/doc/interfaces/nican.rst @@ -18,9 +18,9 @@ This interface adds support for CAN controllers by `National Instruments`_. Bus --- -.. autoclass:: can.interfaces.nican.NicanBus +.. autoclass:: pycan.interfaces.nican.NicanBus -.. autoexception:: can.interfaces.nican.NicanError +.. autoexception:: pycan.interfaces.nican.NicanError .. _National Instruments: http://www.ni.com/can/ diff --git a/doc/interfaces/pcan.rst b/doc/interfaces/pcan.rst index 9bbaec9cb..c7e940101 100644 --- a/doc/interfaces/pcan.rst +++ b/doc/interfaces/pcan.rst @@ -21,12 +21,12 @@ Here is an example configuration file for using `PCAN-USB = 3.4 supports the PCAN adapters natively via :doc:`/interfaces/socketc Bus --- -.. autoclass:: can.interfaces.pcan.PcanBus +.. autoclass:: pycan.interfaces.pcan.PcanBus diff --git a/doc/interfaces/serial.rst b/doc/interfaces/serial.rst index 413d9cfd1..9fcc9cc39 100644 --- a/doc/interfaces/serial.rst +++ b/doc/interfaces/serial.rst @@ -13,13 +13,13 @@ recording CAN traces. .. note:: The properties **extended_id**, **is_remote_frame** and **is_error_frame** - from the class:`~can.Message` are not in use. This interface will not + from the class:`~pycan.Message` are not in use. This interface will not send or receive flags for this properties. Bus --- -.. autoclass:: can.interfaces.serial.serial_can.SerialBus +.. autoclass:: pycan.interfaces.serial.serial_can.SerialBus Internals --------- diff --git a/doc/interfaces/slcan.rst b/doc/interfaces/slcan.rst index de182e8b8..ac8fb1bdd 100755 --- a/doc/interfaces/slcan.rst +++ b/doc/interfaces/slcan.rst @@ -26,7 +26,7 @@ Supported devices Bus --- -.. autoclass:: can.interfaces.slcan.slcanBus +.. autoclass:: pycan.interfaces.slcan.slcanBus :members: diff --git a/doc/interfaces/socketcan.rst b/doc/interfaces/socketcan.rst index bdd934ca7..76c864106 100644 --- a/doc/interfaces/socketcan.rst +++ b/doc/interfaces/socketcan.rst @@ -131,16 +131,16 @@ To spam a bus: .. code-block:: python import time - import can + import pycan bustype = 'socketcan' channel = 'vcan0' def producer(id): """:param id: Spam the bus with messages including the data id.""" - bus = can.interface.Bus(channel=channel, bustype=bustype) + bus = pycan.interface.Bus(channel=channel, bustype=bustype) for i in range(10): - msg = can.Message(arbitration_id=0xc0ffee, data=[id, i, 0, 1, 3, 1, 4, 1], is_extended_id=False) + msg = pycan.Message(arbitration_id=0xc0ffee, data=[id, i, 0, 1, 3, 1, 4, 1], is_extended_id=False) bus.send(msg) time.sleep(1) @@ -168,10 +168,10 @@ function: .. code-block:: python - import can + import pycan can_interface = 'vcan0' - bus = can.interface.Bus(can_interface, bustype='socketcan') + bus = pycan.interface.Bus(can_interface, bustype='socketcan') message = bus.recv() By default, this performs a blocking read, which means ``bus.recv()`` won't @@ -211,13 +211,13 @@ An example that uses the send_periodic is included in ``python-can/examples/cycl The object returned can be used to halt, alter or cancel the periodic message task. -.. autoclass:: can.interfaces.socketcan.CyclicSendTask +.. autoclass:: pycan.interfaces.socketcan.CyclicSendTask Bus --- -.. autoclass:: can.interfaces.socketcan.SocketcanBus +.. autoclass:: pycan.interfaces.socketcan.SocketcanBus .. method:: recv(timeout=None) @@ -226,8 +226,8 @@ Bus :param float timeout: seconds to wait for a message or None to wait indefinitely - :rtype: can.Message or None + :rtype: pycan.Message or None :return: - None on timeout or a :class:`can.Message` object. - :raises can.CanError: + None on timeout or a :class:`pycan.Message` object. + :raises pycan.CanError: if an error occurred while reading diff --git a/doc/interfaces/systec.rst b/doc/interfaces/systec.rst index 0aa4d9444..ff35ab1cc 100644 --- a/doc/interfaces/systec.rst +++ b/doc/interfaces/systec.rst @@ -31,7 +31,7 @@ The interface supports following devices: Bus --- -.. autoclass:: can.interfaces.systec.ucanbus.UcanBus +.. autoclass:: pycan.interfaces.systec.ucanbus.UcanBus :members: Configuration @@ -73,4 +73,4 @@ Periodic tasks The driver supports periodic message sending but without the possibility to set the interval between messages. Therefore the handling of the periodic messages is done -by the interface using the :class:`~can.broadcastmanager.ThreadBasedCyclicSendTask`. +by the interface using the :class:`~pycan.broadcastmanager.ThreadBasedCyclicSendTask`. diff --git a/doc/interfaces/usb2can.rst b/doc/interfaces/usb2can.rst index e2e8d7517..5e6d6fcbb 100644 --- a/doc/interfaces/usb2can.rst +++ b/doc/interfaces/usb2can.rst @@ -77,12 +77,12 @@ There are a few things that are kinda strange about this device and are not over Bus --- -.. autoclass:: can.interfaces.usb2can.Usb2canBus +.. autoclass:: pycan.interfaces.usb2can.Usb2canBus Internals --------- -.. autoclass:: can.interfaces.usb2can.Usb2CanAbstractionLayer +.. autoclass:: pycan.interfaces.usb2can.Usb2CanAbstractionLayer :members: :undoc-members: diff --git a/doc/interfaces/vector.rst b/doc/interfaces/vector.rst index a936e693e..7deda27c7 100644 --- a/doc/interfaces/vector.rst +++ b/doc/interfaces/vector.rst @@ -26,9 +26,9 @@ slow and CPU intensive polling will be used when waiting for new messages. Bus --- -.. autoclass:: can.interfaces.vector.VectorBus +.. autoclass:: pycan.interfaces.vector.VectorBus -.. autoexception:: can.interfaces.vector.VectorError +.. autoexception:: pycan.interfaces.vector.VectorError .. _Vector: https://vector.com/ diff --git a/doc/interfaces/virtual.rst b/doc/interfaces/virtual.rst index ed6681a57..00db9f4c5 100644 --- a/doc/interfaces/virtual.rst +++ b/doc/interfaces/virtual.rst @@ -11,12 +11,12 @@ others messages. .. code-block:: python - import can + import pycan - bus1 = can.interface.Bus('test', bustype='virtual') - bus2 = can.interface.Bus('test', bustype='virtual') + bus1 = pycan.interface.Bus('test', bustype='virtual') + bus2 = pycan.interface.Bus('test', bustype='virtual') - msg1 = can.Message(arbitration_id=0xabcde, data=[1,2,3]) + msg1 = pycan.Message(arbitration_id=0xabcde, data=[1,2,3]) bus1.send(msg1) msg2 = bus2.recv() diff --git a/doc/internal-api.rst b/doc/internal-api.rst index c43db3394..d09c7e321 100644 --- a/doc/internal-api.rst +++ b/doc/internal-api.rst @@ -14,53 +14,53 @@ Extending the ``BusABC`` class ------------------------------ Concrete implementations **must** implement the following: - * :meth:`~can.BusABC.send` to send individual messages - * :meth:`~can.BusABC._recv_internal` to receive individual messages + * :meth:`~pycan.BusABC.send` to send individual messages + * :meth:`~pycan.BusABC._recv_internal` to receive individual messages (see note below!) - * set the :attr:`~can.BusABC.channel_info` attribute to a string describing + * set the :attr:`~pycan.BusABC.channel_info` attribute to a string describing the underlying bus and/or channel They **might** implement the following: - * :meth:`~can.BusABC.flush_tx_buffer` to allow discarding any + * :meth:`~pycan.BusABC.flush_tx_buffer` to allow discarding any messages yet to be sent - * :meth:`~can.BusABC.shutdown` to override how the bus should + * :meth:`~pycan.BusABC.shutdown` to override how the bus should shut down - * :meth:`~can.BusABC._send_periodic_internal` to override the software based + * :meth:`~pycan.BusABC._send_periodic_internal` to override the software based periodic sending and push it down to the kernel or hardware. - * :meth:`~can.BusABC._apply_filters` to apply efficient filters + * :meth:`~pycan.BusABC._apply_filters` to apply efficient filters to lower level systems like the OS kernel or hardware. - * :meth:`~can.BusABC._detect_available_configs` to allow the interface + * :meth:`~pycan.BusABC._detect_available_configs` to allow the interface to report which configurations are currently available for new connections. - * :meth:`~can.BusABC.state` property to allow reading and/or changing + * :meth:`~pycan.BusABC.state` property to allow reading and/or changing the bus state. .. note:: - *TL;DR*: Only override :meth:`~can.BusABC._recv_internal`, - never :meth:`~can.BusABC.recv` directly. + *TL;DR*: Only override :meth:`~pycan.BusABC._recv_internal`, + never :meth:`~pycan.BusABC.recv` directly. - Previously, concrete bus classes had to override :meth:`~can.BusABC.recv` - directly instead of :meth:`~can.BusABC._recv_internal`, but that has + Previously, concrete bus classes had to override :meth:`~pycan.BusABC.recv` + directly instead of :meth:`~pycan.BusABC._recv_internal`, but that has changed to allow the abstract base class to handle in-software message filtering as a fallback. All internal interfaces now implement that new behaviour. Older (custom) interfaces might still be implemented like that and thus might not provide message filtering: -Concrete instances are usually created by :class:`can.Bus` which takes the users +Concrete instances are usually created by :class:`pycan.Bus` which takes the users configuration into account. Bus Internals ~~~~~~~~~~~~~ -Several methods are not documented in the main :class:`can.BusABC` +Several methods are not documented in the main :class:`pycan.BusABC` as they are primarily useful for library developers as opposed to library users. This is the entire ABC bus class with all internal methods: -.. autoclass:: can.BusABC +.. autoclass:: pycan.BusABC :private-members: :special-members: :noindex: @@ -70,11 +70,11 @@ methods: About the IO module ------------------- -Handling of the different file formats is implemented in :mod:`can.io`. +Handling of the different file formats is implemented in :mod:`pycan.io`. Each file/IO type is within a separate module and ideally implements both a *Reader* and a *Writer*. -The reader usually extends :class:`can.io.generic.BaseIOHandler`, while -the writer often additionally extends :class:`can.Listener`, -to be able to be passed directly to a :class:`can.Notifier`. +The reader usually extends :class:`pycan.io.generic.BaseIOHandler`, while +the writer often additionally extends :class:`pycan.Listener`, +to be able to be passed directly to a :class:`pycan.Notifier`. @@ -84,13 +84,13 @@ Adding support for new file formats This assumes that you want to add a new file format, called *canstore*. Ideally add both reading and writing support for the new file format, although this is not strictly required. -1. Create a new module: *can/io/canstore.py* - (*or* simply copy some existing one like *can/io/csv.py*) -2. Implement a reader ``CanstoreReader`` (which often extends :class:`can.io.generic.BaseIOHandler`, but does not have to). +1. Create a new module: *pycan/io/canstore.py* + (*or* simply copy some existing one like *pycan/io/csv.py*) +2. Implement a reader ``CanstoreReader`` (which often extends :class:`pycan.io.generic.BaseIOHandler`, but does not have to). Besides from a constructor, only ``__iter__(self)`` needs to be implemented. -3. Implement a writer ``CanstoreWriter`` (which often extends :class:`can.io.generic.BaseIOHandler` and :class:`can.Listener`, but does not have to). +3. Implement a writer ``CanstoreWriter`` (which often extends :class:`pycan.io.generic.BaseIOHandler` and :class:`pycan.Listener`, but does not have to). Besides from a constructor, only ``on_message_received(self, msg)`` needs to be implemented. -4. Add a case to ``can.io.player.LogReader``'s ``__new__()``. +4. Add a case to ``pycan.io.player.LogReader``'s ``__new__()``. 5. Document the two new classes (and possibly additional helpers) with docstrings and comments. Please mention features and limitations of the implementation. 6. Add a short section to the bottom of *doc/listeners.rst*. @@ -98,8 +98,8 @@ Ideally add both reading and writing support for the new file format, although t `class TestCanstoreFileFormat(ReaderWriterTest)` to *test/logformats_test.py*. That should already handle all of the general testing. Just follow the way the other tests in there do it. -8. Add imports to *can/__init__py* and *can/io/__init__py* so that the - new classes can be simply imported as *from can import CanstoreReader, CanstoreWriter*. +8. Add imports to *pycan/__init__py* and *pycan/io/__init__py* so that the + new classes can be simply imported as *from pycan import CanstoreReader, CanstoreWriter*. @@ -107,7 +107,7 @@ IO Utilities ~~~~~~~~~~~~ -.. automodule:: can.io.generic +.. automodule:: pycan.io.generic :members: @@ -116,5 +116,5 @@ Other Utilities --------------- -.. automodule:: can.util +.. automodule:: pycan.util :members: diff --git a/doc/listeners.rst b/doc/listeners.rst index 975de6fd1..32c576711 100644 --- a/doc/listeners.rst +++ b/doc/listeners.rst @@ -16,10 +16,10 @@ Subclasses of Listener that do not override **on_message_received** will cause :class:`NotImplementedError` to be thrown when a message is received on the CAN bus. -.. autoclass:: can.Listener +.. autoclass:: pycan.Listener :members: -There are some listeners that already ship together with `python-can` +There are some listeners that already ship together with `pythoncan` and are listed below. Some of them allow messages to be written to files, and the corresponding file readers are also documented here. @@ -34,47 +34,47 @@ readers are also documented here. BufferedReader -------------- -.. autoclass:: can.BufferedReader +.. autoclass:: pycan.BufferedReader :members: -.. autoclass:: can.AsyncBufferedReader +.. autoclass:: pycan.AsyncBufferedReader :members: Logger ------ -The :class:`can.Logger` uses the following :class:`can.Listener` types to +The :class:`pycan.Logger` uses the following :class:`pycan.Listener` types to create log files with different file types of the messages received. -.. autoclass:: can.Logger +.. autoclass:: pycan.Logger :members: Printer ------- -.. autoclass:: can.Printer +.. autoclass:: pycan.Printer :members: CSVWriter --------- -.. autoclass:: can.CSVWriter +.. autoclass:: pycan.CSVWriter :members: -.. autoclass:: can.CSVReader +.. autoclass:: pycan.CSVReader :members: SqliteWriter ------------ -.. autoclass:: can.SqliteWriter +.. autoclass:: pycan.SqliteWriter :members: -.. autoclass:: can.SqliteReader +.. autoclass:: pycan.SqliteReader :members: @@ -113,7 +113,7 @@ engineered from existing log files. One description of the format can be found ` Channels will be converted to integers. -.. autoclass:: can.ASCWriter +.. autoclass:: pycan.ASCWriter :members: ASCReader reads CAN data from ASCII log files .asc, @@ -121,7 +121,7 @@ as further references can-utils can be used: `asc2log `_, `log2asc `_. -.. autoclass:: can.ASCReader +.. autoclass:: pycan.ASCReader :members: @@ -134,12 +134,12 @@ As specification following references can-utils can be used: `log2asc `_. -.. autoclass:: can.CanutilsLogWriter +.. autoclass:: pycan.CanutilsLogWriter :members: **CanutilsLogReader** reads CAN data from ASCII log files .log -.. autoclass:: can.CanutilsLogReader +.. autoclass:: pycan.CanutilsLogReader :members: @@ -153,10 +153,10 @@ The data is stored in a compressed format which makes it very compact. .. note:: Channels will be converted to integers. -.. autoclass:: can.BLFWriter +.. autoclass:: pycan.BLFWriter :members: The following class can be used to read messages from BLF file: -.. autoclass:: can.BLFReader +.. autoclass:: pycan.BLFReader :members: diff --git a/doc/message.rst b/doc/message.rst index 921748cb9..a376dfbc6 100644 --- a/doc/message.rst +++ b/doc/message.rst @@ -1,14 +1,14 @@ Message ======= -.. module:: can +.. module:: pycan .. autoclass:: Message - One can instantiate a :class:`~can.Message` defining data, and optional + One can instantiate a :class:`~pycan.Message` defining data, and optional arguments for all attributes such as arbitration ID, flags, and timestamp. - >>> from can import Message + >>> from pycan import Message >>> test = Message(data=[1, 2, 3, 4, 5]) >>> test.data bytearray(b'\x01\x02\x03\x04\x05') @@ -18,10 +18,10 @@ Message Timestamp: 0.000000 ID: 00000000 010 DLC: 5 01 02 03 04 05 - The :attr:`~can.Message.arbitration_id` field in a CAN message may be either + The :attr:`~pycan.Message.arbitration_id` field in a CAN message may be either 11 bits (standard addressing, CAN 2.0A) or 29 bits (extended addressing, CAN - 2.0B) in length, and ``python-can`` exposes this difference with the - :attr:`~can.Message.is_extended_id` attribute. + 2.0B) in length, and ``pythoncan`` exposes this difference with the + :attr:`~pycan.Message.is_extended_id` attribute. .. attribute:: timestamp @@ -58,7 +58,7 @@ Message >>> print(Message(data=example_data)) Timestamp: 0.000000 ID: 00000000 X DLC: 3 01 02 03 - A :class:`~can.Message` can also be created with bytes, or lists of ints: + A :class:`~pycan.Message` can also be created with bytes, or lists of ints: >>> m1 = Message(data=[0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66]) >>> print(m1.data) @@ -102,7 +102,7 @@ Message :type: bool - This flag controls the size of the :attr:`~can.Message.arbitration_id` field. + This flag controls the size of the :attr:`~pycan.Message.arbitration_id` field. Previously this was exposed as `id_type`. >>> print(Message(is_extended_id=False)) @@ -164,7 +164,7 @@ Message A string representation of a CAN message: - >>> from can import Message + >>> from pycan import Message >>> test = Message() >>> print(test) Timestamp: 0.000000 ID: 00000000 X DLC: 0 @@ -183,9 +183,9 @@ Message The flags field is represented as one, two or three letters: - - X if the :attr:`~can.Message.is_extended_id` attribute is set, otherwise S, - - E if the :attr:`~can.Message.is_error_frame` attribute is set, - - R if the :attr:`~can.Message.is_remote_frame` attribute is set. + - X if the :attr:`~pycan.Message.is_extended_id` attribute is set, otherwise S, + - E if the :attr:`~pycan.Message.is_error_frame` attribute is set, + - R if the :attr:`~pycan.Message.is_remote_frame` attribute is set. The arbitration ID field is represented as either a four or eight digit hexadecimal number depending on the length of the arbitration ID diff --git a/doc/scripts.rst b/doc/scripts.rst index a63f1b108..0ffe8c46a 100644 --- a/doc/scripts.rst +++ b/doc/scripts.rst @@ -1,26 +1,26 @@ Scripts ======= -The following modules are callable from python-can. +The following modules are callable from pythoncan. -They can be called for example by ``python -m can.logger`` or ``can_logger.py`` (if installed using pip). +They can be called for example by ``python -m pycan.logger`` or ``can_logger.py`` (if installed using pip). -can.logger +pycan.logger ---------- Command line help, called with ``--help``: -.. command-output:: python -m can.logger -h +.. command-output:: python -m pycan.logger -h -can.player +pycan.player ---------- -.. command-output:: python -m can.player -h +.. command-output:: python -m pycan.player -h -can.viewer +pycan.viewer ---------- A screenshot of the application can be seen below: @@ -33,9 +33,9 @@ The first column is the number of times a frame with the particular ID that has Command line arguments ^^^^^^^^^^^^^^^^^^^^^^ -By default the ``can.viewer`` uses the :doc:`/interfaces/socketcan` interface. All interfaces are supported and can be specified using the ``-i`` argument or configured following :doc:`/configuration`. +By default the ``pycan.viewer`` uses the :doc:`/interfaces/socketcan` interface. All interfaces are supported and can be specified using the ``-i`` argument or configured following :doc:`/configuration`. The full usage page can be seen below: -.. command-output:: python -m can.viewer -h +.. command-output:: python -m pycan.viewer -h diff --git a/examples/asyncio_demo.py b/examples/asyncio_demo.py index 3e71ae6db..abccad4c5 100644 --- a/examples/asyncio_demo.py +++ b/examples/asyncio_demo.py @@ -1,14 +1,14 @@ import asyncio -import can +import pycan def print_message(msg): """Regular callback function. Can also be a coroutine.""" print(msg) async def main(): - can0 = can.Bus('vcan0', bustype='virtual', receive_own_messages=True) - reader = can.AsyncBufferedReader() - logger = can.Logger('logfile.asc') + can0 = pycan.Bus('vcan0', bustype='virtual', receive_own_messages=True) + reader = pycan.AsyncBufferedReader() + logger = pycan.Logger('logfile.asc') listeners = [ print_message, # Callback function @@ -17,9 +17,9 @@ async def main(): ] # Create Notifier with an explicit loop to use for scheduling of callbacks loop = asyncio.get_event_loop() - notifier = can.Notifier(can0, listeners, loop=loop) + notifier = pycan.Notifier(can0, listeners, loop=loop) # Start sending first message - can0.send(can.Message(arbitration_id=0)) + can0.send(pycan.Message(arbitration_id=0)) print('Bouncing 10 messages...') for _ in range(10): diff --git a/examples/cyclic.py b/examples/cyclic.py index 021af14bf..138a6150d 100755 --- a/examples/cyclic.py +++ b/examples/cyclic.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - """ This example exercises the periodic sending capabilities. @@ -15,7 +13,7 @@ import logging import time -import can +import pycan logging.basicConfig(level=logging.INFO) @@ -26,9 +24,9 @@ def simple_periodic_send(bus): Sleeps for 2 seconds then stops the task. """ print("Starting to send a message every 200ms for 2s") - msg = can.Message(arbitration_id=0x123, data=[1, 2, 3, 4, 5, 6], is_extended_id=False) + msg = pycan.Message(arbitration_id=0x123, data=[1, 2, 3, 4, 5, 6], is_extended_id=False) task = bus.send_periodic(msg, 0.20) - assert isinstance(task, can.CyclicSendTaskABC) + assert isinstance(task, pycan.CyclicSendTaskABC) time.sleep(2) task.stop() print("stopped cyclic send") @@ -36,9 +34,9 @@ def simple_periodic_send(bus): def limited_periodic_send(bus): print("Starting to send a message every 200ms for 1s") - msg = can.Message(arbitration_id=0x12345678, data=[0, 0, 0, 0, 0, 0], is_extended_id=True) + msg = pycan.Message(arbitration_id=0x12345678, data=[0, 0, 0, 0, 0, 0], is_extended_id=True) task = bus.send_periodic(msg, 0.20, 1, store_task=False) - if not isinstance(task, can.LimitedDurationCyclicSendTaskABC): + if not isinstance(task, pycan.LimitedDurationCyclicSendTaskABC): print("This interface doesn't seem to support a ") task.stop() return @@ -53,9 +51,9 @@ def limited_periodic_send(bus): def test_periodic_send_with_modifying_data(bus): print("Starting to send a message every 200ms. Initial data is ones") - msg = can.Message(arbitration_id=0x0cf02200, data=[1, 1, 1, 1]) + msg = pycan.Message(arbitration_id=0x0cf02200, data=[1, 1, 1, 1]) task = bus.send_periodic(msg, 0.20) - if not isinstance(task, can.ModifiableCyclicTaskABC): + if not isinstance(task, pycan.ModifiableCyclicTaskABC): print("This interface doesn't seem to support modification") task.stop() return @@ -83,9 +81,9 @@ def test_periodic_send_with_modifying_data(bus): # interfaces will continue to support it... but the top level api won't. # def test_dual_rate_periodic_send(): # """Send a message 10 times at 1ms intervals, then continue to send every 500ms""" -# msg = can.Message(arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5]) +# msg = pycan.Message(arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5]) # print("Creating cyclic task to send message 10 times at 1ms, then every 500ms") -# task = can.interface.MultiRateCyclicSendTask('vcan0', msg, 10, 0.001, 0.50) +# task = pycan.interface.MultiRateCyclicSendTask('vcan0', msg, 10, 0.001, 0.50) # time.sleep(2) # # print("Changing data[0] = 0x42") @@ -107,15 +105,15 @@ def test_periodic_send_with_modifying_data(bus): if __name__ == "__main__": - reset_msg = can.Message(arbitration_id=0x00, data=[0, 0, 0, 0, 0, 0], is_extended_id=False) + reset_msg = pycan.Message(arbitration_id=0x00, data=[0, 0, 0, 0, 0, 0], is_extended_id=False) for interface, channel in [ - ('socketcan', 'vcan0'), - #('ixxat', 0) + ('socketcan', 'vcan0'), + #('ixxat', 0) ]: print("Carrying out cyclic tests with {} interface".format(interface)) - bus = can.Bus(interface=interface, channel=channel, bitrate=500000) + bus = pycan.Bus(interface=interface, channel=channel, bitrate=500000) bus.send(reset_msg) simple_periodic_send(bus) diff --git a/examples/receive_all.py b/examples/receive_all.py index 44a495de7..207773772 100755 --- a/examples/receive_all.py +++ b/examples/receive_all.py @@ -2,15 +2,15 @@ from __future__ import print_function -import can -from can.bus import BusState +import pycan +from pycan.bus import BusState def receive_all(): - bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) - #bus = can.interface.Bus(bustype='ixxat', channel=0, bitrate=250000) - #bus = can.interface.Bus(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000) + bus = pycan.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) + #bus = pycan.interface.Bus(bustype='ixxat', channel=0, bitrate=250000) + #bus = pycan.interface.Bus(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000) bus.state = BusState.ACTIVE # or BusState.PASSIVE diff --git a/examples/send_one.py b/examples/send_one.py index 2533ca37c..2ea61130e 100755 --- a/examples/send_one.py +++ b/examples/send_one.py @@ -1,35 +1,33 @@ #!/usr/bin/env python -# coding: utf-8 - """ This example shows how sending a single message works. """ from __future__ import print_function -import can +import pycan def send_one(): # this uses the default configuration (for example from the config file) # see https://python-can.readthedocs.io/en/stable/configuration.html - bus = can.interface.Bus() + bus = pycan.interface.Bus() # Using specific buses works similar: - # bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000) - # bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) - # bus = can.interface.Bus(bustype='ixxat', channel=0, bitrate=250000) - # bus = can.interface.Bus(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000) + # bus = pycan.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000) + # bus = pycan.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) + # bus = pycan.interface.Bus(bustype='ixxat', channel=0, bitrate=250000) + # bus = pycan.interface.Bus(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000) # ... - msg = can.Message(arbitration_id=0xc0ffee, - data=[0, 25, 0, 1, 3, 1, 4, 1], - is_extended_id=True) + msg = pycan.Message(arbitration_id=0xc0ffee, + data=[0, 25, 0, 1, 3, 1, 4, 1], + is_extended_id=True) try: bus.send(msg) print("Message sent on {}".format(bus.channel_info)) - except can.CanError: + except pycan.CanError: print("Message NOT sent") if __name__ == '__main__': diff --git a/examples/serial_com.py b/examples/serial_com.py index efa0bcdb5..fb1df0f54 100755 --- a/examples/serial_com.py +++ b/examples/serial_com.py @@ -1,8 +1,6 @@ #!/usr/bin/env python -# coding: utf-8 - """ -This example sends every second a messages over the serial interface and also +This example sends every second a messages over the serial interface and also receives incoming messages. python3 -m examples.serial_com @@ -24,7 +22,7 @@ import time import threading -import can +import pycan def send_cyclic(bus, msg, stop_event): @@ -47,11 +45,11 @@ def receive(bus, stop_event): print("Stopped receiving messages") if __name__ == "__main__": - server = can.interface.Bus(bustype='serial', channel='/dev/ttyS10') - client = can.interface.Bus(bustype='serial', channel='/dev/ttyS11') + server = pycan.interface.Bus(bustype='serial', channel='/dev/ttyS10') + client = pycan.interface.Bus(bustype='serial', channel='/dev/ttyS11') - tx_msg = can.Message(arbitration_id=0x01, data=[0x11, 0x22, 0x33, 0x44, - 0x55, 0x66, 0x77, 0x88]) + tx_msg = pycan.Message(arbitration_id=0x01, data=[0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88]) # Thread for sending and receiving messages stop_event = threading.Event() diff --git a/examples/simple_log_converter.py b/examples/simple_log_converter.py index 782ac9b7c..5732a27be 100755 --- a/examples/simple_log_converter.py +++ b/examples/simple_log_converter.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - """ Use this to convert .can/.asc files to .log files. @@ -9,11 +7,11 @@ import sys -import can.io.logger -import can.io.player +import pycan.io.logger +import pycan.io.player -reader = can.io.player.LogReader(sys.argv[1]) -writer = can.io.logger.Logger(sys.argv[2]) +reader = pycan.io.player.LogReader(sys.argv[1]) +writer = pycan.io.logger.Logger(sys.argv[2]) for msg in reader: writer.on_message_received(msg) diff --git a/examples/vcan_filtered.py b/examples/vcan_filtered.py index cf7e1f8e3..fdba5443b 100755 --- a/examples/vcan_filtered.py +++ b/examples/vcan_filtered.py @@ -1,24 +1,22 @@ #!/usr/bin/env python -# coding: utf-8 - """ This shows how message filtering works. """ import time -import can +import pycan if __name__ == '__main__': - bus = can.interface.Bus(bustype='socketcan', - channel='vcan0', - receive_own_messages=True) + bus = pycan.interface.Bus(bustype='socketcan', + channel='vcan0', + receive_own_messages=True) can_filters = [{"can_id": 1, "can_mask": 0xf, "extended": True}] bus.set_filters(can_filters) - notifier = can.Notifier(bus, [can.Printer()]) - bus.send(can.Message(arbitration_id=1, is_extended_id=True)) - bus.send(can.Message(arbitration_id=2, is_extended_id=True)) - bus.send(can.Message(arbitration_id=1, is_extended_id=False)) + notifier = pycan.Notifier(bus, [pycan.Printer()]) + bus.send(pycan.Message(arbitration_id=1, is_extended_id=True)) + bus.send(pycan.Message(arbitration_id=2, is_extended_id=True)) + bus.send(pycan.Message(arbitration_id=1, is_extended_id=False)) time.sleep(10) diff --git a/examples/virtual_can_demo.py b/examples/virtual_can_demo.py index b69fb28da..8dfb4cdef 100755 --- a/examples/virtual_can_demo.py +++ b/examples/virtual_can_demo.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - """ This demo creates multiple processes of producers to spam a socketcan bus. """ @@ -8,7 +6,7 @@ from time import sleep from concurrent.futures import ProcessPoolExecutor -import can +import pycan def producer(id, message_count=16): @@ -17,9 +15,9 @@ def producer(id, message_count=16): :param int id: the id of the thread/process """ - with can.Bus(bustype='socketcan', channel='vcan0') as bus: + with pycan.Bus(bustype='socketcan', channel='vcan0') as bus: for i in range(message_count): - msg = can.Message(arbitration_id=0x0cf02200+id, data=[id, i, 0, 1, 3, 1, 4, 1]) + msg = pycan.Message(arbitration_id=0x0cf02200+id, data=[id, i, 0, 1, 3, 1, 4, 1]) bus.send(msg) sleep(1.0) diff --git a/can/CAN.py b/pycan/CAN.py similarity index 70% rename from can/CAN.py rename to pycan/CAN.py index 0ed96dfb1..777b911d4 100644 --- a/can/CAN.py +++ b/pycan/CAN.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ This module was once the core of python-can, containing implementations of all the major classes in the library, now @@ -8,15 +6,15 @@ WARNING: This module is deprecated an will get removed in version 3.x. -Please use ``import can`` instead. +Please use ``import pycan`` instead. """ from __future__ import absolute_import -from can.message import Message -from can.listener import Listener, BufferedReader, RedirectReader -from can.util import set_logging_level -from can.io import * +from pycan.message import Message +from pycan.listener import Listener, BufferedReader, RedirectReader +from pycan.util import set_logging_level +from pycan.io import * import warnings @@ -26,4 +24,4 @@ # Version 3.x: DeprecationWarning # Version 4.0: Remove the module warnings.warn('Loading python-can via the old "CAN" API is deprecated since v3.0 an will get removed in v4.0 ' - 'Please use `import can` instead.', DeprecationWarning) + 'Please use `import pycan` instead.', DeprecationWarning) diff --git a/can/__init__.py b/pycan/__init__.py similarity index 61% rename from can/__init__.py rename to pycan/__init__.py index a612363ae..5cadb4125 100644 --- a/can/__init__.py +++ b/pycan/__init__.py @@ -1,25 +1,20 @@ -# coding: utf-8 - """ -``can`` is an object-orient Controller Area Network (CAN) interface module. +``pycan`` is an object-orient Controller Area Network (CAN) interface module """ from __future__ import absolute_import import logging -__version__ = "3.2.0" +__version__ = "3.3.4" -log = logging.getLogger('can') +log = logging.getLogger('pycan') rc = dict() class CanError(IOError): - """Indicates an error with the CAN network. - - """ - pass + """Indicates an error with the CAN network""" from .listener import Listener, BufferedReader, RedirectReader @@ -45,9 +40,9 @@ class CanError(IOError): from . import interface from .interface import Bus, detect_available_configs -from .broadcastmanager import send_periodic, \ - CyclicSendTaskABC, \ - LimitedDurationCyclicSendTaskABC, \ - ModifiableCyclicTaskABC, \ - MultiRateCyclicSendTaskABC, \ - RestartableCyclicTaskABC +from .broadcastmanager import (send_periodic, + CyclicSendTaskABC, + LimitedDurationCyclicSendTaskABC, + ModifiableCyclicTaskABC, + MultiRateCyclicSendTaskABC, + RestartableCyclicTaskABC) diff --git a/can/broadcastmanager.py b/pycan/broadcastmanager.py similarity index 86% rename from can/broadcastmanager.py rename to pycan/broadcastmanager.py index 79d586744..cd2762886 100644 --- a/can/broadcastmanager.py +++ b/pycan/broadcastmanager.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Exposes several methods for transmitting cyclic messages. @@ -13,7 +11,7 @@ import time import warnings -log = logging.getLogger('can.bcm') +log = logging.getLogger('pycan.bcm') class CyclicTask(object): @@ -25,7 +23,7 @@ class CyclicTask(object): def stop(self): """Cancel this periodic task. - :raises can.CanError: + :raises pycan.CanError: If stop is called on an already stopped task. """ @@ -37,7 +35,7 @@ class CyclicSendTaskABC(CyclicTask): def __init__(self, message, period): """ - :param can.Message message: The message to be sent periodically. + :param pycan.Message message: The message to be sent periodically. :param float period: The rate in seconds at which to send the message. """ self.message = message @@ -52,7 +50,7 @@ class LimitedDurationCyclicSendTaskABC(CyclicSendTaskABC): def __init__(self, message, period, duration): """Message send task with a defined duration and period. - :param can.Message message: The message to be sent periodically. + :param pycan.Message message: The message to be sent periodically. :param float period: The rate in seconds at which to send the message. :param float duration: The duration to keep sending this message at given rate. @@ -77,8 +75,8 @@ def modify_data(self, message): """Update the contents of this periodically sent message without altering the timing. - :param can.Message message: - The message with the new :attr:`can.Message.data`. + :param pycan.Message message: + The message with the new :attr:`pycan.Message.data`. Note: The arbitration ID cannot be changed. """ self.message = message @@ -94,7 +92,7 @@ def __init__(self, channel, message, count, initial_period, subsequent_period): transmit message at `subsequent_period`. :param channel: See interface specific documentation. - :param can.Message message: + :param pycan.Message message: :param int count: :param float initial_period: :param float subsequent_period: @@ -146,13 +144,13 @@ def _run(self): def send_periodic(bus, message, period, *args, **kwargs): """ - Send a :class:`~can.Message` every `period` seconds on the given bus. + Send a :class:`~pycan.Message` every `period` seconds on the given bus. - :param can.BusABC bus: A CAN bus which supports sending. - :param can.Message message: Message to send periodically. + :param pycan.BusABC bus: A CAN bus which supports sending. + :param pycan.Message message: Message to send periodically. :param float period: The minimum time between sending messages. :return: A started task instance """ - warnings.warn("The function `can.send_periodic` is deprecated and will " + - "be removed in an upcoming version. Please use `can.Bus.send_periodic` instead.", DeprecationWarning) + warnings.warn("The function `pycan.send_periodic` is deprecated and will " + + "be removed in an upcoming version. Please use `pycan.Bus.send_periodic` instead.", DeprecationWarning) return bus.send_periodic(message, period, *args, **kwargs) diff --git a/can/bus.py b/pycan/bus.py similarity index 89% rename from can/bus.py rename to pycan/bus.py index 2b36b3c57..df3cae37e 100644 --- a/can/bus.py +++ b/pycan/bus.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Contains the ABC bus implementation and its documentation. """ @@ -10,7 +8,6 @@ import logging import threading from time import time -from collections import namedtuple from aenum import Enum, auto from .broadcastmanager import ThreadBasedCyclicSendTask @@ -19,7 +16,7 @@ class BusState(Enum): - """The state in which a :class:`can.BusABC` can be.""" + """The state in which a :class:`pycan.BusABC` can be""" ACTIVE = auto() PASSIVE = auto() @@ -50,7 +47,7 @@ def __init__(self, channel, can_filters=None, **kwargs): The can interface identifier. Expected type is backend dependent. :param list can_filters: - See :meth:`~can.BusABC.set_filters` for details. + See :meth:`~pycan.BusABC.set_filters` for details. :param dict kwargs: Any backend dependent configurations are passed in this dictionary @@ -68,10 +65,10 @@ def recv(self, timeout=None): :param timeout: seconds to wait for a message or None to wait indefinitely - :rtype: can.Message or None + :rtype: pycan.Message or None :return: - None on timeout or a :class:`can.Message` object. - :raises can.CanError: + None on timeout or a :class:`pycan.Message` object. + :raises pycan.CanError: if an error occurred while reading """ start = time() @@ -105,21 +102,21 @@ def recv(self, timeout=None): def _recv_internal(self, timeout): """ Read a message from the bus and tell whether it was filtered. - This methods may be called by :meth:`~can.BusABC.recv` + This methods may be called by :meth:`~pycan.BusABC.recv` to read a message multiple times if the filters set by - :meth:`~can.BusABC.set_filters` do not match and the call has + :meth:`~pycan.BusABC.set_filters` do not match and the call has not yet timed out. New implementations should always override this method instead of - :meth:`~can.BusABC.recv`, to be able to take advantage of the - software based filtering provided by :meth:`~can.BusABC.recv` + :meth:`~pycan.BusABC.recv`, to be able to take advantage of the + software based filtering provided by :meth:`~pycan.BusABC.recv` as a fallback. This method should never be called directly. .. note:: This method is not an `@abstractmethod` (for now) to allow older external implementations to continue using their existing - :meth:`~can.BusABC.recv` implementation. + :meth:`~pycan.BusABC.recv` implementation. .. note:: @@ -128,18 +125,18 @@ def _recv_internal(self, timeout): Kvaser interface. Thus it cannot be simplified to a constant value. :param float timeout: seconds to wait for a message, - see :meth:`~can.BusABC.send` + see :meth:`~pycan.BusABC.send` - :rtype: tuple[can.Message, bool] or tuple[None, bool] + :rtype: tuple[pycan.Message, bool] or tuple[None, bool] :return: 1. a message that was read or None on timeout 2. a bool that is True if message filtering has already been done and else False - :raises can.CanError: + :raises pycan.CanError: if an error occurred while reading :raises NotImplementedError: - if the bus provides it's own :meth:`~can.BusABC.recv` + if the bus provides it's own :meth:`~pycan.BusABC.recv` implementation (legacy implementation) """ @@ -151,7 +148,7 @@ def send(self, msg, timeout=None): Override this method to enable the transmit path. - :param can.Message msg: A message object. + :param pycan.Message msg: A message object. :type timeout: float or None :param timeout: @@ -161,7 +158,7 @@ def send(self, msg, timeout=None): Might not be supported by all interfaces. None blocks indefinitely. - :raises can.CanError: + :raises pycan.CanError: if the message could not be sent """ raise NotImplementedError("Trying to write to a readonly bus?") @@ -177,7 +174,7 @@ def send_periodic(self, msg, period, duration=None, store_task=True): - :meth:`BusABC.stop_all_periodic_tasks()` is called - the task's :meth:`CyclicTask.stop()` method is called. - :param can.Message msg: + :param pycan.Message msg: Message to transmit :param float period: Period in seconds between each message @@ -190,7 +187,7 @@ def send_periodic(self, msg, period, duration=None, store_task=True): :return: A started task instance. Note the task can be stopped (and depending on the backend modified) by calling the :meth:`stop` method. - :rtype: can.broadcastmanager.CyclicSendTaskABC + :rtype: pycan.broadcastmanager.CyclicSendTaskABC .. note:: @@ -228,7 +225,7 @@ def _send_periodic_internal(self, msg, period, duration=None): Override this method to enable a more efficient backend specific approach. - :param can.Message msg: + :param pycan.Message msg: Message to transmit :param float period: Period in seconds between each message @@ -238,7 +235,7 @@ def _send_periodic_internal(self, msg, period, duration=None): :return: A started task instance. Note the task can be stopped (and depending on the backend modified) by calling the :meth:`stop` method. - :rtype: can.broadcastmanager.CyclicSendTaskABC + :rtype: pycan.broadcastmanager.CyclicSendTaskABC """ if not hasattr(self, "_lock_send_periodic"): # Create a send lock for this bus @@ -263,7 +260,7 @@ def __iter__(self): :yields: - :class:`can.Message` msg objects. + :class:`pycan.Message` msg objects. """ while True: msg = self.recv(timeout=1.0) @@ -273,7 +270,7 @@ def __iter__(self): @property def filters(self): """ - Modify the filters of this bus. See :meth:`~can.BusABC.set_filters` + Modify the filters of this bus. See :meth:`~pycan.BusABC.set_filters` for details. """ return self._filters @@ -313,18 +310,17 @@ def _apply_filters(self, filters): hardware if supported/implemented by the interface. :param Iterator[dict] filters: - See :meth:`~can.BusABC.set_filters` for details. + See :meth:`~pycan.BusABC.set_filters` for details. """ - pass def _matches_filters(self, msg): """Checks whether the given message matches at least one of the - current filters. See :meth:`~can.BusABC.set_filters` for details + current filters. See :meth:`~pycan.BusABC.set_filters` for details on how the filters work. This method should not be overridden. - :param can.Message msg: + :param pycan.Message msg: the message to check if matching :rtype: bool :return: whether the given message matches at least one filter @@ -356,14 +352,12 @@ def _matches_filters(self, msg): def flush_tx_buffer(self): """Discard every message that may be queued in the output buffer(s). """ - pass def shutdown(self): """ Called to carry out any interface specific cleanup required in shutting down a bus. """ - pass def __enter__(self): return self @@ -376,7 +370,7 @@ def state(self): """ Return the current state of the hardware - :type: can.BusState + :type: pycan.BusState """ return BusState.ACTIVE @@ -385,7 +379,7 @@ def state(self, new_state): """ Set the new state of the hardware - :type: can.BusState + :type: pycan.BusState """ raise NotImplementedError("Property is not implemented.") diff --git a/can/ctypesutil.py b/pycan/ctypesutil.py similarity index 97% rename from can/ctypesutil.py rename to pycan/ctypesutil.py index 8a69b8df9..0e3fcfa7c 100644 --- a/can/ctypesutil.py +++ b/pycan/ctypesutil.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ This module contains common `ctypes` utils. """ @@ -9,7 +7,7 @@ import logging import sys -log = logging.getLogger('can.ctypesutil') +log = logging.getLogger('pycan.ctypesutil') __all__ = ['CLibrary', 'HANDLE', 'PHANDLE', 'HRESULT'] diff --git a/can/interface.py b/pycan/interface.py similarity index 88% rename from can/interface.py rename to pycan/interface.py index 6c830d0c4..d3bfb6a28 100644 --- a/can/interface.py +++ b/pycan/interface.py @@ -1,7 +1,5 @@ -# coding: utf-8 - """ -This module contains the base implementation of :class:`can.BusABC` as well +This module contains the base implementation of :class:`pycan.BusABC` as well as a list of all available backends and some implemented CyclicSendTasks. """ @@ -12,22 +10,15 @@ import importlib import logging -import can from .bus import BusABC -from .broadcastmanager import CyclicSendTaskABC, MultiRateCyclicSendTaskABC from .util import load_config from .interfaces import BACKENDS -if 'linux' in sys.platform: - # Deprecated and undocumented access to SocketCAN cyclic tasks - # Will be removed in version 4.0 - from can.interfaces.socketcan import CyclicSendTask, MultiRateCyclicSendTask - # Required by "detect_available_configs" for argument interpretation if sys.version_info.major > 2: basestring = str -log = logging.getLogger('can.interface') +log = logging.getLogger('pycan.interface') log_autodetect = log.getChild('detect_available_configs') @@ -61,7 +52,7 @@ def _get_class_for_interface(interface): except Exception as e: raise ImportError( "Cannot import class {} from module {} for CAN interface '{}': {}" - .format(class_name, module_name, interface, e) + .format(class_name, module_name, interface, e) ) return bus_class @@ -77,7 +68,7 @@ class Bus(BusABC): @staticmethod def __new__(cls, channel=None, *args, **kwargs): """ - Takes the same arguments as :class:`can.BusABC.__init__`. + Takes the same arguments as :class:`pycan.BusABC.__init__`. Some might have a special meaning, see below. :param channel: @@ -88,7 +79,7 @@ def __new__(cls, channel=None, *args, **kwargs): :param dict kwargs: Should contain an ``interface`` key with a valid interface name. If not, - it is completed using :meth:`can.util.load_config`. + it is completed using :meth:`pycan.util.load_config`. :raises: NotImplementedError if the ``interface`` isn't recognized @@ -144,7 +135,7 @@ def detect_available_configs(interfaces=None): - `None` to search in all known interfaces. :rtype: list[dict] :return: an iterable of dicts, each suitable for usage in - the constructor of :class:`can.BusABC`. + the constructor of :class:`pycan.BusABC`. """ # Figure out where to search diff --git a/pycan/interfaces/__init__.py b/pycan/interfaces/__init__.py new file mode 100644 index 000000000..373b5a63b --- /dev/null +++ b/pycan/interfaces/__init__.py @@ -0,0 +1,24 @@ +""" +Interfaces contain low level implementations that interact with CAN hardware. +""" + + +# interface_name => (module, classname) +BACKENDS = { + 'kvaser': ('pycan.interfaces.kvaser', 'KvaserBus'), + 'socketcan': ('pycan.interfaces.socketcan', 'SocketcanBus'), + 'serial': ('pycan.interfaces.serial.serial_can','SerialBus'), + 'pcan': ('pycan.interfaces.pcan', 'PcanBus'), + 'usb2can': ('pycan.interfaces.usb2can', 'Usb2canBus'), + 'ixxat': ('pycan.interfaces.ixxat', 'IXXATBus'), + 'nican': ('pycan.interfaces.nican', 'NicanBus'), + 'iscan': ('pycan.interfaces.iscan', 'IscanBus'), + 'virtual': ('pycan.interfaces.virtual', 'VirtualBus'), + 'neovi': ('pycan.interfaces.ics_neovi', 'NeoViBus'), + 'vector': ('pycan.interfaces.vector', 'VectorBus'), + 'slcan': ('pycan.interfaces.slcan', 'slcanBus'), + 'canalystii': ('pycan.interfaces.canalystii', 'CANalystIIBus'), + 'systec': ('pycan.interfaces.systec', 'UcanBus') +} + +VALID_INTERFACES = frozenset(list(BACKENDS.keys()) + ['socketcan_native', 'socketcan_ctypes']) diff --git a/can/interfaces/canalystii.py b/pycan/interfaces/canalystii.py similarity index 89% rename from can/interfaces/canalystii.py rename to pycan/interfaces/canalystii.py index 35f240a66..f0eb11bfe 100644 --- a/can/interfaces/canalystii.py +++ b/pycan/interfaces/canalystii.py @@ -1,7 +1,8 @@ +import warnings from ctypes import * import logging import platform -from can import BusABC, Message +from pycan import BusABC, Message logger = logging.getLogger(__name__) @@ -66,17 +67,19 @@ 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, 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 """ - super(CANalystIIBus, self).__init__(channel, can_filters) + super(CANalystIIBus, self).__init__(channel, can_filters, **kwargs) if isinstance(channel, (list, tuple)): self.channels = channel @@ -91,10 +94,15 @@ def __init__(self, channel, device=0, baud=None, Timing0=None, Timing1=None, can 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") diff --git a/pycan/interfaces/ics_neovi/__init__.py b/pycan/interfaces/ics_neovi/__init__.py new file mode 100644 index 000000000..1b4bee532 --- /dev/null +++ b/pycan/interfaces/ics_neovi/__init__.py @@ -0,0 +1 @@ +from pycan.interfaces.ics_neovi.neovi_bus import NeoViBus diff --git a/can/interfaces/ics_neovi/neovi_bus.py b/pycan/interfaces/ics_neovi/neovi_bus.py similarity index 97% rename from can/interfaces/ics_neovi/neovi_bus.py rename to pycan/interfaces/ics_neovi/neovi_bus.py index 4baee6177..c356ee6c0 100644 --- a/can/interfaces/ics_neovi/neovi_bus.py +++ b/pycan/interfaces/ics_neovi/neovi_bus.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ ICS NeoVi interface module. @@ -13,7 +11,7 @@ import logging from collections import deque -from can import Message, CanError, BusABC +from pycan import Message, CanError, BusABC logger = logging.getLogger(__name__) @@ -74,7 +72,7 @@ def __init__(self, channel, can_filters=None, **kwargs): string. :type channel: int or str or list(int) or list(str) :param list can_filters: - See :meth:`can.BusABC.set_filters` for details. + See :meth:`pycan.BusABC.set_filters` for details. :param bool receive_own_messages: If transmitted messages should also be received by this bus. :param bool use_system_timestamp: @@ -334,11 +332,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 diff --git a/can/interfaces/iscan.py b/pycan/interfaces/iscan.py similarity index 97% rename from can/interfaces/iscan.py rename to pycan/interfaces/iscan.py index a646bd96e..1d5c34cb1 100644 --- a/can/interfaces/iscan.py +++ b/pycan/interfaces/iscan.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Interface for isCAN from Thorsis Technologies GmbH, former ifak system GmbH. """ @@ -10,7 +8,7 @@ import time import logging -from can import CanError, BusABC, Message +from pycan import CanError, BusABC, Message logger = logging.getLogger(__name__) @@ -89,7 +87,7 @@ def __init__(self, channel, bitrate=500000, poll_interval=0.01, **kwargs): iscan.isCAN_DeviceInitEx(self.channel, self.BAUDRATES[bitrate]) super(IscanBus, self).__init__(channel=channel, bitrate=bitrate, - poll_interval=poll_interval, **kwargs) + poll_interval=poll_interval, **kwargs) def _recv_internal(self, timeout): raw_msg = MessageExStruct() diff --git a/can/interfaces/ixxat/__init__.py b/pycan/interfaces/ixxat/__init__.py similarity index 77% rename from can/interfaces/ixxat/__init__.py rename to pycan/interfaces/ixxat/__init__.py index aef26b729..b65c385f8 100644 --- a/can/interfaces/ixxat/__init__.py +++ b/pycan/interfaces/ixxat/__init__.py @@ -6,4 +6,4 @@ Copyright (C) 2016 Giuseppe Corbelli """ -from can.interfaces.ixxat.canlib import IXXATBus +from pycan.interfaces.ixxat.canlib import IXXATBus diff --git a/can/interfaces/ixxat/canlib.py b/pycan/interfaces/ixxat/canlib.py similarity index 97% rename from can/interfaces/ixxat/canlib.py rename to pycan/interfaces/ixxat/canlib.py index 84c8751c1..4109f559d 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/pycan/interfaces/ixxat/canlib.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Ctypes wrapper module for IXXAT Virtual CAN Interface V3 on win32 systems @@ -8,7 +6,7 @@ TODO: We could implement this interface such that setting other filters could work when the initial filters were set to zero using the software fallback. Or could the software filters even be changed - after the connection was opened? We need to document that bahaviour! + after the connection was opened? We need to document that behavior! See also the NICAN interface. """ @@ -20,17 +18,17 @@ import logging import sys -from can import CanError, BusABC, Message -from can.broadcastmanager import (LimitedDurationCyclicSendTaskABC, - RestartableCyclicTaskABC) -from can.ctypesutil import CLibrary, HANDLE, PHANDLE, HRESULT as ctypes_HRESULT +from pycan import BusABC, Message +from pycan.broadcastmanager import (LimitedDurationCyclicSendTaskABC, + RestartableCyclicTaskABC) +from pycan.ctypesutil import CLibrary, HANDLE, PHANDLE, HRESULT as ctypes_HRESULT from . import constants, structures from .exceptions import * __all__ = ["VCITimeout", "VCIError", "VCIDeviceNotFoundError", "IXXATBus", "vciFormatError"] -log = logging.getLogger('can.ixxat') +log = logging.getLogger('pycan.ixxat') try: # since Python 3.3 @@ -241,8 +239,8 @@ class IXXATBus(BusABC): .. warning:: This interface does implement efficient filtering of messages, but - the filters have to be set in :meth:`~can.interfaces.ixxat.IXXATBus.__init__` - using the ``can_filters`` parameter. Using :meth:`~can.interfaces.ixxat.IXXATBus.set_filters` + the filters have to be set in :meth:`~pycan.interfaces.ixxat.IXXATBus.__init__` + using the ``can_filters`` parameter. Using :meth:`~pycan.interfaces.ixxat.IXXATBus.set_filters` does not work. """ @@ -255,6 +253,7 @@ class IXXATBus(BusABC): 100000: constants.CAN_BT0_100KB, 125000: constants.CAN_BT0_125KB, 250000: constants.CAN_BT0_250KB, + 400000: constants.CAN_BT0_400KB, 500000: constants.CAN_BT0_500KB, 800000: constants.CAN_BT0_800KB, 1000000: constants.CAN_BT0_1000KB @@ -266,6 +265,7 @@ class IXXATBus(BusABC): 100000: constants.CAN_BT1_100KB, 125000: constants.CAN_BT1_125KB, 250000: constants.CAN_BT1_250KB, + 400000: constants.CAN_BT1_400KB, 500000: constants.CAN_BT1_500KB, 800000: constants.CAN_BT1_800KB, 1000000: constants.CAN_BT1_1000KB @@ -278,7 +278,7 @@ def __init__(self, channel, can_filters=None, **kwargs): The Channel id to create this bus with. :param list can_filters: - See :meth:`can.BusABC.set_filters`. + See :meth:`pycan.BusABC.set_filters`. :param bool receive_own_messages: Enable self-reception of sent messages. @@ -524,7 +524,7 @@ def shutdown(self): __set_filters_has_been_called = False def set_filters(self, can_filers=None): - """Unsupported. See note on :class:`~can.interfaces.ixxat.IXXATBus`. + """Unsupported. See note on :class:`~pycan.interfaces.ixxat.IXXATBus`. """ if self.__set_filters_has_been_called: log.warn("using filters is not supported like this, see note on IXXATBus") diff --git a/can/interfaces/ixxat/constants.py b/pycan/interfaces/ixxat/constants.py similarity index 97% rename from can/interfaces/ixxat/constants.py rename to pycan/interfaces/ixxat/constants.py index d466e096d..7caf3c6bc 100644 --- a/can/interfaces/ixxat/constants.py +++ b/pycan/interfaces/ixxat/constants.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Ctypes wrapper module for IXXAT Virtual CAN Interface V3 on win32 systems @@ -26,10 +24,12 @@ CAN_BT1_125KB = 0x1C CAN_BT0_250KB = 0x01 CAN_BT1_250KB = 0x1C +CAN_BT0_400KB = 0x81 +CAN_BT1_400KB = 0x34 CAN_BT0_500KB = 0x00 CAN_BT1_500KB = 0x1C -CAN_BT0_800KB = 0x00 -CAN_BT1_800KB = 0x16 +CAN_BT0_800KB = 0x80 +CAN_BT1_800KB = 0x34 CAN_BT0_1000KB = 0x00 CAN_BT1_1000KB = 0x14 diff --git a/can/interfaces/ixxat/exceptions.py b/pycan/interfaces/ixxat/exceptions.py similarity index 90% rename from can/interfaces/ixxat/exceptions.py rename to pycan/interfaces/ixxat/exceptions.py index ac1700dca..4e4b54afb 100644 --- a/can/interfaces/ixxat/exceptions.py +++ b/pycan/interfaces/ixxat/exceptions.py @@ -1,24 +1,20 @@ -# coding: utf-8 - """ Ctypes wrapper module for IXXAT Virtual CAN Interface V3 on win32 systems Copyright (C) 2016 Giuseppe Corbelli """ -from can import CanError +from pycan import CanError __all__ = ['VCITimeout', 'VCIError', 'VCIRxQueueEmptyError', 'VCIDeviceNotFoundError'] class VCITimeout(CanError): """ Wraps the VCI_E_TIMEOUT error """ - pass class VCIError(CanError): """ Try to display errors that occur within the wrapped C library nicely. """ - pass class VCIRxQueueEmptyError(VCIError): @@ -28,4 +24,4 @@ def __init__(self): class VCIDeviceNotFoundError(CanError): - pass + """Device not found error""" diff --git a/can/interfaces/ixxat/structures.py b/pycan/interfaces/ixxat/structures.py similarity index 99% rename from can/interfaces/ixxat/structures.py rename to pycan/interfaces/ixxat/structures.py index 65b177d94..92265b586 100644 --- a/can/interfaces/ixxat/structures.py +++ b/pycan/interfaces/ixxat/structures.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Ctypes wrapper module for IXXAT Virtual CAN Interface V3 on win32 systems diff --git a/pycan/interfaces/kvaser/__init__.py b/pycan/interfaces/kvaser/__init__.py new file mode 100644 index 000000000..c2c050856 --- /dev/null +++ b/pycan/interfaces/kvaser/__init__.py @@ -0,0 +1 @@ +from pycan.interfaces.kvaser.canlib import * diff --git a/can/interfaces/kvaser/canlib.py b/pycan/interfaces/kvaser/canlib.py similarity index 95% rename from can/interfaces/kvaser/canlib.py rename to pycan/interfaces/kvaser/canlib.py index fa3a70221..3e0839f94 100644 --- a/can/interfaces/kvaser/canlib.py +++ b/pycan/interfaces/kvaser/canlib.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Contains Python equivalents of the function and constant definitions in CANLIB's canlib.h, with some supporting functionality @@ -15,12 +13,11 @@ import logging import ctypes -from can import CanError, BusABC -from can import Message +from pycan import CanError, BusABC, Message from . import constants as canstat from . import structures -log = logging.getLogger('can.kvaser') +log = logging.getLogger('pycan.kvaser') # Resolution in us TIMESTAMP_RESOLUTION = 10 @@ -50,7 +47,7 @@ def __get_canlib_function(func_name, argtypes=[], restype=None, errcheck=None): retval = getattr(__canlib, func_name) #log.debug('"%s" found in library', func_name) except AttributeError: - log.warning('"%s" was not found in library', func_name) + log.info('"%s" was not found in library', func_name) return _unimplemented_function else: #log.debug('Result type is: %s' % type(restype)) @@ -174,11 +171,11 @@ def __check_bus_handle_validity(handle, function, arguments): errcheck=__check_status) canSetBusParamsFd = __get_canlib_function("canSetBusParamsFd", - argtypes=[c_canHandle, ctypes.c_long, - ctypes.c_uint, ctypes.c_uint, - ctypes.c_uint], - restype=canstat.c_canStatus, - errcheck=__check_status) + argtypes=[c_canHandle, ctypes.c_long, + ctypes.c_uint, ctypes.c_uint, + ctypes.c_uint], + restype=canstat.c_canStatus, + errcheck=__check_status) canSetBusOutputControl = __get_canlib_function("canSetBusOutputControl", argtypes=[c_canHandle, @@ -242,12 +239,12 @@ def __check_bus_handle_validity(handle, function, arguments): errcheck=__check_status) canGetChannelData = __get_canlib_function("canGetChannelData", - argtypes=[ctypes.c_int, - ctypes.c_int, - ctypes.c_void_p, - ctypes.c_size_t], - restype=canstat.c_canStatus, - errcheck=__check_status) + argtypes=[ctypes.c_int, + ctypes.c_int, + ctypes.c_void_p, + ctypes.c_size_t], + restype=canstat.c_canStatus, + errcheck=__check_status) canRequestBusStatistics = __get_canlib_function("canRequestBusStatistics", argtypes=[c_canHandle], @@ -398,7 +395,7 @@ def __init__(self, channel, can_filters=None, **kwargs): canstat.canIOCTL_SET_TIMER_SCALE, ctypes.byref(ctypes.c_long(TIMESTAMP_RESOLUTION)), 4) - + if fd: if 'tseg1' not in kwargs and bitrate in BITRATE_FD: # Use predefined bitrate for arbitration @@ -568,8 +565,8 @@ def flash(self, flash=True): try: kvFlashLeds(self._read_handle, action, 30000) - except (CANLIBError, NotImplementedError) as e: - log.error('Could not flash LEDs (%s)', e) + except (CANLIBError, NotImplementedError) as err: + log.error('Could not flash LEDs (%s)', err) def shutdown(self): # Wait for transmit queue to be cleared @@ -595,7 +592,7 @@ def get_stats(self): std_data: 0, std_remote: 0, ext_data: 0, ext_remote: 0, err_frame: 0, bus_load: 0.0%, overruns: 0 :returns: bus statistics. - :rtype: can.interfaces.kvaser.structures.BusStatistics + :rtype: pycan.interfaces.kvaser.structures.BusStatistics """ canRequestBusStatistics(self._write_handle) stats = structures.BusStatistics() diff --git a/can/interfaces/kvaser/constants.py b/pycan/interfaces/kvaser/constants.py similarity index 100% rename from can/interfaces/kvaser/constants.py rename to pycan/interfaces/kvaser/constants.py diff --git a/can/interfaces/kvaser/structures.py b/pycan/interfaces/kvaser/structures.py similarity index 100% rename from can/interfaces/kvaser/structures.py rename to pycan/interfaces/kvaser/structures.py diff --git a/can/interfaces/nican.py b/pycan/interfaces/nican.py similarity index 94% rename from can/interfaces/nican.py rename to pycan/interfaces/nican.py index 0e962cd2f..2d1174844 100644 --- a/can/interfaces/nican.py +++ b/pycan/interfaces/nican.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ NI-CAN interface module. @@ -19,7 +17,7 @@ import logging import sys -from can import CanError, BusABC, Message +from pycan import CanError, BusABC, Message logger = logging.getLogger(__name__) @@ -123,8 +121,8 @@ class NicanBus(BusABC): .. warning:: This interface does implement efficient filtering of messages, but - the filters have to be set in :meth:`~can.interfaces.nican.NicanBus.__init__` - using the ``can_filters`` parameter. Using :meth:`~can.interfaces.nican.NicanBus.set_filters` + the filters have to be set in :meth:`~pycan.interfaces.nican.NicanBus.__init__` + using the ``can_filters`` parameter. Using :meth:`~pycan.interfaces.nican.NicanBus.set_filters` does not work. """ @@ -138,14 +136,14 @@ def __init__(self, channel, can_filters=None, bitrate=None, log_errors=True, **k Bitrate in bits/s :param list can_filters: - See :meth:`can.BusABC.set_filters`. + See :meth:`pycan.BusABC.set_filters`. :param bool log_errors: If True, communication errors will appear as CAN messages with ``is_error_frame`` set to True and ``arbitration_id`` will identify the error (default True) - :raises can.interfaces.nican.NicanError: + :raises pycan.interfaces.nican.NicanError: If starting communication fails """ @@ -212,7 +210,7 @@ def _recv_internal(self, timeout): :param float timeout: Max time to wait in seconds or None if infinite - :raises can.interfaces.nican.NicanError: + :raises pycan.interfaces.nican.NicanError: If reception fails """ if timeout is None: @@ -255,10 +253,10 @@ def send(self, msg, timeout=None): """ Send a message to NI-CAN. - :param can.Message msg: + :param pycan.Message msg: Message to send - :raises can.interfaces.nican.NicanError: + :raises pycan.interfaces.nican.NicanError: If writing to transmit buffer fails. It does not wait for message to be ACKed currently. """ @@ -295,10 +293,10 @@ def shutdown(self): __set_filters_has_been_called = False def set_filters(self, can_filers=None): - """Unsupported. See note on :class:`~can.interfaces.nican.NicanBus`. + """Unsupported. See note on :class:`~pycan.interfaces.nican.NicanBus`. """ if self.__set_filters_has_been_called: - logger.warn("using filters is not supported like this, see note on NicanBus") + logger.warning("using filters is not supported like this, see note on NicanBus") else: # allow the constructor to call this without causing a warning self.__set_filters_has_been_called = True diff --git a/pycan/interfaces/pcan/__init__.py b/pycan/interfaces/pcan/__init__.py new file mode 100644 index 000000000..516049f92 --- /dev/null +++ b/pycan/interfaces/pcan/__init__.py @@ -0,0 +1 @@ +from pycan.interfaces.pcan.pcan import PcanBus diff --git a/can/interfaces/pcan/basic.py b/pycan/interfaces/pcan/basic.py similarity index 99% rename from can/interfaces/pcan/basic.py rename to pycan/interfaces/pcan/basic.py index 053197119..4cc92edad 100644 --- a/can/interfaces/pcan/basic.py +++ b/pycan/interfaces/pcan/basic.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ PCAN-Basic API @@ -17,7 +15,7 @@ import platform import logging -logger = logging.getLogger('can.pcan') +logger = logging.getLogger('pycan.pcan') #/////////////////////////////////////////////////////////// # Type definitions @@ -242,8 +240,9 @@ # to calculate the BTROBTR1 register for every bit rate and sample point. PCAN_BAUD_1M = TPCANBaudrate(0x0014) # 1 MBit/s -PCAN_BAUD_800K = TPCANBaudrate(0x0016) # 800 kBit/s +PCAN_BAUD_800K = TPCANBaudrate(0x8434) # 800 kBit/s PCAN_BAUD_500K = TPCANBaudrate(0x001C) # 500 kBit/s +PCAN_BAUD_400K = TPCANBaudrate(0x807A) # 400 kBit/s PCAN_BAUD_250K = TPCANBaudrate(0x011C) # 250 kBit/s PCAN_BAUD_125K = TPCANBaudrate(0x031C) # 125 kBit/s PCAN_BAUD_100K = TPCANBaudrate(0x432F) # 100 kBit/s diff --git a/can/interfaces/pcan/pcan.py b/pycan/interfaces/pcan/pcan.py similarity index 92% rename from can/interfaces/pcan/pcan.py rename to pycan/interfaces/pcan/pcan.py index 864308bab..27f56fbf5 100644 --- a/can/interfaces/pcan/pcan.py +++ b/pycan/interfaces/pcan/pcan.py @@ -1,19 +1,15 @@ -# coding: utf-8 - """ -Enable basic CAN over a PCAN USB device. +Enable basic CAN over a PCAN USB device """ from __future__ import absolute_import, print_function, division import logging -import sys import time -import can -from can import CanError, Message, BusABC -from can.bus import BusState -from can.util import len2dlc, dlc2len +from pycan import CanError, Message, BusABC +from pycan.bus import BusState +from pycan.util import len2dlc, dlc2len from .basic import * boottimeEpoch = 0 @@ -47,23 +43,24 @@ timeout_clock = time.clock # Set up logging -log = logging.getLogger('can.pcan') +log = logging.getLogger('pycan.pcan') pcan_bitrate_objs = {1000000 : PCAN_BAUD_1M, - 800000 : PCAN_BAUD_800K, - 500000 : PCAN_BAUD_500K, - 250000 : PCAN_BAUD_250K, - 125000 : PCAN_BAUD_125K, - 100000 : PCAN_BAUD_100K, - 95000 : PCAN_BAUD_95K, - 83000 : PCAN_BAUD_83K, - 50000 : PCAN_BAUD_50K, - 47000 : PCAN_BAUD_47K, - 33000 : PCAN_BAUD_33K, - 20000 : PCAN_BAUD_20K, - 10000 : PCAN_BAUD_10K, - 5000 : PCAN_BAUD_5K} + 800000 : PCAN_BAUD_800K, + 500000 : PCAN_BAUD_500K, + 400000 : PCAN_BAUD_400K, + 250000 : PCAN_BAUD_250K, + 125000 : PCAN_BAUD_125K, + 100000 : PCAN_BAUD_100K, + 95000 : PCAN_BAUD_95K, + 83000 : PCAN_BAUD_83K, + 50000 : PCAN_BAUD_50K, + 47000 : PCAN_BAUD_47K, + 33000 : PCAN_BAUD_33K, + 20000 : PCAN_BAUD_20K, + 10000 : PCAN_BAUD_10K, + 5000 : PCAN_BAUD_5K} pcan_fd_parameter_list = ['nom_brp', 'nom_tseg1', 'nom_tseg2', 'nom_sjw', 'data_brp', 'data_tseg1', 'data_tseg2', 'data_sjw'] @@ -74,15 +71,15 @@ class PcanBus(BusABC): def __init__(self, channel='PCAN_USBBUS1', state=BusState.ACTIVE, bitrate=500000, *args, **kwargs): """A PCAN USB interface to CAN. - On top of the usual :class:`~can.Bus` methods provided, - the PCAN interface includes the :meth:`~can.interface.pcan.PcanBus.flash` - and :meth:`~can.interface.pcan.PcanBus.status` methods. + On top of the usual :class:`~pycan.Bus` methods provided, + the PCAN interface includes the :meth:`~pycan.interface.pcan.PcanBus.flash` + and :meth:`~pycan.interface.pcan.PcanBus.status` methods. :param str channel: The can interface name. An example would be 'PCAN_USBBUS1' Default is 'PCAN_USBBUS1' - :param can.bus.BusState state: + :param pycan.bus.BusState state: BusState of the channel. Default is ACTIVE @@ -184,7 +181,7 @@ def __init__(self, channel='PCAN_USBBUS1', state=BusState.ACTIVE, bitrate=500000 f_clock = "{}={}".format('f_clock_mhz', kwargs.get('f_clock_mhz', None)) else: f_clock = "{}={}".format('f_clock', kwargs.get('f_clock', None)) - + fd_parameters_values = [f_clock] + ["{}={}".format(key, kwargs.get(key, None)) for key in pcan_fd_parameter_list if kwargs.get(key, None) is not None] self.fd_bitrate = ' ,'.join(fd_parameters_values).encode("ascii") @@ -357,7 +354,7 @@ def send(self, msg, timeout=None): CANMsg = TPCANMsgFDMac() else: CANMsg = TPCANMsgFD() - + # configure the message. ID, Length of data, message type and data CANMsg.ID = msg.arbitration_id CANMsg.DLC = len2dlc(msg.dlc) @@ -385,9 +382,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] diff --git a/pycan/interfaces/serial/__init__.py b/pycan/interfaces/serial/__init__.py new file mode 100644 index 000000000..3fc594e80 --- /dev/null +++ b/pycan/interfaces/serial/__init__.py @@ -0,0 +1 @@ +from pycan.interfaces.serial.serial_can import SerialBus as Bus diff --git a/can/interfaces/serial/serial_can.py b/pycan/interfaces/serial/serial_can.py similarity index 95% rename from can/interfaces/serial/serial_can.py rename to pycan/interfaces/serial/serial_can.py index afa545734..f21f4d9cf 100644 --- a/can/interfaces/serial/serial_can.py +++ b/pycan/interfaces/serial/serial_can.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ A text based interface. For example use over serial ports like "/dev/ttyS1" or "/dev/ttyUSB0" on Linux machines or "COM1" on Windows. @@ -12,9 +10,9 @@ import logging import struct -from can import BusABC, Message +from pycan import BusABC, Message -logger = logging.getLogger('can.serial') +logger = logging.getLogger('pycan.serial') try: import serial @@ -28,7 +26,7 @@ class SerialBus(BusABC): """ Enable basic can communication over a serial device. - .. note:: See :meth:`can.interfaces.serial.SerialBus._recv_internal` + .. note:: See :meth:`pycan.interfaces.serial.SerialBus._recv_internal` for some special semantics. """ @@ -72,7 +70,7 @@ def send(self, msg, timeout=None): """ Send a message over the serial device. - :param can.Message msg: + :param pycan.Message msg: Message to send. .. note:: Flags like ``extended_id``, ``is_remote_frame`` and @@ -124,7 +122,7 @@ def _recv_internal(self, timeout): message are the default values. :rtype: - can.Message, bool + pycan.Message, bool """ try: # ser.read can return an empty string diff --git a/can/interfaces/slcan.py b/pycan/interfaces/slcan.py similarity index 99% rename from can/interfaces/slcan.py rename to pycan/interfaces/slcan.py index 8793e2c22..7373e0f17 100644 --- a/can/interfaces/slcan.py +++ b/pycan/interfaces/slcan.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Interface for slcan compatible interfaces (win32/linux). @@ -14,7 +12,7 @@ import time import logging -from can import BusABC, Message +from pycan import BusABC, Message logger = logging.getLogger(__name__) diff --git a/pycan/interfaces/socketcan/__init__.py b/pycan/interfaces/socketcan/__init__.py new file mode 100644 index 000000000..28263b493 --- /dev/null +++ b/pycan/interfaces/socketcan/__init__.py @@ -0,0 +1,5 @@ +""" +See: https://www.kernel.org/doc/Documentation/networking/can.txt +""" + +from pycan.interfaces.socketcan.socketcan import SocketcanBus, CyclicSendTask, MultiRateCyclicSendTask diff --git a/can/interfaces/socketcan/constants.py b/pycan/interfaces/socketcan/constants.py similarity index 94% rename from can/interfaces/socketcan/constants.py rename to pycan/interfaces/socketcan/constants.py index b56eaae64..2cade1c75 100644 --- a/can/interfaces/socketcan/constants.py +++ b/pycan/interfaces/socketcan/constants.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Defines shared CAN constants. """ @@ -9,8 +7,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/pycan/interfaces/socketcan/socketcan.py similarity index 90% rename from can/interfaces/socketcan/socketcan.py rename to pycan/interfaces/socketcan/socketcan.py index 633c87b22..ac5f4bd8b 100644 --- a/can/interfaces/socketcan/socketcan.py +++ b/pycan/interfaces/socketcan/socketcan.py @@ -1,9 +1,7 @@ -# coding: utf-8 import logging import ctypes import ctypes.util -import os import select import socket import struct @@ -22,12 +20,12 @@ log.error("fcntl not available on this platform") -import can -from can import Message, BusABC -from can.broadcastmanager import ModifiableCyclicTaskABC, \ +import pycan +from pycan import Message, BusABC +from pycan.broadcastmanager import ModifiableCyclicTaskABC, \ RestartableCyclicTaskABC, LimitedDurationCyclicSendTaskABC -from can.interfaces.socketcan.constants import * # CAN_RAW, CAN_*_FLAG -from can.interfaces.socketcan.utils import \ +from pycan.interfaces.socketcan.constants import * # CAN_RAW, CAN_*_FLAG +from pycan.interfaces.socketcan.utils import \ pack_filters, find_available_interfaces, error_code_to_str @@ -42,7 +40,7 @@ if not HAS_NATIVE_SUPPORT: def check_status(result, function, arguments): if result < 0: - raise can.CanError(error_code_to_str(ctypes.get_errno())) + raise pycan.CanError(error_code_to_str(ctypes.get_errno())) return result try: @@ -197,15 +195,15 @@ def build_can_frame(msg): def build_bcm_header( - opcode, - flags, - count, - ival1_seconds, - ival1_usec, - ival2_seconds, - ival2_usec, - can_id, - nframes, + opcode, + flags, + count, + ival1_seconds, + ival1_usec, + ival2_seconds, + ival2_usec, + can_id, + nframes, ): result = BcmMsgHead( opcode=opcode, @@ -282,13 +280,13 @@ def send_bcm(bcm_socket, data): base = "Couldn't send CAN BCM frame. OS Error {}: {}\n".format(e.errno, e.strerror) if e.errno == errno.EINVAL: - raise can.CanError(base + "You are probably referring to a non-existing frame.") + raise pycan.CanError(base + "You are probably referring to a non-existing frame.") elif e.errno == errno.ENETDOWN: - raise can.CanError(base + "The CAN interface appears to be down.") + raise pycan.CanError(base + "The CAN interface appears to be down.") elif e.errno == errno.EBADF: - raise can.CanError(base + "The CAN socket appears to be closed.") + raise pycan.CanError(base + "The CAN socket appears to be closed.") else: raise e @@ -323,7 +321,7 @@ class CyclicSendTask(LimitedDurationCyclicSendTaskABC, def __init__(self, bcm_socket, message, period, duration=None): """ :param bcm_socket: An open bcm socket on the desired CAN channel. - :param can.Message message: The message to be sent periodically. + :param pycan.Message message: The message to be sent periodically. :param float period: The rate in seconds at which to send the message. :param float duration: Approximate duration in seconds to send the message. """ @@ -346,8 +344,40 @@ 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: + if e.errno != errno.EINVAL: + raise e + 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) @@ -367,7 +397,7 @@ def stop(self): def modify_data(self, message): """Update the contents of this periodically sent message. - Note the Message must have the same :attr:`~can.Message.arbitration_id` + Note the Message must have the same :attr:`~pycan.Message.arbitration_id` like the first message. """ assert message.arbitration_id == self.can_id, "You cannot modify the can identifier" @@ -466,7 +496,7 @@ def capture_message(sock, get_channel=False): cf = sock.recv(CANFD_MTU) channel = None except socket.error as exc: - raise can.CanError("Error receiving: %s" % exc) + raise pycan.CanError("Error receiving: %s" % exc) can_id, can_dlc, flags, data = dissect_can_frame(cf) #log.debug('Received: can_id=%x, can_dlc=%x, data=%s', can_id, can_dlc, data) @@ -517,7 +547,7 @@ def capture_message(sock, get_channel=False): class SocketcanBus(BusABC): """ - Implements :meth:`can.BusABC._detect_available_configs`. + Implements :meth:`pycan.BusABC._detect_available_configs`. """ def __init__(self, channel="", receive_own_messages=False, fd=False, **kwargs): @@ -527,13 +557,13 @@ def __init__(self, channel="", receive_own_messages=False, fd=False, **kwargs): would be 'vcan0' or 'can0'. An empty string '' will receive messages from all channels. In that case any sent messages must be explicitly addressed to a - channel using :attr:`can.Message.channel`. + channel using :attr:`pycan.Message.channel`. :param bool receive_own_messages: If transmitted messages should also be received by this bus. :param bool fd: If CAN-FD frames should be supported. :param list can_filters: - See :meth:`can.BusABC.set_filters`. + See :meth:`pycan.BusABC.set_filters`. """ self.socket = create_socket() self.channel = channel @@ -582,7 +612,7 @@ def _recv_internal(self, timeout): ready_receive_sockets, _, _ = select.select([self.socket], [], [], timeout) except socket.error as exc: # something bad happened (e.g. the interface went down) - raise can.CanError("Failed to receive: %s" % exc) + raise pycan.CanError("Failed to receive: %s" % exc) if ready_receive_sockets: # not empty or True get_channel = self.channel == "" @@ -598,12 +628,12 @@ def _recv_internal(self, timeout): def send(self, msg, timeout=None): """Transmit a message to the CAN bus. - :param can.Message msg: A message object. + :param pycan.Message msg: A message object. :param float timeout: Wait up to this many seconds for the transmit queue to be ready. If not given, the call may fail immediately. - :raises can.CanError: + :raises pycan.CanError: if the message could not be written. """ log.debug("We've been asked to write a message to the bus") @@ -630,7 +660,7 @@ def send(self, msg, timeout=None): data = data[sent:] time_left = timeout - (time.time() - started) - raise can.CanError("Transmit buffer full") + raise pycan.CanError("Transmit buffer full") def _send_once(self, data, channel=None): try: @@ -646,7 +676,7 @@ def _send_once(self, data, channel=None): else: sent = self.socket.send(data) except socket.error as exc: - raise can.CanError("Failed to transmit: %s" % exc) + raise pycan.CanError("Failed to transmit: %s" % exc) return sent def _send_periodic_internal(self, msg, period, duration=None): @@ -654,7 +684,7 @@ def _send_periodic_internal(self, msg, period, duration=None): The kernel's broadcast manager will be used. - :param can.Message msg: + :param pycan.Message msg: Message to transmit :param float period: Period in seconds between each message @@ -665,7 +695,7 @@ def _send_periodic_internal(self, msg, period, duration=None): :return: A started task instance. This can be used to modify the data, pause/resume the transmission and to stop the transmission. - :rtype: can.interfaces.socketcan.CyclicSendTask + :rtype: pycan.interfaces.socketcan.CyclicSendTask .. note:: diff --git a/can/interfaces/socketcan/utils.py b/pycan/interfaces/socketcan/utils.py similarity index 96% rename from can/interfaces/socketcan/utils.py rename to pycan/interfaces/socketcan/utils.py index 44d356920..6bbf1e712 100644 --- a/can/interfaces/socketcan/utils.py +++ b/pycan/interfaces/socketcan/utils.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Defines common socketcan functions. """ @@ -8,11 +6,10 @@ import os import errno import struct -import sys import subprocess import re -from can.interfaces.socketcan.constants import CAN_EFF_FLAG +from pycan.interfaces.socketcan.constants import CAN_EFF_FLAG log = logging.getLogger(__name__) diff --git a/pycan/interfaces/systec/__init__.py b/pycan/interfaces/systec/__init__.py new file mode 100644 index 000000000..069fd378c --- /dev/null +++ b/pycan/interfaces/systec/__init__.py @@ -0,0 +1 @@ +from pycan.interfaces.systec.ucanbus import UcanBus diff --git a/can/interfaces/systec/constants.py b/pycan/interfaces/systec/constants.py similarity index 99% rename from can/interfaces/systec/constants.py rename to pycan/interfaces/systec/constants.py index 64122dac9..326e782ce 100644 --- a/can/interfaces/systec/constants.py +++ b/pycan/interfaces/systec/constants.py @@ -1,5 +1,3 @@ -# coding: utf-8 - from ctypes import c_ubyte as BYTE, c_ushort as WORD, c_ulong as DWORD #: Maximum number of modules that are supported. diff --git a/can/interfaces/systec/exceptions.py b/pycan/interfaces/systec/exceptions.py similarity index 99% rename from can/interfaces/systec/exceptions.py rename to pycan/interfaces/systec/exceptions.py index d3525cd88..54198eb21 100644 --- a/can/interfaces/systec/exceptions.py +++ b/pycan/interfaces/systec/exceptions.py @@ -1,7 +1,5 @@ -# coding: utf-8 - from .constants import ReturnCode -from can import CanError +from pycan import CanError class UcanException(CanError): diff --git a/can/interfaces/systec/structures.py b/pycan/interfaces/systec/structures.py similarity index 99% rename from can/interfaces/systec/structures.py rename to pycan/interfaces/systec/structures.py index a521e044f..9718ef802 100644 --- a/can/interfaces/systec/structures.py +++ b/pycan/interfaces/systec/structures.py @@ -1,5 +1,3 @@ -# coding: utf-8 - from ctypes import Structure, POINTER, sizeof from ctypes import c_ubyte as BYTE, c_ushort as WORD, c_ulong as DWORD, c_long as BOOL, c_void_p as LPVOID import os diff --git a/can/interfaces/systec/ucan.py b/pycan/interfaces/systec/ucan.py similarity index 99% rename from can/interfaces/systec/ucan.py rename to pycan/interfaces/systec/ucan.py index e42c187eb..42173e9ab 100644 --- a/can/interfaces/systec/ucan.py +++ b/pycan/interfaces/systec/ucan.py @@ -1,5 +1,3 @@ -# coding: utf-8 - import logging import sys @@ -10,7 +8,7 @@ from .structures import * from .exceptions import * -log = logging.getLogger("can.systec") +log = logging.getLogger("pycan.systec") def check_valid_rx_can_msg(result): diff --git a/can/interfaces/systec/ucanbus.py b/pycan/interfaces/systec/ucanbus.py similarity index 96% rename from can/interfaces/systec/ucanbus.py rename to pycan/interfaces/systec/ucanbus.py index 9731398bd..3ee1777df 100644 --- a/can/interfaces/systec/ucanbus.py +++ b/pycan/interfaces/systec/ucanbus.py @@ -1,15 +1,13 @@ -# coding: utf-8 - import logging from threading import Event -from can import BusABC, BusState, Message +from pycan import BusABC, BusState, Message from .constants import * from .structures import * from .ucan import UcanServer -log = logging.getLogger('can.systec') +log = logging.getLogger('pycan.systec') class Ucan(UcanServer): @@ -54,7 +52,7 @@ def __init__(self, channel, can_filters=None, **kwargs): The Channel id to create this bus with. :param list can_filters: - See :meth:`can.BusABC.set_filters`. + See :meth:`pycan.BusABC.set_filters`. Backend Configuration @@ -68,7 +66,7 @@ def __init__(self, channel, can_filters=None, **kwargs): be used, in case only one module is connected to the computer). Default is 255. - :param can.bus.BusState state: + :param pycan.bus.BusState state: BusState of the channel. Default is ACTIVE. @@ -87,7 +85,7 @@ def __init__(self, channel, can_filters=None, **kwargs): :raises ValueError: If invalid input parameter were passed. - :raises can.CanError: + :raises pycan.CanError: If hardware or CAN interface initialization failed. """ try: @@ -155,13 +153,13 @@ def send(self, msg, timeout=None): the "auto delete" state. Within this state all transmit CAN messages for this channel will be deleted automatically for not blocking the other channel. - :param can.Message msg: + :param pycan.Message msg: The CAN message. :param float timeout: Transmit timeout in seconds (value 0 switches off the "auto delete") - :raises can.CanError: + :raises pycan.CanError: If the message could not be sent. """ @@ -207,7 +205,7 @@ def flush_tx_buffer(self): """ Flushes the transmit buffer. - :raises can.CanError: + :raises pycan.CanError: If flushing of the transmit buffer failed. """ log.info('Flushing transmit buffer') diff --git a/can/interfaces/usb2can/__init__.py b/pycan/interfaces/usb2can/__init__.py similarity index 83% rename from can/interfaces/usb2can/__init__.py rename to pycan/interfaces/usb2can/__init__.py index 454942934..2882764b8 100644 --- a/can/interfaces/usb2can/__init__.py +++ b/pycan/interfaces/usb2can/__init__.py @@ -1,9 +1,3 @@ -# coding: utf-8 - -""" -""" - from __future__ import absolute_import - from .usb2canInterface import Usb2canBus from .usb2canabstractionlayer import Usb2CanAbstractionLayer diff --git a/can/interfaces/usb2can/usb2canInterface.py b/pycan/interfaces/usb2can/usb2canInterface.py similarity index 77% rename from can/interfaces/usb2can/usb2canInterface.py rename to pycan/interfaces/usb2can/usb2canInterface.py index eb87ffbd7..4cb53d73e 100644 --- a/can/interfaces/usb2can/usb2canInterface.py +++ b/pycan/interfaces/usb2can/usb2canInterface.py @@ -1,7 +1,5 @@ -# coding: utf-8 - """ -This interface is for Windows only, otherwise use socketCAN. +This interface is for Windows only, otherwise use socketCAN """ from __future__ import division, print_function, absolute_import @@ -9,12 +7,11 @@ import logging from ctypes import byref -from can import BusABC, Message, CanError +from pycan import BusABC, Message, CanError from .usb2canabstractionlayer import * -from .serial_selector import find_serial_devices # Set up logging -log = logging.getLogger('can.usb2can') +log = logging.getLogger('pycan.usb2can') def message_convert_tx(msg): @@ -71,6 +68,10 @@ class Usb2canBus(BusABC): Bitrate of channel in bit/s. Values will be limited to a maximum of 1000 Kb/s. Default is 500 Kbs + :param str bitrate_config (optional): + Bitrate config for the channel. Will override bitrate if both are set. + String should be in the following form: '0;{tseg1};{tseg2};{sjw};{brp}' + :param int flags (optional): Flags to directly pass to open function of the usb2can abstraction layer. @@ -86,25 +87,24 @@ class Usb2canBus(BusABC): """ def __init__(self, channel=None, dll="usb2can.dll", flags=0x00000008, - bitrate=500000, *args, **kwargs): + bitrate=500000, bitrate_config=None, *args, **kwargs): self.can = Usb2CanAbstractionLayer(dll) - # get the serial number of the device + # Get the serial number of the device if "serial" in kwargs: device_id = kwargs["serial"] - else: + elif channel is not None: device_id = channel + else: + raise CanError("Device serial number must be specified") - # search for a serial number if the device_id is None or empty - if not device_id: - devices = find_serial_devices() - if not devices: - raise CanError("could not automatically find any device") - device_id = devices[0] - - # convert to kb/s and cap: max rate is 1000 kb/s - baudrate = min(int(bitrate // 1000), 1000) + if bitrate_config is not None: + # This allows for custom bit rates to be set + baudrate = bitrate_config + else: + # convert to kb/s and cap: max rate is 1000 kb/s + baudrate = min(int(bitrate // 1000), 1000) self.channel_info = "USB2CAN device {}".format(device_id) @@ -157,18 +157,3 @@ def shutdown(self): if status != CANAL_ERROR_SUCCESS: raise CanError("could not shut down bus: status == {}".format(status)) - - @staticmethod - def _detect_available_configs(serial_matcher=None): - """ - Uses the Windows Management Instrumentation to identify serial devices. - - :param str serial_matcher (optional): - search string for automatic detection of the device serial - """ - if serial_matcher: - channels = find_serial_devices(serial_matcher) - else: - channels = find_serial_devices() - - return [{'interface': 'usb2can', 'channel': c} for c in channels] diff --git a/can/interfaces/usb2can/usb2canabstractionlayer.py b/pycan/interfaces/usb2can/usb2canabstractionlayer.py similarity index 91% rename from can/interfaces/usb2can/usb2canabstractionlayer.py rename to pycan/interfaces/usb2can/usb2canabstractionlayer.py index a318bcd6f..cf27441b0 100644 --- a/can/interfaces/usb2can/usb2canabstractionlayer.py +++ b/pycan/interfaces/usb2can/usb2canabstractionlayer.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ This wrapper is for windows or direct access via CANAL API. Socket CAN is recommended under Unix/Linux systems. @@ -11,9 +9,9 @@ from struct import * import logging -import can +import pycan -log = logging.getLogger('can.usb2can') +log = logging.getLogger('pycan.usb2can') # type definitions flags = c_ulong @@ -86,7 +84,7 @@ def open(self, configuration, flags): :param str configuration: the configuration: "device_id; baudrate" :param int flags: the flags to be set - :raises can.CanError: if any error occurred + :raises pycan.CanError: if any error occurred :returns: Valid handle for CANAL API functions on success """ try: @@ -96,15 +94,15 @@ def open(self, configuration, flags): result = self.__m_dllBasic.CanalOpen(config_ascii, flags) except Exception as ex: # catch any errors thrown by this call and re-raise - raise can.CanError('CanalOpen() failed, configuration: "{}", error: {}' - .format(configuration, ex)) + raise pycan.CanError('CanalOpen() failed, configuration: "{}", error: {}' + .format(configuration, ex)) else: # any greater-than-zero return value indicates a success # (see https://grodansparadis.gitbooks.io/the-vscp-daemon/canal_interface_specification.html) # raise an error if the return code is <= 0 if result <= 0: - raise can.CanError('CanalOpen() failed, configuration: "{}", return code: {}' - .format(configuration, result)) + raise pycan.CanError('CanalOpen() failed, configuration: "{}", return code: {}' + .format(configuration, result)) else: return result @@ -122,7 +120,7 @@ def send(self, handle, msg): return res except: log.warning('Sending error') - raise can.CanError("Failed to transmit frame") + raise pycan.CanError("Failed to transmit frame") def receive(self, handle, msg): try: diff --git a/can/interfaces/vector/__init__.py b/pycan/interfaces/vector/__init__.py similarity index 71% rename from can/interfaces/vector/__init__.py rename to pycan/interfaces/vector/__init__.py index dac47be4a..36c368b57 100644 --- a/can/interfaces/vector/__init__.py +++ b/pycan/interfaces/vector/__init__.py @@ -1,7 +1,2 @@ -# coding: utf-8 - -""" -""" - from .canlib import VectorBus from .exceptions import VectorError diff --git a/can/interfaces/vector/canlib.py b/pycan/interfaces/vector/canlib.py similarity index 99% rename from can/interfaces/vector/canlib.py rename to pycan/interfaces/vector/canlib.py index 251b9fa56..8676c0710 100644 --- a/can/interfaces/vector/canlib.py +++ b/pycan/interfaces/vector/canlib.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Ctypes wrapper module for Vector CAN Interface on win32/win64 systems. @@ -10,7 +8,6 @@ # ============================== import ctypes import logging -import sys import time try: @@ -28,8 +25,8 @@ # Import Modules # ============== -from can import BusABC, Message, CanError -from can.util import len2dlc, dlc2len +from pycan import BusABC, Message +from pycan.util import len2dlc, dlc2len from .exceptions import VectorError # Define Module Logger @@ -87,7 +84,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)) diff --git a/can/interfaces/vector/exceptions.py b/pycan/interfaces/vector/exceptions.py similarity index 82% rename from can/interfaces/vector/exceptions.py rename to pycan/interfaces/vector/exceptions.py index 8715c276f..23edb47fb 100644 --- a/can/interfaces/vector/exceptions.py +++ b/pycan/interfaces/vector/exceptions.py @@ -1,9 +1,4 @@ -# coding: utf-8 - -""" -""" - -from can import CanError +from pycan import CanError class VectorError(CanError): diff --git a/can/interfaces/vector/vxlapi.py b/pycan/interfaces/vector/vxlapi.py similarity index 99% rename from can/interfaces/vector/vxlapi.py rename to pycan/interfaces/vector/vxlapi.py index ae87706c4..56b39b774 100644 --- a/can/interfaces/vector/vxlapi.py +++ b/pycan/interfaces/vector/vxlapi.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Ctypes wrapper module for Vector CAN Interface on win32/win64 systems. diff --git a/can/interfaces/virtual.py b/pycan/interfaces/virtual.py similarity index 93% rename from can/interfaces/virtual.py rename to pycan/interfaces/virtual.py index 6f24c73f2..f354646b9 100644 --- a/can/interfaces/virtual.py +++ b/pycan/interfaces/virtual.py @@ -1,11 +1,9 @@ -# coding: utf-8 - """ This module implements an OS and hardware independent virtual CAN interface for testing purposes. Any VirtualBus instances connecting to the same channel -and reside in the same process will receive the same messages. +and residing in the same process will receive the same messages. """ from copy import deepcopy @@ -18,8 +16,8 @@ from threading import RLock from random import randint -from can.bus import BusABC -from can import CanError +from pycan.bus import BusABC +from pycan import CanError logger = logging.getLogger(__name__) @@ -37,8 +35,8 @@ class VirtualBus(BusABC): In this interface, a channel is an arbitrary object used as an identifier for connected buses. - Implements :meth:`can.BusABC._detect_available_configs`; see - :meth:`can.VirtualBus._detect_available_configs` for how it + Implements :meth:`pycan.BusABC._detect_available_configs`; see + :meth:`pycan.VirtualBus._detect_available_configs` for how it behaves here. .. note:: diff --git a/can/io/__init__.py b/pycan/io/__init__.py similarity index 96% rename from can/io/__init__.py rename to pycan/io/__init__.py index a0d89f28b..8f972bf0b 100644 --- a/can/io/__init__.py +++ b/pycan/io/__init__.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Read and write CAN bus messages using a range of Readers and Writers based off the file extension. diff --git a/can/io/asc.py b/pycan/io/asc.py similarity index 82% rename from can/io/asc.py rename to pycan/io/asc.py index 3ed50f04a..8b8c4485e 100644 --- a/can/io/asc.py +++ b/pycan/io/asc.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Contains handling of ASC logging files. @@ -23,12 +21,13 @@ CAN_MSG_EXT = 0x80000000 CAN_ID_MASK = 0x1FFFFFFF -logger = logging.getLogger('can.io.asc') +logger = logging.getLogger('pycan.io.asc') 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 """ @@ -58,9 +57,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 @@ -77,7 +80,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': @@ -91,16 +97,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]: @@ -115,7 +137,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/can/io/blf.py b/pycan/io/blf.py similarity index 98% rename from can/io/blf.py rename to pycan/io/blf.py index d162fdebc..62040afc8 100644 --- a/can/io/blf.py +++ b/pycan/io/blf.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Implements support for BLF (Binary Logging Format) which is a proprietary CAN log format from Vector Informatik GmbH (Germany). @@ -22,9 +20,9 @@ import time import logging -from can.message import Message -from can.listener import Listener -from can.util import len2dlc, dlc2len, channel2int +from pycan.message import Message +from pycan.listener import Listener +from pycan.util import len2dlc, dlc2len, channel2int from .generic import BaseIOHandler @@ -195,8 +193,11 @@ 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) + 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 @@ -222,7 +223,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, diff --git a/can/io/canutils.py b/pycan/io/canutils.py similarity index 96% rename from can/io/canutils.py rename to pycan/io/canutils.py index 69c0227a4..0eebabbef 100644 --- a/can/io/canutils.py +++ b/pycan/io/canutils.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ This module works with CAN data in ASCII log files (*.log). It is is compatible with "candump -L" from the canutils program @@ -8,16 +6,14 @@ from __future__ import absolute_import, division -import time -import datetime import logging -from can.message import Message -from can.listener import Listener +from pycan.message import Message +from pycan.listener import Listener from .generic import BaseIOHandler -log = logging.getLogger('can.io.canutils') +log = logging.getLogger('pycan.io.canutils') CAN_MSG_EXT = 0x80000000 CAN_ERR_FLAG = 0x20000000 @@ -62,7 +58,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: diff --git a/can/io/csv.py b/pycan/io/csv.py similarity index 93% rename from can/io/csv.py rename to pycan/io/csv.py index 92f841f8f..79503d74b 100644 --- a/can/io/csv.py +++ b/pycan/io/csv.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ This module contains handling for CSV (comma separated values) files. @@ -15,8 +13,8 @@ from base64 import b64encode, b64decode -from can.message import Message -from can.listener import Listener +from pycan.message import Message +from pycan.listener import Listener from .generic import BaseIOHandler @@ -74,7 +72,7 @@ def on_message_received(self, msg): class CSVReader(BaseIOHandler): """Iterator over CAN messages from a .csv file that was - generated by :class:`~can.CSVWriter` or that uses the same + generated by :class:`~pycan.CSVWriter` or that uses the same format as described there. Assumes that there is a header and thus skips the first line. @@ -91,7 +89,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: diff --git a/can/io/generic.py b/pycan/io/generic.py similarity index 96% rename from can/io/generic.py rename to pycan/io/generic.py index a61c33a9f..ee6e01aaf 100644 --- a/can/io/generic.py +++ b/pycan/io/generic.py @@ -1,12 +1,10 @@ -# coding: utf-8 - """ Contains a generic class for file IO. """ from abc import ABCMeta, abstractmethod -from can import Listener +from pycan import Listener class BaseIOHandler(object): diff --git a/can/io/logger.py b/pycan/io/logger.py similarity index 81% rename from can/io/logger.py rename to pycan/io/logger.py index 52d2e8d83..9cd86e922 100644 --- a/can/io/logger.py +++ b/pycan/io/logger.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ See the :class:`Logger` class. """ @@ -17,7 +15,7 @@ from .sqlite import SqliteWriter from .printer import Printer -log = logging.getLogger("can.io.logger") +log = logging.getLogger("pycan.io.logger") class Logger(BaseIOHandler, Listener): @@ -25,12 +23,12 @@ class Logger(BaseIOHandler, Listener): Logs CAN messages to a file. The format is determined from the file format which can be one of: - * .asc: :class:`can.ASCWriter` - * .blf :class:`can.BLFWriter` - * .csv: :class:`can.CSVWriter` - * .db: :class:`can.SqliteWriter` - * .log :class:`can.CanutilsLogWriter` - * other: :class:`can.Printer` + * .asc: :class:`pycan.ASCWriter` + * .blf :class:`pycan.BLFWriter` + * .csv: :class:`pycan.CSVWriter` + * .db: :class:`pycan.SqliteWriter` + * .log :class:`pycan.CanutilsLogWriter` + * other: :class:`pycan.Printer` The log files may be incomplete until `stop()` is called due to buffering. @@ -45,7 +43,7 @@ def __new__(cls, filename, *args, **kwargs): :type filename: str or None or path-like :param filename: the filename/path the file to write to, may be a path-like object if the target logger supports - it, and may be None to instantiate a :class:`~can.Printer` + it, and may be None to instantiate a :class:`~pycan.Printer` """ if filename: @@ -61,5 +59,5 @@ def __new__(cls, filename, *args, **kwargs): return CanutilsLogWriter(filename, *args, **kwargs) # else: - log.info('unknown file type "%s", falling pack to can.Printer', filename) + log.info('unknown file type "%s", falling pack to pycan.Printer', filename) return Printer(filename, *args, **kwargs) diff --git a/can/io/player.py b/pycan/io/player.py similarity index 93% rename from can/io/player.py rename to pycan/io/player.py index 229c157c3..f0511b042 100644 --- a/can/io/player.py +++ b/pycan/io/player.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ This module contains the generic :class:`LogReader` as well as :class:`MessageSync` which plays back messages @@ -18,7 +16,7 @@ from .csv import CSVReader from .sqlite import SqliteReader -log = logging.getLogger('can.io.player') +log = logging.getLogger('pycan.io.player') class LogReader(BaseIOHandler): @@ -39,7 +37,7 @@ class LogReader(BaseIOHandler): .. note:: There are no time delays, if you want to reproduce the measured - delays between messages look at the :class:`can.MessageSync` class. + delays between messages look at the :class:`pycan.MessageSync` class. .. note:: This class itself is just a dispatcher, and any positional an keyword @@ -73,7 +71,7 @@ class MessageSync(object): def __init__(self, messages, timestamps=True, gap=0.0001, skip=60): """Creates an new **MessageSync** instance. - :param Iterable[can.Message] messages: An iterable of :class:`can.Message` instances. + :param Iterable[pycan.Message] messages: An iterable of :class:`pycan.Message` instances. :param bool timestamps: Use the messages' timestamps. If False, uses the *gap* parameter as the time between messages. :param float gap: Minimum time between sent messages in seconds :param float skip: Skip periods of inactivity greater than this (in seconds). diff --git a/can/io/printer.py b/pycan/io/printer.py similarity index 82% rename from can/io/printer.py rename to pycan/io/printer.py index 6cc01f69b..f737e7c16 100644 --- a/can/io/printer.py +++ b/pycan/io/printer.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ This Listener simply prints to stdout / the terminal or a file. """ @@ -8,17 +6,17 @@ import logging -from can.listener import Listener +from pycan.listener import Listener from .generic import BaseIOHandler -log = logging.getLogger('can.io.printer') +log = logging.getLogger('pycan.io.printer') class Printer(BaseIOHandler, Listener): """ - The Printer class is a subclass of :class:`~can.Listener` which simply prints + The Printer class is a subclass of :class:`~pycan.Listener` which simply prints any messages it receives to the terminal (stdout). A message is turned into a - string using :meth:`~can.Message.__str__`. + string using :meth:`~pycan.Message.__str__`. :attr bool write_to_file: `True` iff this instance prints to a file instead of standard out diff --git a/can/io/sqlite.py b/pycan/io/sqlite.py similarity index 94% rename from can/io/sqlite.py rename to pycan/io/sqlite.py index 21cd2aafc..7532d6f0c 100644 --- a/can/io/sqlite.py +++ b/pycan/io/sqlite.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ Implements an SQL database writer and reader for storing CAN messages. @@ -14,11 +12,11 @@ import logging import sqlite3 -from can.listener import BufferedReader -from can.message import Message +from pycan.listener import BufferedReader +from pycan.message import Message from .generic import BaseIOHandler -log = logging.getLogger('can.io.sqlite') +log = logging.getLogger('pycan.io.sqlite') if sys.version_info.major < 3: # legacy fallback for Python 2 @@ -79,7 +77,7 @@ def __len__(self): def read_all(self): """Fetches all messages in the database. - :rtype: Generator[can.Message] + :rtype: Generator[pycan.Message] """ result = self._cursor.execute("SELECT * FROM {}".format(self.table_name)).fetchall() return (SqliteReader._assemble_message(frame) for frame in result) @@ -98,9 +96,9 @@ class SqliteWriter(BaseIOHandler, BufferedReader): be created when the first message arrives. Messages are internally buffered and written to the SQL file in a background - thread. Ensures that all messages that are added before calling :meth:`~can.SqliteWriter.stop()` + thread. Ensures that all messages that are added before calling :meth:`~pycan.SqliteWriter.stop()` are actually written to the database after that call returns. Thus, calling - :meth:`~can.SqliteWriter.stop()` may take a while. + :meth:`~pycan.SqliteWriter.stop()` may take a while. :attr str table_name: the name of the database table used for storing the messages :attr int num_frames: the number of frames actually written to the database, this @@ -119,9 +117,9 @@ class SqliteWriter(BaseIOHandler, BufferedReader): is received, the internal buffer is written out to the database file. However if the bus is still saturated with messages, the Listener - will continue receiving until the :attr:`~can.SqliteWriter.MAX_TIME_BETWEEN_WRITES` + will continue receiving until the :attr:`~pycan.SqliteWriter.MAX_TIME_BETWEEN_WRITES` timeout is reached or more than - :attr:`~can.SqliteWriter.MAX_BUFFER_SIZE_BEFORE_WRITES` messages are buffered. + :attr:`~pycan.SqliteWriter.MAX_BUFFER_SIZE_BEFORE_WRITES` messages are buffered. .. note:: The database schema is given in the documentation of the loggers. diff --git a/can/listener.py b/pycan/listener.py similarity index 84% rename from can/listener.py rename to pycan/listener.py index a91b1dac1..13962c82a 100644 --- a/can/listener.py +++ b/pycan/listener.py @@ -1,7 +1,5 @@ -# coding: utf-8 - """ -This module contains the implementation of `can.Listener` and some readers. +This module contains the implementation of `pycan.Listener` and some readers. """ from abc import ABCMeta, abstractmethod @@ -45,10 +43,8 @@ class Listener(object): def on_message_received(self, msg): """This method is called to handle the given message. - :param can.Message msg: the delivered message - + :param pycan.Message msg: the delivered message """ - pass def __call__(self, msg): return self.on_message_received(msg) @@ -83,14 +79,14 @@ def on_message_received(self, msg): class BufferedReader(Listener): """ - A BufferedReader is a subclass of :class:`~can.Listener` which implements a - **message buffer**: that is, when the :class:`can.BufferedReader` instance is + A BufferedReader is a subclass of :class:`~pycan.Listener` which implements a + **message buffer**: that is, when the :class:`pycan.BufferedReader` instance is notified of a new message it pushes it into a queue of messages waiting to be serviced. The messages can then be fetched with - :meth:`~can.BufferedReader.get_message`. + :meth:`~pycan.BufferedReader.get_message`. - Putting in messages after :meth:`~can.BufferedReader.stop` has be called will raise - an exception, see :meth:`~can.BufferedReader.on_message_received`. + Putting in messages after :meth:`~pycan.BufferedReader.stop` has be called will raise + an exception, see :meth:`~pycan.BufferedReader.on_message_received`. :attr bool is_stopped: ``True`` iff the reader has been stopped """ @@ -116,10 +112,10 @@ def get_message(self, timeout=0.5): Attempts to retrieve the latest message received by the instance. If no message is available it blocks for given timeout or until a message is received, or else returns None (whichever is shorter). This method does not block after - :meth:`can.BufferedReader.stop` has been called. + :meth:`pycan.BufferedReader.stop` has been called. :param float timeout: The number of seconds to wait for a new message. - :rytpe: can.Message or None + :rytpe: pycan.Message or None :return: the message if there is one, or None if there is not. """ try: @@ -137,8 +133,8 @@ def stop(self): class AsyncBufferedReader(Listener): """A message buffer for use with :mod:`asyncio`. - See :ref:`asyncio` for how to use with :class:`can.Notifier`. - + See :ref:`asyncio` for how to use with :class:`pycan.Notifier`. + Can also be used as an asynchronous iterator:: async for msg in reader: @@ -151,7 +147,7 @@ def __init__(self, loop=None): def on_message_received(self, msg): """Append a message to the buffer. - + Must only be called inside an event loop! """ self.buffer.put_nowait(msg) @@ -159,16 +155,16 @@ def on_message_received(self, msg): def get_message(self): """ Retrieve the latest message when awaited for:: - + msg = await reader.get_message() - :rtype: can.Message + :rtype: pycan.Message :return: The CAN message. """ return self.buffer.get() def __aiter__(self): return self - + def __anext__(self): return self.buffer.get() diff --git a/can/logger.py b/pycan/logger.py similarity index 92% rename from can/logger.py rename to pycan/logger.py index 204eb8dfb..cb0c15d6f 100644 --- a/can/logger.py +++ b/pycan/logger.py @@ -1,5 +1,3 @@ -# coding: utf-8 - """ logger.py logs CAN traffic to the terminal and to a file on disk. @@ -23,17 +21,17 @@ import socket from datetime import datetime -import can -from can import Bus, BusState, Logger +import pycan +from pycan import Bus, BusState, Logger def main(): parser = argparse.ArgumentParser( - "python -m can.logger", + "python -m pycan.logger", description="Log CAN traffic, printing messages to stdout or to a given file.") parser.add_argument("-f", "--file_name", dest="log_file", - help="""Path and base log filename, for supported types see can.Logger.""", + help="""Path and base log filename, for supported types see pycan.Logger.""", default=None) parser.add_argument("-v", action="count", dest="verbosity", @@ -47,7 +45,7 @@ def main(): parser.add_argument('-i', '--interface', dest="interface", help='''Specify the backend CAN interface to use. If left blank, fall back to reading from configuration files.''', - choices=can.VALID_INTERFACES) + choices=pycan.VALID_INTERFACES) parser.add_argument('--filter', help='''Comma separated filters can be specified for the given CAN interface: : (matches when & mask == can_id & mask) @@ -59,9 +57,9 @@ def main(): state_group = parser.add_mutually_exclusive_group(required=False) state_group.add_argument('--active', help="Start the bus as active, this is applied by default.", - action='store_true') + action='store_true') state_group.add_argument('--passive', help="Start the bus as passive.", - action='store_true') + action='store_true') # print help message when no arguments wre given if len(sys.argv) < 2: @@ -74,7 +72,7 @@ def main(): verbosity = results.verbosity logging_level_name = ['critical', 'error', 'warning', 'info', 'debug', 'subdebug'][min(5, verbosity)] - can.set_logging_level(logging_level_name) + pycan.set_logging_level(logging_level_name) can_filters = [] if len(results.filter) > 0: diff --git a/can/message.py b/pycan/message.py similarity index 96% rename from can/message.py rename to pycan/message.py index f85218fc0..bdc8ef404 100644 --- a/can/message.py +++ b/pycan/message.py @@ -1,7 +1,5 @@ -# coding: utf-8 - """ -This module contains the implementation of :class:`can.Message`. +This module contains the implementation of :class:`pycan.Message`. .. note:: Could use `@dataclass `__ @@ -17,7 +15,7 @@ class Message(object): """ - The :class:`~can.Message` object is used to represent CAN messages for + The :class:`~pycan.Message` object is used to represent CAN messages for sending, receiving and other purposes like converting between different logging formats. @@ -25,7 +23,7 @@ class Message(object): data and may be associated to a channel. Messages are always compared by identity and never by value, because that - may introduce unexpected behaviour. See also :meth:`~can.Message.equals`. + may introduce unexpected behaviour. See also :meth:`~pycan.Message.equals`. :func:`~copy.copy`/:func:`~copy.deepcopy` is supported as well. @@ -203,7 +201,7 @@ def __repr__(self): args.append("is_error_frame={}".format(self.is_error_frame)) if self.channel is not None: - args.append("channel={!r}".format(self.channel)) + args.append("channel={!r}".format(self.channel)) data = ["{:#02x}".format(byte) for byte in self.data] args += ["dlc={}".format(self.dlc), @@ -214,7 +212,7 @@ def __repr__(self): args.append("bitrate_switch={}".format(self.bitrate_switch)) args.append("error_state_indicator={}".format(self.error_state_indicator)) - return "can.Message({})".format(", ".join(args)) + return "pycan.Message({})".format(", ".join(args)) def __format__(self, format_spec): if not format_spec: @@ -309,7 +307,7 @@ def equals(self, other, timestamp_delta=1.0e-6): """ Compares a given message with this one. - :param can.Message other: the message to compare with + :param pycan.Message other: the message to compare with :type timestamp_delta: float or int or None :param timestamp_delta: the maximum difference at which two timestamps are diff --git a/can/notifier.py b/pycan/notifier.py similarity index 84% rename from can/notifier.py rename to pycan/notifier.py index 737ec978e..e422292b6 100644 --- a/can/notifier.py +++ b/pycan/notifier.py @@ -1,7 +1,5 @@ -# coding: utf-8 - """ -This module contains the implementation of :class:`~can.Notifier`. +This module contains the implementation of :class:`~pycan.Notifier`. """ import threading @@ -12,13 +10,13 @@ except ImportError: asyncio = None -logger = logging.getLogger('can.Notifier') +logger = logging.getLogger('pycan.Notifier') class Notifier(object): def __init__(self, bus, listeners, timeout=1.0, loop=None): - """Manages the distribution of :class:`can.Message` instances to listeners. + """Manages the distribution of :class:`pycan.Message` instances to listeners. Supports multiple buses and listeners. @@ -28,8 +26,8 @@ def __init__(self, bus, listeners, timeout=1.0, loop=None): many listeners carry out flush operations to persist data. - :param can.BusABC bus: A :ref:`bus` or a list of buses to listen to. - :param list listeners: An iterable of :class:`~can.Listener` + :param pycan.BusABC bus: A :ref:`bus` or a list of buses to listen to. + :param list listeners: An iterable of :class:`~pycan.Listener` :param float timeout: An optional maximum number of seconds to wait for any message. :param asyncio.AbstractEventLoop loop: An :mod:`asyncio` event loop to schedule listeners in. @@ -53,7 +51,7 @@ def __init__(self, bus, listeners, timeout=1.0, loop=None): def add_bus(self, bus): """Add a bus for notification. - :param can.BusABC bus: + :param pycan.BusABC bus: CAN bus instance. """ if self._loop is not None and hasattr(bus, 'fileno') and bus.fileno() >= 0: @@ -62,14 +60,14 @@ def add_bus(self, bus): self._loop.add_reader(reader, self._on_message_available, bus) else: reader = threading.Thread(target=self._rx_thread, args=(bus,), - name='can.notifier for bus "{}"'.format(bus.channel_info)) + name='pycan.notifier for bus "{}"'.format(bus.channel_info)) reader.daemon = True reader.start() self._readers.append(reader) def stop(self, timeout=5): - """Stop notifying Listeners when new :class:`~can.Message` objects arrive - and call :meth:`~can.Listener.stop` on each Listener. + """Stop notifying Listeners when new :class:`~pycan.Message` objects arrive + and call :meth:`~pycan.Listener.stop` on each Listener. :param float timeout: Max time in seconds to wait for receive threads to finish. @@ -131,7 +129,7 @@ def add_listener(self, listener): If it is already present, it will be called two times each time a message arrives. - :param can.Listener listener: Listener to be added to + :param pycan.Listener listener: Listener to be added to the list to be notified """ self.listeners.append(listener) @@ -141,7 +139,7 @@ def remove_listener(self, listener): trows an exception if the given listener is not part of the stored listeners. - :param can.Listener listener: Listener to be removed from + :param pycan.Listener listener: Listener to be removed from the list to be notified :raises ValueError: if `listener` was never added to this notifier """ diff --git a/can/player.py b/pycan/player.py similarity index 82% rename from can/player.py rename to pycan/player.py index c712f1714..b2fa7e17e 100644 --- a/can/player.py +++ b/pycan/player.py @@ -1,10 +1,8 @@ -# coding: utf-8 - """ -Replays CAN traffic saved with can.logger back +Replays CAN traffic saved with pycan.logger back to a CAN bus. -Similar to canplayer in the can-utils package. +Similar to canplayer in the pycan-utils package. """ from __future__ import absolute_import, print_function @@ -13,17 +11,17 @@ import argparse from datetime import datetime -import can -from can import Bus, LogReader, MessageSync +import pycan +from pycan import Bus, LogReader, MessageSync def main(): parser = argparse.ArgumentParser( - "python -m can.player", + "python -m pycan.player", description="Replay CAN traffic.") parser.add_argument("-f", "--file_name", dest="log_file", - help="""Path and base log filename, for supported types see can.LogReader.""", + help="""Path and base log filename, for supported types see pycan.LogReader.""", default=None) parser.add_argument("-v", action="count", dest="verbosity", @@ -38,7 +36,7 @@ def main(): parser.add_argument('-i', '--interface', dest="interface", help='''Specify the backend CAN interface to use. If left blank, fall back to reading from configuration files.''', - choices=can.VALID_INTERFACES) + choices=pycan.VALID_INTERFACES) parser.add_argument('-b', '--bitrate', type=int, help='''Bitrate to use for the CAN bus.''') @@ -47,13 +45,19 @@ 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, help=''' skip gaps greater than 's' seconds''') parser.add_argument('infile', metavar='input-file', type=str, - help='The file to replay. For supported types see can.LogReader.') + help='The file to replay. For supported types see pycan.LogReader.') # print help message when no arguments were given if len(sys.argv) < 2: @@ -66,7 +70,9 @@ def main(): verbosity = results.verbosity logging_level_name = ['critical', 'error', 'warning', 'info', 'debug', 'subdebug'][min(5, verbosity)] - can.set_logging_level(logging_level_name) + pycan.set_logging_level(logging_level_name) + + error_frames = results.error_frames config = {"single_handle": True} if results.interface: @@ -84,6 +90,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) diff --git a/can/thread_safe_bus.py b/pycan/thread_safe_bus.py similarity index 84% rename from can/thread_safe_bus.py rename to pycan/thread_safe_bus.py index d82ac6bd6..89f038612 100644 --- a/can/thread_safe_bus.py +++ b/pycan/thread_safe_bus.py @@ -1,12 +1,9 @@ -# coding: utf-8 - from __future__ import print_function, absolute_import from threading import RLock try: - # Only raise an exception on instantiation but allow module - # to be imported + # Only raise an exception on instantiation but allow module to be imported from wrapt import ObjectProxy import_exc = None except ImportError as exc: @@ -37,19 +34,19 @@ def __exit__(self, *args): class ThreadSafeBus(ObjectProxy): """ - Contains a thread safe :class:`can.BusABC` implementation that + Contains a thread safe :class:`pycan.BusABC` implementation that wraps around an existing interface instance. All public methods of that base class are now safe to be called from multiple threads. The send and receive methods are synchronized separately. - Use this as a drop-in replacement for :class:`~can.BusABC`. + Use this as a drop-in replacement for :class:`~pycan.BusABC`. .. note:: - This approach assumes that both :meth:`~can.BusABC.send` and - :meth:`~can.BusABC._recv_internal` of the underlying bus instance can be - called simultaneously, and that the methods use :meth:`~can.BusABC._recv_internal` - instead of :meth:`~can.BusABC.recv` directly. + This approach assumes that both :meth:`~pycan.BusABC.send` and + :meth:`~pycan.BusABC._recv_internal` of the underlying bus instance can be + called simultaneously, and that the methods use :meth:`~pycan.BusABC._recv_internal` + instead of :meth:`~pycan.BusABC.recv` directly. """ def __init__(self, *args, **kwargs): @@ -58,7 +55,7 @@ def __init__(self, *args, **kwargs): super(ThreadSafeBus, self).__init__(Bus(*args, **kwargs)) - # now, BusABC.send_periodic() does not need a lock anymore, but the + # Now, BusABC.send_periodic() does not need a lock anymore, but the # implementation still requires a context manager self.__wrapped__._lock_send_periodic = nullcontext() diff --git a/can/util.py b/pycan/util.py similarity index 92% rename from can/util.py rename to pycan/util.py index af421651f..faaaf828e 100644 --- a/can/util.py +++ b/pycan/util.py @@ -1,14 +1,11 @@ -# coding: utf-8 - """ -Utilities and configuration file parsing. +Utilities and configuration file parsing """ from __future__ import absolute_import, print_function import os import os.path -import sys import platform import re import logging @@ -19,10 +16,10 @@ except ImportError: from ConfigParser import SafeConfigParser as ConfigParser -import can -from can.interfaces import VALID_INTERFACES +import pycan +from pycan.interfaces import VALID_INTERFACES -log = logging.getLogger('can.util') +log = logging.getLogger('pycan.util') # List of valid data lengths for a CAN FD message CAN_FD_DLC = [ @@ -36,21 +33,21 @@ ] -CONFIG_FILES = ['~/can.conf'] +CONFIG_FILES = ['~/pycan.conf'] if platform.system() == "Linux": CONFIG_FILES.extend( [ - '/etc/can.conf', - '~/.can', - '~/.canrc' + '/etc/pycan.conf', + '~/.pycan', + '~/.pycanrc' ] ) elif platform.system() == "Windows" or platform.python_implementation() == "IronPython": CONFIG_FILES.extend( [ - 'can.ini', - os.path.join(os.getenv('APPDATA', ''), 'can.ini') + 'pycan.ini', + os.path.join(os.getenv('APPDATA', ''), 'pycan.ini') ] ) @@ -118,11 +115,11 @@ def load_config(path=None, config=None, context=None): - Config files ``/etc/can.conf`` or ``~/.can`` or ``~/.canrc`` where the latter may add or replace values of the former. - Interface can be any of the strings from ``can.VALID_INTERFACES`` for example: + Interface can be any of the strings from ``pycan.VALID_INTERFACES`` for example: kvaser, socketcan, pcan, usb2can, ixxat, nican, virtual. .. note:: - + The key ``bustype`` is copied to ``interface`` if that one is missing and does never appear in the result. @@ -162,7 +159,7 @@ def load_config(path=None, config=None, context=None): # use the given dict for default values config_sources = [ given_config, - can.rc, + pycan.rc, lambda _context: load_environment_config(), # context is not supported lambda _context: load_file_config(path, _context) ] @@ -199,15 +196,15 @@ def load_config(path=None, config=None, context=None): if 'bitrate' in config: config['bitrate'] = int(config['bitrate']) - can.log.debug("can config: {}".format(config)) + pycan.log.debug("can config: {}".format(config)) return config - + def set_logging_level(level_name=None): """Set the logging level for the "can" logger. Expects one of: 'critical', 'error', 'warning', 'info', 'debug', 'subdebug' """ - can_logger = logging.getLogger('can') + can_logger = logging.getLogger('pycan') try: can_logger.setLevel(getattr(logging, level_name.upper())) @@ -248,7 +245,7 @@ def channel2int(channel): :param channel: Channel string (e.g. can0, CAN1) or integer - + :returns: Channel integer or `None` if unsuccessful :rtype: int """ diff --git a/can/viewer.py b/pycan/viewer.py similarity index 96% rename from can/viewer.py rename to pycan/viewer.py index 316d3e3e4..65d777fe9 100644 --- a/can/viewer.py +++ b/pycan/viewer.py @@ -30,11 +30,9 @@ import sys import time import logging -from typing import Dict, List, Tuple, Union -import can -from can import __version__ +import pycan -logger = logging.getLogger('can.serial') +logger = logging.getLogger('pycan.serial') try: import curses @@ -326,7 +324,7 @@ def parse_args(args): kwargs = {'allow_abbrev': False} # Parse command line arguments - parser = argparse.ArgumentParser('python -m can.viewer', + parser = argparse.ArgumentParser('python -m pycan.viewer', description='A simple CAN viewer terminal application written in Python', epilog='R|Shortcuts: ' '\n +---------+-------------------------+' @@ -345,7 +343,7 @@ def parse_args(args): optional.add_argument('-h', '--help', action='help', help='Show this help message and exit') optional.add_argument('--version', action='version', help="Show program's version number and exit", - version='%(prog)s (version {version})'.format(version=__version__)) + version='%(prog)s (version {version})'.format(version=pycan.__version__)) # Copied from: https://github.com/hardbyte/python-can/blob/develop/can/logger.py optional.add_argument('-b', '--bitrate', type=int, help='''Bitrate to use for the given CAN interface''') @@ -370,7 +368,7 @@ def parse_args(args): '\n q = int64_t, Q = uint64_t' '\n f = float (32-bits), d = double (64-bits)' '\nFx to convert six bytes with ID 0x100 into uint8_t, uint16 and uint32_t:' - '\n $ python -m can.viewer -d "100:: (matches when & mask == can_id & mask)' '\n ~ (matches when & mask != can_id & mask)' '\nFx to show only frames with ID 0x100 to 0x103 and 0x200 to 0x20F:' - '\n python -m can.viewer -f 100:7FC 200:7F0' + '\n python -m pycan.viewer -f 100:7FC 200:7F0' '\nNote that the ID and mask are alway interpreted as hex values', metavar='{:,~}', nargs=argparse.ONE_OR_MORE, default='') optional.add_argument('-i', '--interface', dest='interface', help='R|Specify the backend CAN interface to use.', - choices=sorted(can.VALID_INTERFACES)) + choices=sorted(pycan.VALID_INTERFACES)) # Print help message when no arguments are given if len(args) == 0: @@ -490,7 +488,7 @@ def main(): # pragma: no cover config['bitrate'] = parsed_args.bitrate # Create a CAN-Bus interface - bus = can.Bus(parsed_args.channel, **config) + bus = pycan.Bus(parsed_args.channel, **config) # print('Connected to {}: {}'.format(bus.__class__.__name__, bus.channel_info)) curses.wrapper(CanViewer, bus, data_structs) diff --git a/scripts/can_logger.py b/scripts/can_logger.py index 72a92b9d0..a76deadee 100644 --- a/scripts/can_logger.py +++ b/scripts/can_logger.py @@ -1,13 +1,11 @@ #!/usr/bin/env python -# coding: utf-8 - """ See :mod:`can.logger`. """ from __future__ import absolute_import -from can.logger import main +from pycan.logger import main if __name__ == "__main__": diff --git a/scripts/can_player.py b/scripts/can_player.py index afbd3df6e..193aed25b 100644 --- a/scripts/can_player.py +++ b/scripts/can_player.py @@ -1,13 +1,11 @@ #!/usr/bin/env python -# coding: utf-8 - """ See :mod:`can.player`. """ from __future__ import absolute_import -from can.player import main +from pycan.player import main if __name__ == "__main__": diff --git a/scripts/can_viewer.py b/scripts/can_viewer.py index 3c9ba738c..43603da34 100644 --- a/scripts/can_viewer.py +++ b/scripts/can_viewer.py @@ -1,13 +1,11 @@ #!/usr/bin/env python -# coding: utf-8 - """ -See :mod:`can.viewer`. +See :mod:`pycan.viewer`. """ from __future__ import absolute_import -from can.viewer import main +from pycan.viewer import main if __name__ == "__main__": diff --git a/setup.cfg b/setup.cfg index 49177e68e..7821138bc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,16 +8,16 @@ test=pytest license_file = LICENSE.txt [tool:pytest] -addopts = -v --timeout=300 --cov=can --cov-config=setup.cfg +addopts = -v --timeout=300 --cov=pycan --cov-config=setup.cfg [coverage:run] # we could also use branch coverage branch = False -# already specified by call to pytest using --cov=can -#source = can +# already specified by call to pytest using --cov=pycan +#source = pycan omit = # legacy code - can/CAN.py + pycan/CAN.py [coverage:report] # two digits after decimal point diff --git a/setup.py b/setup.py index c600b7215..084ee1361 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,5 @@ -#!/usr/bin/env python -# coding: utf-8 - """ -python-can requires the setuptools package to be installed. +pythoncan requires the setuptools package to be installed """ from __future__ import absolute_import @@ -11,11 +8,12 @@ from os.path import isfile, join import re import logging +import sys from setuptools import setup, find_packages logging.basicConfig(level=logging.WARNING) -with open('can/__init__.py', 'r') as fd: +with open('pycan/__init__.py', 'r') as fd: version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), re.MULTILINE).group(1) @@ -32,20 +30,31 @@ '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 +# 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 - name="python-can", - url="https://github.com/hardbyte/python-can", + name="pythoncan", + url="https://github.com/SpectraLogic/python-can", description="Controller Area Network interface module for Python", long_description=long_description, classifiers=[ @@ -55,6 +64,8 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", @@ -78,7 +89,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 @@ -104,7 +115,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 ) diff --git a/test/__init__.py b/test/__init__.py index 394a0a067..e69de29bb 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,2 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 diff --git a/test/back2back_test.py b/test/back2back_test.py index 4062d462a..364f4d5b3 100644 --- a/test/back2back_test.py +++ b/test/back2back_test.py @@ -1,13 +1,10 @@ #!/usr/bin/env python -# coding: utf-8 - """ This module tests two virtual buses attached to each other. """ from __future__ import absolute_import, print_function -import sys import unittest from time import sleep from multiprocessing.dummy import Pool as ThreadPool @@ -15,7 +12,7 @@ import pytest import random -import can +import pycan from .config import * @@ -35,16 +32,16 @@ class Back2BackTestCase(unittest.TestCase): CHANNEL_2 = 'virtual_channel_0' def setUp(self): - self.bus1 = can.Bus(channel=self.CHANNEL_1, - bustype=self.INTERFACE_1, - bitrate=self.BITRATE, - fd=TEST_CAN_FD, - single_handle=True) - self.bus2 = can.Bus(channel=self.CHANNEL_2, - bustype=self.INTERFACE_2, - bitrate=self.BITRATE, - fd=TEST_CAN_FD, - single_handle=True) + self.bus1 = pycan.Bus(channel=self.CHANNEL_1, + bustype=self.INTERFACE_1, + bitrate=self.BITRATE, + fd=TEST_CAN_FD, + single_handle=True) + self.bus2 = pycan.Bus(channel=self.CHANNEL_2, + bustype=self.INTERFACE_2, + bitrate=self.BITRATE, + fd=TEST_CAN_FD, + single_handle=True) def tearDown(self): self.bus1.shutdown() @@ -83,10 +80,10 @@ def test_no_message(self): @unittest.skipIf(IS_CI, "the timing sensitive behaviour cannot be reproduced reliably on a CI server") def test_timestamp(self): - self.bus2.send(can.Message()) + self.bus2.send(pycan.Message()) recv_msg1 = self.bus1.recv(self.TIMEOUT) sleep(2.0) - self.bus2.send(can.Message()) + self.bus2.send(pycan.Message()) recv_msg2 = self.bus1.recv(self.TIMEOUT) delta_time = recv_msg2.timestamp - recv_msg1.timestamp self.assertTrue(1.75 <= delta_time <= 2.25, @@ -94,45 +91,45 @@ def test_timestamp(self): 'But measured {}'.format(delta_time)) def test_standard_message(self): - msg = can.Message(is_extended_id=False, - arbitration_id=0x100, - data=[1, 2, 3, 4, 5, 6, 7, 8]) + msg = pycan.Message(is_extended_id=False, + arbitration_id=0x100, + data=[1, 2, 3, 4, 5, 6, 7, 8]) self._send_and_receive(msg) def test_extended_message(self): - msg = can.Message(is_extended_id=True, - arbitration_id=0x123456, - data=[10, 11, 12, 13, 14, 15, 16, 17]) + msg = pycan.Message(is_extended_id=True, + arbitration_id=0x123456, + data=[10, 11, 12, 13, 14, 15, 16, 17]) self._send_and_receive(msg) def test_remote_message(self): - msg = can.Message(is_extended_id=False, - arbitration_id=0x200, - is_remote_frame=True, - dlc=4) + msg = pycan.Message(is_extended_id=False, + arbitration_id=0x200, + is_remote_frame=True, + dlc=4) self._send_and_receive(msg) def test_dlc_less_than_eight(self): - msg = can.Message(is_extended_id=False, - arbitration_id=0x300, - data=[4, 5, 6]) + msg = pycan.Message(is_extended_id=False, + arbitration_id=0x300, + data=[4, 5, 6]) self._send_and_receive(msg) @unittest.skipUnless(TEST_CAN_FD, "Don't test CAN-FD") def test_fd_message(self): - msg = can.Message(is_fd=True, - is_extended_id=True, - arbitration_id=0x56789, - data=[0xff] * 64) + msg = pycan.Message(is_fd=True, + is_extended_id=True, + arbitration_id=0x56789, + data=[0xff] * 64) self._send_and_receive(msg) @unittest.skipUnless(TEST_CAN_FD, "Don't test CAN-FD") def test_fd_message_with_brs(self): - msg = can.Message(is_fd=True, - bitrate_switch=True, - is_extended_id=True, - arbitration_id=0x98765, - data=[0xff] * 48) + msg = pycan.Message(is_fd=True, + bitrate_switch=True, + is_extended_id=True, + arbitration_id=0x98765, + data=[0xff] * 48) self._send_and_receive(msg) @@ -149,20 +146,20 @@ class BasicTestSocketCan(Back2BackTestCase): class SocketCanBroadcastChannel(unittest.TestCase): def setUp(self): - self.broadcast_bus = can.Bus(channel='', bustype='socketcan') - self.regular_bus = can.Bus(channel='vcan0', bustype='socketcan') + self.broadcast_bus = pycan.Bus(channel='', bustype='socketcan') + self.regular_bus = pycan.Bus(channel='vcan0', bustype='socketcan') def tearDown(self): self.broadcast_bus.shutdown() self.regular_bus.shutdown() def test_broadcast_channel(self): - self.broadcast_bus.send(can.Message(channel='vcan0')) + self.broadcast_bus.send(pycan.Message(channel='vcan0')) recv_msg = self.regular_bus.recv(1) self.assertIsNotNone(recv_msg) self.assertEqual(recv_msg.channel, 'vcan0') - self.regular_bus.send(can.Message()) + self.regular_bus.send(pycan.Message()) recv_msg = self.broadcast_bus.recv(1) self.assertIsNotNone(recv_msg) self.assertEqual(recv_msg.channel, 'vcan0') @@ -171,23 +168,23 @@ def test_broadcast_channel(self): class TestThreadSafeBus(Back2BackTestCase): def setUp(self): - self.bus1 = can.ThreadSafeBus(channel=self.CHANNEL_1, - bustype=self.INTERFACE_1, - bitrate=self.BITRATE, - fd=TEST_CAN_FD, - single_handle=True) - self.bus2 = can.ThreadSafeBus(channel=self.CHANNEL_2, - bustype=self.INTERFACE_2, - bitrate=self.BITRATE, - fd=TEST_CAN_FD, - single_handle=True) + self.bus1 = pycan.ThreadSafeBus(channel=self.CHANNEL_1, + bustype=self.INTERFACE_1, + bitrate=self.BITRATE, + fd=TEST_CAN_FD, + single_handle=True) + self.bus2 = pycan.ThreadSafeBus(channel=self.CHANNEL_2, + bustype=self.INTERFACE_2, + bitrate=self.BITRATE, + fd=TEST_CAN_FD, + single_handle=True) @pytest.mark.timeout(5.0) def test_concurrent_writes(self): sender_pool = ThreadPool(100) receiver_pool = ThreadPool(100) - message = can.Message( + message = pycan.Message( arbitration_id=0x123, channel=self.CHANNEL_1, is_extended_id=True, @@ -218,14 +215,14 @@ def test_filtered_bus(self): sender_pool = ThreadPool(100) receiver_pool = ThreadPool(100) - included_message = can.Message( + included_message = pycan.Message( arbitration_id=0x123, channel=self.CHANNEL_1, is_extended_id=True, timestamp=121334.365, data=[254, 255, 1, 2] ) - excluded_message = can.Message( + excluded_message = pycan.Message( arbitration_id=0x02, channel=self.CHANNEL_1, is_extended_id=True, diff --git a/test/config.py b/test/config.py index 940ba7cf0..97c74b079 100644 --- a/test/config.py +++ b/test/config.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - """ This module contains various configuration for the tests. diff --git a/test/contextmanager_test.py b/test/contextmanager_test.py index 35bc045da..9920674bd 100644 --- a/test/contextmanager_test.py +++ b/test/contextmanager_test.py @@ -1,22 +1,20 @@ #!/usr/bin/env python -# coding: utf-8 - """ This module tests the context manager of Bus and Notifier classes """ import unittest -import can +import pycan class ContextManagerTest(unittest.TestCase): def setUp(self): data = [0, 1, 2, 3, 4, 5, 6, 7] - self.msg_send = can.Message(is_extended_id=False, arbitration_id=0x100, data=data) + self.msg_send = pycan.Message(is_extended_id=False, arbitration_id=0x100, data=data) def test_open_buses(self): - with can.Bus(interface='virtual') as bus_send, can.Bus(interface='virtual') as bus_recv: + with pycan.Bus(interface='virtual') as bus_send, pycan.Bus(interface='virtual') as bus_recv: bus_send.send(self.msg_send) msg_recv = bus_recv.recv() @@ -24,12 +22,12 @@ def test_open_buses(self): self.assertTrue(msg_recv) def test_use_closed_bus(self): - with can.Bus(interface='virtual') as bus_send, can.Bus(interface='virtual') as bus_recv: + with pycan.Bus(interface='virtual') as bus_send, pycan.Bus(interface='virtual') as bus_recv: bus_send.send(self.msg_send) # Receiving a frame after bus has been closed should raise a CanException - self.assertRaises(can.CanError, bus_recv.recv) - self.assertRaises(can.CanError, bus_send.send, self.msg_send) + self.assertRaises(pycan.CanError, bus_recv.recv) + self.assertRaises(pycan.CanError, bus_send.send, self.msg_send) if __name__ == '__main__': diff --git a/test/data/example_data.py b/test/data/example_data.py index dd433dc3c..c80c5b7e5 100644 --- a/test/data/example_data.py +++ b/test/data/example_data.py @@ -9,7 +9,7 @@ import random from operator import attrgetter -from can import Message +from pycan import Message # make tests more reproducible random.seed(13339115) @@ -19,7 +19,7 @@ def sort_messages(messages): """ Sorts the given messages by timestamps (ascending). - :param Iterable[can.Message] messages: a sequence of messages to sort + :param Iterable[pycan.Message] messages: a sequence of messages to sort :rtype: list """ return list(sorted(messages, key=attrgetter('timestamp'))) 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 diff --git a/test/listener_test.py b/test/listener_test.py index c25a6fb56..bc9384729 100644 --- a/test/listener_test.py +++ b/test/listener_test.py @@ -1,26 +1,19 @@ #!/usr/bin/env python -# coding: utf-8 - -""" -""" - from __future__ import absolute_import, print_function -from time import sleep import unittest import random import logging import tempfile -import sqlite3 import os from os.path import join, dirname -import can +import pycan from .data.example_data import generate_message channel = 'virtual_channel_0' -can.rc['interface'] = 'virtual' +pycan.rc['interface'] = 'virtual' logging.basicConfig(level=logging.DEBUG) @@ -31,37 +24,37 @@ class ListenerImportTest(unittest.TestCase): def testClassesImportable(self): - self.assertTrue(hasattr(can, 'Listener')) - self.assertTrue(hasattr(can, 'BufferedReader')) - self.assertTrue(hasattr(can, 'Notifier')) - self.assertTrue(hasattr(can, 'Logger')) + self.assertTrue(hasattr(pycan, 'Listener')) + self.assertTrue(hasattr(pycan, 'BufferedReader')) + self.assertTrue(hasattr(pycan, 'Notifier')) + self.assertTrue(hasattr(pycan, 'Logger')) - self.assertTrue(hasattr(can, 'ASCWriter')) - self.assertTrue(hasattr(can, 'ASCReader')) + self.assertTrue(hasattr(pycan, 'ASCWriter')) + self.assertTrue(hasattr(pycan, 'ASCReader')) - self.assertTrue(hasattr(can, 'BLFReader')) - self.assertTrue(hasattr(can, 'BLFWriter')) + self.assertTrue(hasattr(pycan, 'BLFReader')) + self.assertTrue(hasattr(pycan, 'BLFWriter')) - self.assertTrue(hasattr(can, 'CSVReader')) - self.assertTrue(hasattr(can, 'CSVWriter')) + self.assertTrue(hasattr(pycan, 'CSVReader')) + self.assertTrue(hasattr(pycan, 'CSVWriter')) - self.assertTrue(hasattr(can, 'CanutilsLogWriter')) - self.assertTrue(hasattr(can, 'CanutilsLogReader')) + self.assertTrue(hasattr(pycan, 'CanutilsLogWriter')) + self.assertTrue(hasattr(pycan, 'CanutilsLogReader')) - self.assertTrue(hasattr(can, 'SqliteReader')) - self.assertTrue(hasattr(can, 'SqliteWriter')) + self.assertTrue(hasattr(pycan, 'SqliteReader')) + self.assertTrue(hasattr(pycan, 'SqliteWriter')) - self.assertTrue(hasattr(can, 'Printer')) + self.assertTrue(hasattr(pycan, 'Printer')) - self.assertTrue(hasattr(can, 'LogReader')) + self.assertTrue(hasattr(pycan, 'LogReader')) - self.assertTrue(hasattr(can, 'MessageSync')) + self.assertTrue(hasattr(pycan, 'MessageSync')) class BusTest(unittest.TestCase): def setUp(self): - self.bus = can.interface.Bus() + self.bus = pycan.interface.Bus() def tearDown(self): self.bus.shutdown() @@ -70,22 +63,22 @@ def tearDown(self): class ListenerTest(BusTest): def testBasicListenerCanBeAddedToNotifier(self): - a_listener = can.Printer() - notifier = can.Notifier(self.bus, [a_listener], 0.1) + a_listener = pycan.Printer() + notifier = pycan.Notifier(self.bus, [a_listener], 0.1) notifier.stop() self.assertIn(a_listener, notifier.listeners) def testAddListenerToNotifier(self): - a_listener = can.Printer() - notifier = can.Notifier(self.bus, [], 0.1) + a_listener = pycan.Printer() + notifier = pycan.Notifier(self.bus, [], 0.1) notifier.stop() self.assertNotIn(a_listener, notifier.listeners) notifier.add_listener(a_listener) self.assertIn(a_listener, notifier.listeners) def testRemoveListenerFromNotifier(self): - a_listener = can.Printer() - notifier = can.Notifier(self.bus, [a_listener], 0.1) + a_listener = pycan.Printer() + notifier = pycan.Notifier(self.bus, [a_listener], 0.1) notifier.stop() self.assertIn(a_listener, notifier.listeners) notifier.remove_listener(a_listener) @@ -104,21 +97,21 @@ def test_filetype_to_instance(extension, klass): with file_handler as my_file: filename = my_file.name - with can.LogReader(filename) as reader: + with pycan.LogReader(filename) as reader: self.assertIsInstance(reader, klass) finally: if delete: os.remove(filename) - test_filetype_to_instance(".asc", can.ASCReader) - test_filetype_to_instance(".blf", can.BLFReader) - test_filetype_to_instance(".csv", can.CSVReader) - test_filetype_to_instance(".db" , can.SqliteReader) - test_filetype_to_instance(".log", can.CanutilsLogReader) + test_filetype_to_instance(".asc", pycan.ASCReader) + test_filetype_to_instance(".blf", pycan.BLFReader) + test_filetype_to_instance(".csv", pycan.CSVReader) + test_filetype_to_instance(".db" , pycan.SqliteReader) + test_filetype_to_instance(".log", pycan.CanutilsLogReader) # test file extensions that are not supported with self.assertRaisesRegexp(NotImplementedError, ".xyz_42"): - test_filetype_to_instance(".xyz_42", can.Printer) + test_filetype_to_instance(".xyz_42", pycan.Printer) def testLoggerTypeResolution(self): def test_filetype_to_instance(extension, klass): @@ -126,27 +119,27 @@ def test_filetype_to_instance(extension, klass): try: with tempfile.NamedTemporaryFile(suffix=extension, delete=False) as my_file: filename = my_file.name - with can.Logger(filename) as writer: + with pycan.Logger(filename) as writer: self.assertIsInstance(writer, klass) finally: os.remove(filename) - test_filetype_to_instance(".asc", can.ASCWriter) - test_filetype_to_instance(".blf", can.BLFWriter) - test_filetype_to_instance(".csv", can.CSVWriter) - test_filetype_to_instance(".db" , can.SqliteWriter) - test_filetype_to_instance(".log", can.CanutilsLogWriter) - test_filetype_to_instance(".txt", can.Printer) + test_filetype_to_instance(".asc", pycan.ASCWriter) + test_filetype_to_instance(".blf", pycan.BLFWriter) + test_filetype_to_instance(".csv", pycan.CSVWriter) + test_filetype_to_instance(".db" , pycan.SqliteWriter) + test_filetype_to_instance(".log", pycan.CanutilsLogWriter) + test_filetype_to_instance(".txt", pycan.Printer) # test file extensions that should use a fallback - test_filetype_to_instance("", can.Printer) - test_filetype_to_instance(".", can.Printer) - test_filetype_to_instance(".some_unknown_extention_42", can.Printer) - with can.Logger(None) as logger: - self.assertIsInstance(logger, can.Printer) + test_filetype_to_instance("", pycan.Printer) + test_filetype_to_instance(".", pycan.Printer) + test_filetype_to_instance(".some_unknown_extention_42", pycan.Printer) + with pycan.Logger(None) as logger: + self.assertIsInstance(logger, pycan.Printer) def testBufferedListenerReceives(self): - a_listener = can.BufferedReader() + a_listener = pycan.BufferedReader() a_listener(generate_message(0xDADADA)) a_listener(generate_message(0xDADADA)) self.assertIsNotNone(a_listener.get_message(0.1)) diff --git a/test/logformats_test.py b/test/logformats_test.py index d9551e5d6..94711c282 100644 --- a/test/logformats_test.py +++ b/test/logformats_test.py @@ -1,8 +1,6 @@ #!/usr/bin/env python -# coding: utf-8 - """ -This test module test the separate reader/writer combinations of the can.io.* +This test module test the separate reader/writer combinations of the pycan.io.* modules by writing some messages to a temporary file and reading it again. Then it checks if the messages that were read are same ones as the ones that were written. It also checks that the order of the messages @@ -29,7 +27,7 @@ # Python 2 from itertools import izip_longest as zip_longest -import can +import pycan from .data.example_data import TEST_MESSAGES_BASE, TEST_MESSAGES_REMOTE_FRAMES, \ TEST_MESSAGES_ERROR_FRAMES, TEST_COMMENTS, \ @@ -81,7 +79,7 @@ def _setup_instance_helper(self, but deterministically, which makes the test reproducible. :param bool test_append: tests the writer in append mode as well - :param float or int or None allowed_timestamp_delta: directly passed to :meth:`can.Message.equals` + :param float or int or None allowed_timestamp_delta: directly passed to :meth:`pycan.Message.equals` :param bool preserves_channel: if True, checks that the channel attribute is preserved :param any adds_default_channel: sets this as the channel when not other channel was given ignored, if *preserves_channel* is True @@ -175,7 +173,7 @@ def test_path_like_context_manager(self): if hasattr(r.file, 'closed'): self.assertTrue(r.file.closed) - # check if at least the number of messages matches; + # check if at least the number of messages matches; self.assertEqual(len(read_messages), len(self.original_messages), "the number of written messages does not match the number of read messages") @@ -234,7 +232,7 @@ def test_file_like_context_manager(self): if hasattr(my_file, 'closed'): self.assertTrue(my_file.closed) - # check if at least the number of messages matches; + # check if at least the number of messages matches; self.assertEqual(len(read_messages), len(self.original_messages), "the number of written messages does not match the number of read messages") @@ -310,23 +308,23 @@ def assertIncludesComments(self, filename): class TestAscFileFormat(ReaderWriterTest): - """Tests can.ASCWriter and can.ASCReader""" + """Tests pycan.ASCWriter and pycan.ASCReader""" def _setup_instance(self): super(TestAscFileFormat, self)._setup_instance_helper( - can.ASCWriter, can.ASCReader, - check_fd=False, + pycan.ASCWriter, pycan.ASCReader, + check_fd=True, check_comments=True, preserves_channel=False, adds_default_channel=0 ) class TestBlfFileFormat(ReaderWriterTest): - """Tests can.BLFWriter and can.BLFReader""" + """Tests pycan.BLFWriter and pycan.BLFReader""" def _setup_instance(self): super(TestBlfFileFormat, self)._setup_instance_helper( - can.BLFWriter, can.BLFReader, + pycan.BLFWriter, pycan.BLFReader, binary_file=True, check_fd=False, check_comments=False, @@ -336,16 +334,16 @@ def _setup_instance(self): def test_read_known_file(self): logfile = os.path.join(os.path.dirname(__file__), "data", "logfile.blf") - with can.BLFReader(logfile) as reader: + with pycan.BLFReader(logfile) as reader: messages = list(reader) expected = [ - can.Message( + pycan.Message( timestamp=1.0, is_extended_id=False, arbitration_id=0x64, data=[0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]), - can.Message( + pycan.Message( timestamp=73.0, is_extended_id=True, arbitration_id=0x1FFFFFFF, @@ -356,11 +354,11 @@ def test_read_known_file(self): class TestCanutilsFileFormat(ReaderWriterTest): - """Tests can.CanutilsLogWriter and can.CanutilsLogReader""" + """Tests pycan.CanutilsLogWriter and pycan.CanutilsLogReader""" def _setup_instance(self): super(TestCanutilsFileFormat, self)._setup_instance_helper( - can.CanutilsLogWriter, can.CanutilsLogReader, + pycan.CanutilsLogWriter, pycan.CanutilsLogReader, check_fd=False, test_append=True, check_comments=False, preserves_channel=False, adds_default_channel='vcan0' @@ -368,11 +366,11 @@ def _setup_instance(self): class TestCsvFileFormat(ReaderWriterTest): - """Tests can.ASCWriter and can.ASCReader""" + """Tests pycan.ASCWriter and pycan.ASCReader""" def _setup_instance(self): super(TestCsvFileFormat, self)._setup_instance_helper( - can.CSVWriter, can.CSVReader, + pycan.CSVWriter, pycan.CSVReader, check_fd=False, test_append=True, check_comments=False, preserves_channel=False, adds_default_channel=None @@ -380,11 +378,11 @@ def _setup_instance(self): class TestSqliteDatabaseFormat(ReaderWriterTest): - """Tests can.SqliteWriter and can.SqliteReader""" + """Tests pycan.SqliteWriter and pycan.SqliteReader""" def _setup_instance(self): super(TestSqliteDatabaseFormat, self)._setup_instance_helper( - can.SqliteWriter, can.SqliteReader, + pycan.SqliteWriter, pycan.SqliteReader, check_fd=False, test_append=True, check_comments=False, preserves_channel=False, adds_default_channel=None @@ -400,7 +398,7 @@ def test_file_like_context_manager(self): def test_read_all(self): """ - testing :meth:`can.SqliteReader.read_all` with context manager and path-like object + testing :meth:`pycan.SqliteReader.read_all` with context manager and path-like object """ # create writer print("writing all messages/comments") @@ -412,7 +410,7 @@ def test_read_all(self): with self.reader_constructor(self.test_file_name) as reader: read_messages = list(reader.read_all()) - # check if at least the number of messages matches; + # check if at least the number of messages matches; self.assertEqual(len(read_messages), len(self.original_messages), "the number of written messages does not match the number of read messages") @@ -420,19 +418,19 @@ def test_read_all(self): class TestPrinter(unittest.TestCase): - """Tests that can.Printer does not crash""" + """Tests that pycan.Printer does not crash""" # TODO add CAN FD messages messages = TEST_MESSAGES_BASE + TEST_MESSAGES_REMOTE_FRAMES + TEST_MESSAGES_ERROR_FRAMES def test_not_crashes_with_stdout(self): - with can.Printer() as printer: + with pycan.Printer() as printer: for message in self.messages: printer(message) def test_not_crashes_with_file(self): with tempfile.NamedTemporaryFile('w', delete=False) as temp_file: - with can.Printer(temp_file) as printer: + with pycan.Printer(temp_file) as printer: for message in self.messages: printer(message) diff --git a/test/message_helper.py b/test/message_helper.py index 9a4756207..cfc26816f 100644 --- a/test/message_helper.py +++ b/test/message_helper.py @@ -1,8 +1,6 @@ #!/usr/bin/env python -# coding: utf-8 - """ -This module contains a helper for writing test cases that need to compare messages. +This module contains a helper for writing test cases that need to compare messages """ from __future__ import absolute_import, print_function @@ -20,7 +18,7 @@ class ComparingMessagesTestCase(object): def __init__(self, allowed_timestamp_delta=0.0, preserves_channel=True): """ - :param float or int or None allowed_timestamp_delta: directly passed to :meth:`can.Message.equals` + :param float or int or None allowed_timestamp_delta: directly passed to :meth:`pycan.Message.equals` :param bool preserves_channel: if True, checks that the channel attribute is preserved """ self.allowed_timestamp_delta = allowed_timestamp_delta diff --git a/test/network_test.py b/test/network_test.py index f4163329d..4bae93f5f 100644 --- a/test/network_test.py +++ b/test/network_test.py @@ -1,29 +1,22 @@ #!/usr/bin/env python -# coding: utf-8 - from __future__ import print_function import unittest import threading -try: - import queue -except ImportError: - import Queue as queue import random - import logging logging.getLogger(__file__).setLevel(logging.WARNING) -# make a random bool: +# Make a random bool: rbool = lambda: bool(round(random.random())) -import can +import pycan channel = 'vcan0' -can.rc['interface'] = 'virtual' +pycan.rc['interface'] = 'virtual' -@unittest.skipIf('interface' not in can.rc, "Need a CAN interface") +@unittest.skipIf('interface' not in pycan.rc, "Need a CAN interface") class ControllerAreaNetworkTestCase(unittest.TestCase): """ This test ensures that what messages go in to the bus is what comes out. @@ -48,10 +41,10 @@ class ControllerAreaNetworkTestCase(unittest.TestCase): for b in range(num_messages)) def producer(self, ready_event, msg_read): - self.client_bus = can.interface.Bus(channel=channel) + self.client_bus = pycan.interface.Bus(channel=channel) ready_event.wait() for i in range(self.num_messages): - m = can.Message( + m = pycan.Message( arbitration_id=self.ids[i], is_remote_frame=self.remote_flags[i], is_error_frame=self.error_flags[i], @@ -80,7 +73,7 @@ def testProducerConsumer(self): ready = threading.Event() msg_read = threading.Event() - self.server_bus = can.interface.Bus(channel=channel) + self.server_bus = pycan.interface.Bus(channel=channel) t = threading.Thread(target=self.producer, args=(ready, msg_read)) t.start() diff --git a/test/notifier_test.py b/test/notifier_test.py index 3ab257cf7..0357c14fe 100644 --- a/test/notifier_test.py +++ b/test/notifier_test.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - import unittest import time try: @@ -8,27 +6,27 @@ except ImportError: asyncio = None -import can +import pycan class NotifierTest(unittest.TestCase): def test_single_bus(self): - bus = can.Bus('test', bustype='virtual', receive_own_messages=True) - reader = can.BufferedReader() - notifier = can.Notifier(bus, [reader], 0.1) - msg = can.Message() + bus = pycan.Bus('test', bustype='virtual', receive_own_messages=True) + reader = pycan.BufferedReader() + notifier = pycan.Notifier(bus, [reader], 0.1) + msg = pycan.Message() bus.send(msg) self.assertIsNotNone(reader.get_message(1)) notifier.stop() bus.shutdown() def test_multiple_bus(self): - bus1 = can.Bus(0, bustype='virtual', receive_own_messages=True) - bus2 = can.Bus(1, bustype='virtual', receive_own_messages=True) - reader = can.BufferedReader() - notifier = can.Notifier([bus1, bus2], [reader], 0.1) - msg = can.Message() + bus1 = pycan.Bus(0, bustype='virtual', receive_own_messages=True) + bus2 = pycan.Bus(1, bustype='virtual', receive_own_messages=True) + reader = pycan.BufferedReader() + notifier = pycan.Notifier([bus1, bus2], [reader], 0.1) + msg = pycan.Message() bus1.send(msg) time.sleep(0.1) bus2.send(msg) @@ -48,10 +46,10 @@ class AsyncNotifierTest(unittest.TestCase): @unittest.skipIf(asyncio is None, 'Test requires asyncio') def test_asyncio_notifier(self): loop = asyncio.get_event_loop() - bus = can.Bus('test', bustype='virtual', receive_own_messages=True) - reader = can.AsyncBufferedReader() - notifier = can.Notifier(bus, [reader], 0.1, loop=loop) - msg = can.Message() + bus = pycan.Bus('test', bustype='virtual', receive_own_messages=True) + reader = pycan.AsyncBufferedReader() + notifier = pycan.Notifier(bus, [reader], 0.1, loop=loop) + msg = pycan.Message() bus.send(msg) future = asyncio.wait_for(reader.get_message(), 1.0) recv_msg = loop.run_until_complete(future) @@ -60,6 +58,5 @@ def test_asyncio_notifier(self): bus.shutdown() - if __name__ == '__main__': unittest.main() diff --git a/test/serial_test.py b/test/serial_test.py index 5b26ae42a..d9aa6a048 100644 --- a/test/serial_test.py +++ b/test/serial_test.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - """ This module is testing the serial interface. @@ -12,8 +10,8 @@ import unittest from mock import patch -import can -from can.interfaces.serial.serial_can import SerialBus +import pycan +from pycan.interfaces.serial.serial_can import SerialBus from .message_helper import ComparingMessagesTestCase @@ -52,7 +50,7 @@ def test_rx_tx_min_max_data(self): Tests the transfer from 0x00 to 0xFF for a 1 byte payload """ for b in range(0, 255): - msg = can.Message(data=[b]) + msg = pycan.Message(data=[b]) self.bus.send(msg) msg_receive = self.bus.recv() self.assertMessageEqual(msg, msg_receive) @@ -64,7 +62,7 @@ def test_rx_tx_min_max_dlc(self): payload = bytearray() for b in range(1, 9): payload.append(0) - msg = can.Message(data=payload) + msg = pycan.Message(data=payload) self.bus.send(msg) msg_receive = self.bus.recv() self.assertMessageEqual(msg, msg_receive) @@ -73,7 +71,7 @@ def test_rx_tx_data_none(self): """ Tests the transfer without payload """ - msg = can.Message(data=None) + msg = pycan.Message(data=None) self.bus.send(msg) msg_receive = self.bus.recv() self.assertMessageEqual(msg, msg_receive) @@ -82,7 +80,7 @@ def test_rx_tx_min_id(self): """ Tests the transfer with the lowest arbitration id """ - msg = can.Message(arbitration_id=0) + msg = pycan.Message(arbitration_id=0) self.bus.send(msg) msg_receive = self.bus.recv() self.assertMessageEqual(msg, msg_receive) @@ -91,7 +89,7 @@ def test_rx_tx_max_id(self): """ Tests the transfer with the highest arbitration id """ - msg = can.Message(arbitration_id=536870911) + msg = pycan.Message(arbitration_id=536870911) self.bus.send(msg) msg_receive = self.bus.recv() self.assertMessageEqual(msg, msg_receive) @@ -101,7 +99,7 @@ def test_rx_tx_max_timestamp(self): Tests the transfer with the highest possible timestamp """ - msg = can.Message(timestamp=self.MAX_TIMESTAMP) + msg = pycan.Message(timestamp=self.MAX_TIMESTAMP) self.bus.send(msg) msg_receive = self.bus.recv() self.assertMessageEqual(msg, msg_receive) @@ -111,14 +109,14 @@ def test_rx_tx_max_timestamp_error(self): """ Tests for an exception with an out of range timestamp (max + 1) """ - msg = can.Message(timestamp=self.MAX_TIMESTAMP+1) + msg = pycan.Message(timestamp=self.MAX_TIMESTAMP+1) self.assertRaises(ValueError, self.bus.send, msg) def test_rx_tx_min_timestamp(self): """ Tests the transfer with the lowest possible timestamp """ - msg = can.Message(timestamp=0) + msg = pycan.Message(timestamp=0) self.bus.send(msg) msg_receive = self.bus.recv() self.assertMessageEqual(msg, msg_receive) @@ -128,7 +126,7 @@ def test_rx_tx_min_timestamp_error(self): """ Tests for an exception with an out of range timestamp (min - 1) """ - msg = can.Message(timestamp=-1) + msg = pycan.Message(timestamp=-1) self.assertRaises(ValueError, self.bus.send, msg) diff --git a/test/simplecyclic_test.py b/test/simplecyclic_test.py index a10871648..50386594e 100644 --- a/test/simplecyclic_test.py +++ b/test/simplecyclic_test.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - """ This module tests cyclic send tasks. """ @@ -11,7 +9,7 @@ import unittest import gc -import can +import pycan from .config import * from .message_helper import ComparingMessagesTestCase @@ -21,26 +19,26 @@ class SimpleCyclicSendTaskTest(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) + ComparingMessagesTestCase.__init__(self, allowed_timestamp_delta=0.03, preserves_channel=True) @unittest.skipIf(IS_CI, "the timing sensitive behaviour cannot be reproduced reliably on a CI server") def test_cycle_time(self): - msg = can.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) + msg = pycan.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) - with can.interface.Bus(bustype='virtual') as bus1: - with can.interface.Bus(bustype='virtual') as bus2: + with pycan.interface.Bus(bustype='virtual') as bus1: + with pycan.interface.Bus(bustype='virtual') as bus2: # disabling the garbage collector makes the time readings more reliable gc.disable() task = bus1.send_periodic(msg, 0.01, 1) - self.assertIsInstance(task, can.broadcastmanager.CyclicSendTaskABC) + self.assertIsInstance(task, pycan.broadcastmanager.CyclicSendTaskABC) sleep(2) size = bus2.queue.qsize() # About 100 messages should have been transmitted - self.assertTrue(80 <= size <= 120, - '100 +/- 20 messages should have been transmitted. But queue contained {}'.format(size)) + self.assertTrue(60 <= size <= 100, + 'at least 60 messages should have been transmitted. But queue contained {}'.format(size)) last_msg = bus2.recv() next_last_msg = bus2.recv() @@ -53,20 +51,20 @@ def test_cycle_time(self): # Check the message id/data sent is the same as message received # Set timestamp and channel to match recv'd because we don't care - # and they are not initialized by the can.Message constructor. + # and they are not initialized by the pycan.Message constructor. msg.timestamp = last_msg.timestamp msg.channel = last_msg.channel self.assertMessageEqual(msg, last_msg) def test_removing_bus_tasks(self): - bus = can.interface.Bus(bustype='virtual') + bus = pycan.interface.Bus(bustype='virtual') tasks = [] for task_i in range(10): - msg = can.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) + msg = pycan.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) msg.arbitration_id = task_i task = bus.send_periodic(msg, 0.1, 1) tasks.append(task) - self.assertIsInstance(task, can.broadcastmanager.CyclicSendTaskABC) + self.assertIsInstance(task, pycan.broadcastmanager.CyclicSendTaskABC) assert len(bus._periodic_tasks) == 10 @@ -78,14 +76,14 @@ def test_removing_bus_tasks(self): bus.shutdown() def test_managed_tasks(self): - bus = can.interface.Bus(bustype='virtual', receive_own_messages=True) + bus = pycan.interface.Bus(bustype='virtual', receive_own_messages=True) tasks = [] for task_i in range(3): - msg = can.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) + msg = pycan.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) msg.arbitration_id = task_i task = bus.send_periodic(msg, 0.1, 10, store_task=False) tasks.append(task) - self.assertIsInstance(task, can.broadcastmanager.CyclicSendTaskABC) + self.assertIsInstance(task, pycan.broadcastmanager.CyclicSendTaskABC) assert len(bus._periodic_tasks) == 0 @@ -104,10 +102,10 @@ def test_managed_tasks(self): bus.shutdown() def test_stopping_perodic_tasks(self): - bus = can.interface.Bus(bustype='virtual') + bus = pycan.interface.Bus(bustype='virtual') tasks = [] for task_i in range(10): - msg = can.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) + msg = pycan.Message(is_extended_id=False, arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5, 6, 7]) msg.arbitration_id = task_i task = bus.send_periodic(msg, 0.1, 1) tasks.append(task) diff --git a/test/test_detect_available_configs.py b/test/test_detect_available_configs.py index ca2d82c15..329e98111 100644 --- a/test/test_detect_available_configs.py +++ b/test/test_detect_available_configs.py @@ -1,9 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 - """ -This module tests :meth:`can.BusABC._detect_available_configs` and -:meth:`can.BusABC.detect_available_configs`. +This module tests :meth:`pycan.BusABC._detect_available_configs` and +:meth:`pycan.BusABC.detect_available_configs`. """ from __future__ import absolute_import @@ -13,9 +11,9 @@ if sys.version_info.major > 2: basestring = str -from can import detect_available_configs +from pycan import detect_available_configs -from .config import IS_LINUX, IS_CI, TEST_INTERFACE_SOCKETCAN +from .config import TEST_INTERFACE_SOCKETCAN class TestDetectAvailableConfigs(unittest.TestCase): diff --git a/test/test_kvaser.py b/test/test_kvaser.py index 3e0bcf396..8e2ae86c8 100644 --- a/test/test_kvaser.py +++ b/test/test_kvaser.py @@ -1,23 +1,17 @@ #!/usr/bin/env python -# coding: utf-8 -""" -""" - -import ctypes import time -import logging import unittest try: - from unittest.mock import Mock, patch + from unittest.mock import Mock except ImportError: - from mock import patch, Mock + from mock import Mock import pytest -import can -from can.interfaces.kvaser import canlib -from can.interfaces.kvaser import constants +import pycan +from pycan.interfaces.kvaser import canlib +from pycan.interfaces.kvaser import constants class KvaserTest(unittest.TestCase): @@ -43,7 +37,7 @@ def setUp(self): self.msg = {} self.msg_in_cue = None - self.bus = can.Bus(channel=0, bustype='kvaser') + self.bus = pycan.Bus(channel=0, bustype='kvaser') def tearDown(self): if self.bus: @@ -100,7 +94,7 @@ def test_filter_setup(self): expected_args) def test_send_extended(self): - msg = can.Message( + msg = pycan.Message( arbitration_id=0xc0ffee, data=[0, 25, 0, 1, 3, 1, 4], is_extended_id=True) @@ -113,7 +107,7 @@ def test_send_extended(self): self.assertSequenceEqual(self.msg['data'], [0, 25, 0, 1, 3, 1, 4]) def test_send_standard(self): - msg = can.Message( + msg = pycan.Message( arbitration_id=0x321, data=[50, 51], is_extended_id=False) @@ -130,7 +124,7 @@ def test_recv_no_message(self): self.assertEqual(self.bus.recv(timeout=0.5), None) def test_recv_extended(self): - self.msg_in_cue = can.Message( + self.msg_in_cue = pycan.Message( arbitration_id=0xc0ffef, data=[1, 2, 3, 4, 5, 6, 7, 8], is_extended_id=True) @@ -144,7 +138,7 @@ def test_recv_extended(self): self.assertTrue(now - 1 < msg.timestamp < now + 1) def test_recv_standard(self): - self.msg_in_cue = can.Message( + self.msg_in_cue = pycan.Message( arbitration_id=0x123, data=[100, 101], is_extended_id=False) @@ -154,7 +148,7 @@ def test_recv_standard(self): self.assertEqual(msg.dlc, 2) self.assertEqual(msg.is_extended_id, False) self.assertSequenceEqual(msg.data, [100, 101]) - + def test_available_configs(self): configs = canlib.KvaserBus._detect_available_configs() expected = [ @@ -166,7 +160,7 @@ def test_available_configs(self): def test_canfd_default_data_bitrate(self): canlib.canSetBusParams.reset_mock() canlib.canSetBusParamsFd.reset_mock() - can.Bus(channel=0, bustype='kvaser', fd=True) + pycan.Bus(channel=0, bustype='kvaser', fd=True) canlib.canSetBusParams.assert_called_once_with( 0, constants.canFD_BITRATE_500K_80P, 0, 0, 0, 0, 0) canlib.canSetBusParamsFd.assert_called_once_with( @@ -176,7 +170,7 @@ def test_canfd_nondefault_data_bitrate(self): canlib.canSetBusParams.reset_mock() canlib.canSetBusParamsFd.reset_mock() data_bitrate = 2000000 - can.Bus(channel=0, bustype='kvaser', fd=True, data_bitrate=data_bitrate) + pycan.Bus(channel=0, bustype='kvaser', fd=True, data_bitrate=data_bitrate) bitrate_constant = canlib.BITRATE_FD[data_bitrate] canlib.canSetBusParams.assert_called_once_with( 0, constants.canFD_BITRATE_500K_80P, 0, 0, 0, 0, 0) @@ -187,7 +181,7 @@ def test_canfd_custom_data_bitrate(self): canlib.canSetBusParams.reset_mock() canlib.canSetBusParamsFd.reset_mock() data_bitrate = 123456 - can.Bus(channel=0, bustype='kvaser', fd=True, data_bitrate=data_bitrate) + pycan.Bus(channel=0, bustype='kvaser', fd=True, data_bitrate=data_bitrate) canlib.canSetBusParams.assert_called_once_with( 0, constants.canFD_BITRATE_500K_80P, 0, 0, 0, 0, 0) canlib.canSetBusParamsFd.assert_called_once_with( diff --git a/test/test_load_file_config.py b/test/test_load_file_config.py index 52a45d734..1aad7de12 100644 --- a/test/test_load_file_config.py +++ b/test/test_load_file_config.py @@ -1,11 +1,10 @@ #!/usr/bin/env python -# coding: utf-8 import shutil import tempfile import unittest from tempfile import NamedTemporaryFile -import can +import pycan class LoadFileConfigTest(unittest.TestCase): @@ -37,21 +36,21 @@ def _gen_configration_file(self, sections): def test_config_file_with_default(self): tmp_config = self._gen_configration_file(['default']) - config = can.util.load_file_config(path=tmp_config) + config = pycan.util.load_file_config(path=tmp_config) self.assertEqual(config, self.configuration['default']) def test_config_file_with_default_and_section(self): tmp_config = self._gen_configration_file(['default', 'one']) - default = can.util.load_file_config(path=tmp_config) + default = pycan.util.load_file_config(path=tmp_config) self.assertEqual(default, self.configuration['default']) - one = can.util.load_file_config(path=tmp_config, section='one') + one = pycan.util.load_file_config(path=tmp_config, section='one') self.assertEqual(one, self.configuration['one']) def test_config_file_with_section_only(self): tmp_config = self._gen_configration_file(['one']) - config = can.util.load_file_config(path=tmp_config, section='one') + config = pycan.util.load_file_config(path=tmp_config, section='one') self.assertEqual(config, self.configuration['one']) def test_config_file_with_section_and_key_in_default(self): @@ -59,13 +58,13 @@ def test_config_file_with_section_and_key_in_default(self): expected.update(self.configuration['two']) tmp_config = self._gen_configration_file(['default', 'two']) - config = can.util.load_file_config(path=tmp_config, section='two') + config = pycan.util.load_file_config(path=tmp_config, section='two') self.assertEqual(config, expected) def test_config_file_with_section_missing_interface(self): expected = self.configuration['two'].copy() tmp_config = self._gen_configration_file(['two']) - config = can.util.load_file_config(path=tmp_config, section='two') + config = pycan.util.load_file_config(path=tmp_config, section='two') self.assertEqual(config, expected) def test_config_file_extra(self): @@ -73,7 +72,7 @@ def test_config_file_extra(self): expected.update(self.configuration['three']) tmp_config = self._gen_configration_file(['default', 'three']) - config = can.util.load_file_config(path=tmp_config, section='three') + config = pycan.util.load_file_config(path=tmp_config, section='three') self.assertEqual(config, expected) def test_config_file_with_non_existing_section(self): @@ -81,7 +80,7 @@ def test_config_file_with_non_existing_section(self): tmp_config = self._gen_configration_file([ 'default', 'one', 'two', 'three']) - config = can.util.load_file_config(path=tmp_config, section='zero') + config = pycan.util.load_file_config(path=tmp_config, section='zero') self.assertEqual(config, expected) diff --git a/test/test_message_class.py b/test/test_message_class.py index 85dbe8560..90810da27 100644 --- a/test/test_message_class.py +++ b/test/test_message_class.py @@ -1,15 +1,13 @@ #!/usr/bin/env python -# coding: utf-8 - import unittest import sys from math import isinf, isnan from copy import copy, deepcopy -from hypothesis import given, settings, reproduce_failure +from hypothesis import given, settings import hypothesis.strategies as st -from can import Message +from pycan import Message class TestMessageClass(unittest.TestCase): diff --git a/test/test_message_filtering.py b/test/test_message_filtering.py index 1419a4439..a16efb3b6 100644 --- a/test/test_message_filtering.py +++ b/test/test_message_filtering.py @@ -1,15 +1,13 @@ #!/usr/bin/env python -# coding: utf-8 - """ -This module tests :meth:`can.BusABC._matches_filters`. +This module tests :meth:`pycan.BusABC._matches_filters`. """ from __future__ import absolute_import import unittest -from can import Bus, Message +from pycan import Bus, Message from .data.example_data import TEST_ALL_MESSAGES diff --git a/test/test_message_sync.py b/test/test_message_sync.py index ec21a0660..28ccad19a 100644 --- a/test/test_message_sync.py +++ b/test/test_message_sync.py @@ -1,8 +1,6 @@ #!/usr/bin/env python -# coding: utf-8 - """ -This module tests :class:`can.MessageSync`. +This module tests :class:`pycan.MessageSync`. """ from __future__ import absolute_import @@ -14,7 +12,7 @@ import unittest import pytest -from can import MessageSync, Message +from pycan import MessageSync, Message from .config import IS_CI, IS_APPVEYOR, IS_TRAVIS, IS_OSX from .message_helper import ComparingMessagesTestCase diff --git a/test/test_scripts.py b/test/test_scripts.py index 74ae71489..af888b0da 100644 --- a/test/test_scripts.py +++ b/test/test_scripts.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 - """ This module tests that the scripts are all callable. """ @@ -72,7 +70,7 @@ class TestLoggerScript(CanScriptTest): def _commands(self): commands = [ - "python -m can.logger --help", + "python -m pycan.logger --help", "python scripts/can_logger.py --help" ] if IS_UNIX: @@ -80,7 +78,7 @@ def _commands(self): return commands def _import(self): - import can.logger as module + import pycan.logger as module return module @@ -88,7 +86,7 @@ class TestPlayerScript(CanScriptTest): def _commands(self): commands = [ - "python -m can.player --help", + "python -m pycan.player --help", "python scripts/can_player.py --help" ] if IS_UNIX: @@ -96,7 +94,7 @@ def _commands(self): return commands def _import(self): - import can.player as module + import pycan.player as module return module diff --git a/test/test_slcan.py b/test/test_slcan.py index 29869cb1c..ebe040ca1 100644 --- a/test/test_slcan.py +++ b/test/test_slcan.py @@ -1,13 +1,12 @@ #!/usr/bin/env python -# coding: utf-8 import unittest -import can +import pycan class slcanTestCase(unittest.TestCase): def setUp(self): - self.bus = can.Bus('loop://', bustype='slcan', sleep_after_open=0) + self.bus = pycan.Bus('loop://', bustype='slcan', sleep_after_open=0) self.serial = self.bus.serialPortOrig self.serial.read(self.serial.in_waiting) @@ -25,9 +24,9 @@ def test_recv_extended(self): self.assertSequenceEqual(msg.data, [0xAA, 0x55]) def test_send_extended(self): - msg = can.Message(arbitration_id=0x12ABCDEF, - is_extended_id=True, - data=[0xAA, 0x55]) + msg = pycan.Message(arbitration_id=0x12ABCDEF, + is_extended_id=True, + data=[0xAA, 0x55]) self.bus.send(msg) data = self.serial.read(self.serial.in_waiting) self.assertEqual(data, b'T12ABCDEF2AA55\r') @@ -43,9 +42,9 @@ def test_recv_standard(self): self.assertSequenceEqual(msg.data, [0x11, 0x22, 0x33]) def test_send_standard(self): - msg = can.Message(arbitration_id=0x456, - is_extended_id=False, - data=[0x11, 0x22, 0x33]) + msg = pycan.Message(arbitration_id=0x456, + is_extended_id=False, + data=[0x11, 0x22, 0x33]) self.bus.send(msg) data = self.serial.read(self.serial.in_waiting) self.assertEqual(data, b't4563112233\r') @@ -60,10 +59,10 @@ def test_recv_standard_remote(self): self.assertEqual(msg.dlc, 8) def test_send_standard_remote(self): - msg = can.Message(arbitration_id=0x123, - is_extended_id=False, - is_remote_frame=True, - dlc=8) + msg = pycan.Message(arbitration_id=0x123, + is_extended_id=False, + is_remote_frame=True, + dlc=8) self.bus.send(msg) data = self.serial.read(self.serial.in_waiting) self.assertEqual(data, b'r1238\r') @@ -78,10 +77,10 @@ def test_recv_extended_remote(self): self.assertEqual(msg.dlc, 6) def test_send_extended_remote(self): - msg = can.Message(arbitration_id=0x12ABCDEF, - is_extended_id=True, - is_remote_frame=True, - dlc=6) + msg = pycan.Message(arbitration_id=0x12ABCDEF, + is_extended_id=True, + is_remote_frame=True, + dlc=6) self.bus.send(msg) data = self.serial.read(self.serial.in_waiting) self.assertEqual(data, b'R12ABCDEF6\r') diff --git a/test/test_socketcan.py b/test/test_socketcan.py index f010a6372..7ce276dba 100644 --- a/test/test_socketcan.py +++ b/test/test_socketcan.py @@ -1,20 +1,16 @@ """ -Test functions in `can.interfaces.socketcan.socketcan`. +Test functions in `pycan.interfaces.socketcan.socketcan`. """ import unittest try: - from unittest.mock import Mock from unittest.mock import patch - from unittest.mock import call except ImportError: - from mock import Mock from mock import patch - from mock import call import ctypes -from can.interfaces.socketcan.socketcan import bcm_header_factory +from pycan.interfaces.socketcan.socketcan import bcm_header_factory class SocketCANTest(unittest.TestCase): @@ -25,7 +21,7 @@ def setUp(self): @patch("ctypes.sizeof") @patch("ctypes.alignment") def test_bcm_header_factory_32_bit_sizeof_long_4_alignof_long_4( - self, ctypes_sizeof, ctypes_alignment + self, ctypes_sizeof, ctypes_alignment ): """This tests a 32-bit platform (ex. Debian Stretch on i386), where: @@ -94,7 +90,7 @@ def side_effect_ctypes_alignment(value): @patch("ctypes.sizeof") @patch("ctypes.alignment") def test_bcm_header_factory_32_bit_sizeof_long_4_alignof_long_8( - self, ctypes_sizeof, ctypes_alignment + self, ctypes_sizeof, ctypes_alignment ): """This tests a 32-bit platform (ex. Raspbian Stretch on armv7l), where: @@ -163,7 +159,7 @@ def side_effect_ctypes_alignment(value): @patch("ctypes.sizeof") @patch("ctypes.alignment") def test_bcm_header_factory_64_bit_sizeof_long_4_alignof_long_4( - self, ctypes_sizeof, ctypes_alignment + self, ctypes_sizeof, ctypes_alignment ): """This tests a 64-bit platform (ex. Ubuntu 18.04 on x86_64), where: diff --git a/test/test_socketcan_helpers.py b/test/test_socketcan_helpers.py index f1462549a..b3477b421 100644 --- a/test/test_socketcan_helpers.py +++ b/test/test_socketcan_helpers.py @@ -1,15 +1,13 @@ #!/usr/bin/env python -# coding: utf-8 - """ -Tests helpers in `can.interfaces.socketcan.socketcan_common`. +Tests helpers in `pycan.interfaces.socketcan.socketcan_common`. """ from __future__ import absolute_import import unittest -from can.interfaces.socketcan.utils import \ +from pycan.interfaces.socketcan.utils import \ find_available_interfaces, error_code_to_str from .config import * diff --git a/test/test_systec.py b/test/test_systec.py index ce5dda4a7..494059759 100644 --- a/test/test_systec.py +++ b/test/test_systec.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 import unittest try: @@ -7,9 +6,9 @@ except ImportError: from mock import Mock, patch -import can -from can.interfaces.systec import ucan, ucanbus -from can.interfaces.systec.ucan import * +import pycan +from pycan.interfaces.systec import ucan, ucanbus +from pycan.interfaces.systec.ucan import * class SystecTest(unittest.TestCase): @@ -20,8 +19,8 @@ def compare_message(self, first, second, msg): raise self.failureException(msg) def setUp(self): - # add equality function for can.Message - self.addTypeEqualityFunc(can.Message, self.compare_message) + # add equality function for pycan.Message + self.addTypeEqualityFunc(pycan.Message, self.compare_message) ucan.UcanInitHwConnectControlEx = Mock() ucan.UcanInitHardwareEx = Mock() @@ -33,7 +32,7 @@ def setUp(self): ucan.UcanDeinitHardware = Mock() ucan.UcanWriteCanMsgEx = Mock() ucan.UcanResetCanEx = Mock() - self.bus = can.Bus(bustype='systec', channel=0, bitrate=125000) + self.bus = pycan.Bus(bustype='systec', channel=0, bitrate=125000) def test_bus_creation(self): self.assertIsInstance(self.bus, ucanbus.UcanBus) @@ -81,9 +80,9 @@ def test_filter_setup(self): ) self.assertEqual(ucan.UcanSetAcceptanceEx.call_args, expected_args) - @patch('can.interfaces.systec.ucan.UcanServer.write_can_msg') + @patch('pycan.interfaces.systec.ucan.UcanServer.write_can_msg') def test_send_extended(self, mock_write_can_msg): - msg = can.Message( + msg = pycan.Message( arbitration_id=0xc0ffee, data=[0, 25, 0, 1, 3, 1, 4], is_extended_id=True) @@ -94,9 +93,9 @@ def test_send_extended(self, mock_write_can_msg): ) self.assertEqual(mock_write_can_msg.call_args, expected_args) - @patch('can.interfaces.systec.ucan.UcanServer.write_can_msg') + @patch('pycan.interfaces.systec.ucan.UcanServer.write_can_msg') def test_send_standard(self, mock_write_can_msg): - msg = can.Message( + msg = pycan.Message( arbitration_id=0x321, data=[50, 51], is_extended_id=False) @@ -107,31 +106,31 @@ def test_send_standard(self, mock_write_can_msg): ) self.assertEqual(mock_write_can_msg.call_args, expected_args) - @patch('can.interfaces.systec.ucan.UcanServer.get_msg_pending') + @patch('pycan.interfaces.systec.ucan.UcanServer.get_msg_pending') def test_recv_no_message(self, mock_get_msg_pending): mock_get_msg_pending.return_value = 0 self.assertEqual(self.bus.recv(timeout=0.5), None) - @patch('can.interfaces.systec.ucan.UcanServer.get_msg_pending') - @patch('can.interfaces.systec.ucan.UcanServer.read_can_msg') + @patch('pycan.interfaces.systec.ucan.UcanServer.get_msg_pending') + @patch('pycan.interfaces.systec.ucan.UcanServer.read_can_msg') def test_recv_extended(self, mock_read_can_msg, mock_get_msg_pending): mock_read_can_msg.return_value = [CanMsg(0xc0ffef, MsgFrameFormat.MSG_FF_EXT, [1, 2, 3, 4, 5, 6, 7, 8])], 0 mock_get_msg_pending.return_value = 1 - msg = can.Message( + msg = pycan.Message( arbitration_id=0xc0ffef, data=[1, 2, 3, 4, 5, 6, 7, 8], is_extended_id=True) can_msg = self.bus.recv() self.assertEqual(can_msg, msg) - @patch('can.interfaces.systec.ucan.UcanServer.get_msg_pending') - @patch('can.interfaces.systec.ucan.UcanServer.read_can_msg') + @patch('pycan.interfaces.systec.ucan.UcanServer.get_msg_pending') + @patch('pycan.interfaces.systec.ucan.UcanServer.read_can_msg') def test_recv_standard(self, mock_read_can_msg, mock_get_msg_pending): mock_read_can_msg.return_value = [CanMsg(0x321, MsgFrameFormat.MSG_FF_STD, [50, 51])], 0 mock_get_msg_pending.return_value = 1 - msg = can.Message( + msg = pycan.Message( arbitration_id=0x321, data=[50, 51], is_extended_id=False) @@ -141,7 +140,7 @@ def test_recv_standard(self, mock_read_can_msg, mock_get_msg_pending): @staticmethod def test_bus_defaults(): ucan.UcanInitCanEx2.reset_mock() - bus = can.Bus(bustype='systec', channel=0) + bus = pycan.Bus(bustype='systec', channel=0) ucan.UcanInitCanEx2.assert_called_once_with( bus._ucan._handle, 0, @@ -160,7 +159,7 @@ def test_bus_defaults(): @staticmethod def test_bus_channel(): ucan.UcanInitCanEx2.reset_mock() - bus = can.Bus(bustype='systec', channel=1) + bus = pycan.Bus(bustype='systec', channel=1) ucan.UcanInitCanEx2.assert_called_once_with( bus._ucan._handle, 1, @@ -179,7 +178,7 @@ def test_bus_channel(): @staticmethod def test_bus_bitrate(): ucan.UcanInitCanEx2.reset_mock() - bus = can.Bus(bustype='systec', channel=0, bitrate=125000) + bus = pycan.Bus(bustype='systec', channel=0, bitrate=125000) ucan.UcanInitCanEx2.assert_called_once_with( bus._ucan._handle, 0, @@ -197,12 +196,12 @@ def test_bus_bitrate(): def test_bus_custom_bitrate(self): with self.assertRaises(ValueError): - can.Bus(bustype='systec', channel=0, bitrate=123456) + pycan.Bus(bustype='systec', channel=0, bitrate=123456) @staticmethod def test_receive_own_messages(): ucan.UcanInitCanEx2.reset_mock() - bus = can.Bus(bustype='systec', channel=0, receive_own_messages=True) + bus = pycan.Bus(bustype='systec', channel=0, receive_own_messages=True) ucan.UcanInitCanEx2.assert_called_once_with( bus._ucan._handle, 0, @@ -221,7 +220,7 @@ def test_receive_own_messages(): @staticmethod def test_bus_passive_state(): ucan.UcanInitCanEx2.reset_mock() - bus = can.Bus(bustype='systec', channel=0, state=can.BusState.PASSIVE) + bus = pycan.Bus(bustype='systec', channel=0, state=pycan.BusState.PASSIVE) ucan.UcanInitCanEx2.assert_called_once_with( bus._ucan._handle, 0, @@ -240,7 +239,7 @@ def test_bus_passive_state(): @staticmethod def test_rx_buffer_entries(): ucan.UcanInitCanEx2.reset_mock() - bus = can.Bus(bustype='systec', channel=0, rx_buffer_entries=1024) + bus = pycan.Bus(bustype='systec', channel=0, rx_buffer_entries=1024) ucan.UcanInitCanEx2.assert_called_once_with( bus._ucan._handle, 0, @@ -259,7 +258,7 @@ def test_rx_buffer_entries(): @staticmethod def test_tx_buffer_entries(): ucan.UcanInitCanEx2.reset_mock() - bus = can.Bus(bustype='systec', channel=0, tx_buffer_entries=1024) + bus = pycan.Bus(bustype='systec', channel=0, tx_buffer_entries=1024) ucan.UcanInitCanEx2.assert_called_once_with( bus._ucan._handle, 0, diff --git a/test/test_viewer.py b/test/test_viewer.py index c4b7aa45f..77447a6c2 100644 --- a/test/test_viewer.py +++ b/test/test_viewer.py @@ -26,7 +26,7 @@ from __future__ import absolute_import import argparse -import can +import pycan import curses import math import pytest @@ -37,8 +37,6 @@ import os import six -from typing import Dict, Tuple, Union - try: # noinspection PyCompatibility from unittest.mock import Mock, patch @@ -46,7 +44,7 @@ # noinspection PyPackageRequirements from mock import Mock, patch -from can.viewer import KEY_ESC, KEY_SPACE, CanViewer, parse_args +from pycan.viewer import KEY_ESC, KEY_SPACE, CanViewer, parse_args # noinspection SpellCheckingInspection,PyUnusedLocal @@ -115,7 +113,7 @@ def setUpClass(cls): def setUp(self): stdscr = StdscrDummy() config = {'interface': 'virtual', 'receive_own_messages': True} - bus = can.Bus(**config) + bus = pycan.Bus(**config) data_structs = None patch_curs_set = patch('curses.curs_set') @@ -154,31 +152,31 @@ def tearDown(self): def test_send(self): # CANopen EMCY data = [1, 2, 3, 4, 5, 6, 7] # Wrong length - msg = can.Message(arbitration_id=0x080 + 1, data=data, is_extended_id=False) + msg = pycan.Message(arbitration_id=0x080 + 1, data=data, is_extended_id=False) self.can_viewer.bus.send(msg) data = [1, 2, 3, 4, 5, 6, 7, 8] - msg = can.Message(arbitration_id=0x080 + 1, data=data, is_extended_id=False) + msg = pycan.Message(arbitration_id=0x080 + 1, data=data, is_extended_id=False) self.can_viewer.bus.send(msg) # CANopen HEARTBEAT data = [0x05] # Operational - msg = can.Message(arbitration_id=0x700 + 0x7F, data=data, is_extended_id=False) + msg = pycan.Message(arbitration_id=0x700 + 0x7F, data=data, is_extended_id=False) self.can_viewer.bus.send(msg) # Send non-CANopen message data = [1, 2, 3, 4, 5, 6, 7, 8] - msg = can.Message(arbitration_id=0x101, data=data, is_extended_id=False) + msg = pycan.Message(arbitration_id=0x101, data=data, is_extended_id=False) self.can_viewer.bus.send(msg) # Send the same command, but with another data length data = [1, 2, 3, 4, 5, 6] - msg = can.Message(arbitration_id=0x101, data=data, is_extended_id=False) + msg = pycan.Message(arbitration_id=0x101, data=data, is_extended_id=False) self.can_viewer.bus.send(msg) # Message with extended id data = [1, 2, 3, 4, 5, 6, 7, 8] - msg = can.Message(arbitration_id=0x123456, data=data, is_extended_id=True) + msg = pycan.Message(arbitration_id=0x123456, data=data, is_extended_id=True) self.can_viewer.bus.send(msg) # self.assertTupleEqual(self.can_viewer.parse_canopen_message(msg), (None, None)) @@ -187,7 +185,7 @@ def test_send(self): self.can_viewer.bus.send(msg) # Send error message - msg = can.Message(is_error_frame=True) + msg = pycan.Message(is_error_frame=True) self.can_viewer.bus.send(msg) def test_receive(self): diff --git a/test/zero_dlc_test.py b/test/zero_dlc_test.py index 77d55d678..4117dd4a4 100644 --- a/test/zero_dlc_test.py +++ b/test/zero_dlc_test.py @@ -1,14 +1,9 @@ #!/usr/bin/env python -# coding: utf-8 -""" -""" - -from time import sleep import unittest import logging -import can +import pycan logging.getLogger(__file__).setLevel(logging.DEBUG) @@ -16,10 +11,10 @@ class ZeroDLCTest(unittest.TestCase): def test_recv_non_zero_dlc(self): - bus_send = can.interface.Bus(bustype='virtual') - bus_recv = can.interface.Bus(bustype='virtual') + bus_send = pycan.interface.Bus(bustype='virtual') + bus_recv = pycan.interface.Bus(bustype='virtual') data = [0, 1, 2, 3, 4, 5, 6, 7] - msg_send = can.Message(is_extended_id=False, arbitration_id=0x100, data=data) + msg_send = pycan.Message(is_extended_id=False, arbitration_id=0x100, data=data) bus_send.send(msg_send) msg_recv = bus_recv.recv() @@ -28,7 +23,7 @@ def test_recv_non_zero_dlc(self): self.assertTrue(msg_recv) def test_recv_none(self): - bus_recv = can.interface.Bus(bustype='virtual') + bus_recv = pycan.interface.Bus(bustype='virtual') msg_recv = bus_recv.recv(timeout=0) @@ -36,9 +31,9 @@ def test_recv_none(self): self.assertFalse(msg_recv) def test_recv_zero_dlc(self): - bus_send = can.interface.Bus(bustype='virtual') - bus_recv = can.interface.Bus(bustype='virtual') - msg_send = can.Message(is_extended_id=False, arbitration_id=0x100, data=[]) + bus_send = pycan.interface.Bus(bustype='virtual') + bus_recv = pycan.interface.Bus(bustype='virtual') + msg_send = pycan.Message(is_extended_id=False, arbitration_id=0x100, data=[]) bus_send.send(msg_send) msg_recv = bus_recv.recv()