From 043b296ca8e11d6d60757abcfef71e190603d1fe Mon Sep 17 00:00:00 2001 From: Tim Stamper Date: Tue, 27 Mar 2018 10:39:43 -0500 Subject: [PATCH] fix(API): 'Frame.pdu_*' properties should be considered for a tuple BREAKING CHANGE: 'pdus', 'pdu_start_bits', and 'pdu_update_bits' properties have been removed from the Frame class. Use 'pdu_properties' instead. --- nixnet/database/_frame.py | 108 +++++++++----------------------------- nixnet/database/_pdu.py | 4 +- nixnet/types.py | 21 +++++++- 3 files changed, 47 insertions(+), 86 deletions(-) diff --git a/nixnet/database/_frame.py b/nixnet/database/_frame.py index 973e699c..647d793a 100644 --- a/nixnet/database/_frame.py +++ b/nixnet/database/_frame.py @@ -2,12 +2,14 @@ from __future__ import division from __future__ import print_function +import operator import typing # NOQA: F401 from nixnet import _cconsts from nixnet import _errors from nixnet import _props from nixnet import constants +from nixnet import types from nixnet.database import _cluster from nixnet.database import _collection @@ -553,27 +555,21 @@ def mux_subframes(self): return self._mux_subframes @property - def pdus(self): - # actually returns typing.Iterable[_pdu.Pdu], but avoiding a circular import - # type: () -> typing.Iterable[typing.Any] - """list of :any:`Pdu`: Get or set a list that maps existing PDUs to a frame. + def pdu_properties(self): + # type: () -> typing.Iterable[types.PduProperties] + """list of :any:`PduProperties`: Get or set a list that maps existing PDUs to a frame. A mapped PDU is transmitted inside the frame payload when the frame is transmitted. You can map one or more PDUs to a frame and one PDU to multiple frames. - Mapping PDUs to a frame requires setting three frame properties. - All three properties are lists of values: + Mapping PDUs to a frame requires setting pdu_properties with a list of PduProperties tuples. + Each tuple contains the following properties: - * :any:`Frame.pdus`: Set this property first to define - the sequence of values for the other two properties. - * :any:`Frame.pdu_start_bits`: Defines the start bit of the PDU inside the frame. - * :any:`Frame.pdu_update_bits`: Defines the update bit for the PDU inside the frame. + * :any:`PduProperties.pdu`: Defines the sequence of values for the other two properties. + * :any:`PduProperties.start_bit`: Defines the start bit of the PDU inside the frame. + * :any:`PduProperties.update_bit`: Defines the update bit for the PDU inside the frame. If the update bit is not used, set the value to ``-1``. - Values on the same list position are corresponding. - For example, ``pdus[0]``, ``pdu_start_bits[0]``, - and ``pdu_update_bits[0]`` define the mapping for the first PDU in the frame. - Databases imported from FIBEX prior to version 3.0, from DBC, NCD, or LDF files have a strong one-to-one relationship between frames and PDUs. Every frame has exactly one PDU mapped, and every PDU is mapped to exactly one frame. @@ -588,74 +584,22 @@ def pdus(self): you can avoid using PDUs in the database API and create signals and subframes directly on a frame. """ - from nixnet.database import _pdu - for handle in _props.get_frame_pdu_refs(self._handle): - yield _pdu.Pdu(handle) - - @pdus.setter - def pdus(self, value): - # value is actually typing.Iterable[_pdu.Pdu], but avoiding a circular import - # type: (typing.Iterable[typing.Any]) -> None - handle_list = [pdu._handle for pdu in value] - _props.set_frame_pdu_refs(self._handle, handle_list) - - @property - def pdu_start_bits(self): - # type: () -> typing.Iterable[int] - """list of int: This property defines the start bits of PDUs mapped to a frame. - - A mapped PDU is transmitted inside the frame payload when the frame is transmitted. - You can map one or more PDUs to a frame and one PDU to multiple frames. - - Mapping PDUs to a frame requires setting of three frame properties. - All three properties are lists of values: - - * :any:`Frame.pdus`: Set this property first to define - the sequence of values for the other two properties. - * :any:`Frame.pdu_start_bits`: Defines the start bit of the PDU inside the frame. - * :any:`Frame.pdu_update_bits`: Defines the update bit for the PDU inside the frame. - If the update bit is not used, set the value to ``-1``. - - Values on the same list position are corresponding. - For example, ``pdus[0]``, ``pdu_start_bits[0]``, - and ``pdu_update_bits[0]`` define the mapping for the first PDU in the frame. - """ - return _props.get_frame_pdu_start_bits(self._handle) - - @pdu_start_bits.setter - def pdu_start_bits(self, value): - # type: (typing.List[int]) -> None - _props.set_frame_pdu_start_bits(self._handle, value) - - @property - def pdu_update_bits(self): - # type: () -> typing.Iterable[int] - """list of int: Get or set the update bits of PDUs mapped to a frame. - - If the update bit is not used for the PDU, set the value to -1. - The receiver uses the update bit to determine whether the frame sender has updated data in a particular PDU. - Update bits allow for the decoupling of a signal update from a frame occurrence. - Update bits is an optional PDU property. - - Mapping PDUs to a frame requires setting three frame properties. - All three properties are lists of values: - - * :any:`Frame.pdus`: Set this property first to define - the sequence of values for the other two properties. - * :any:`Frame.pdu_start_bits`: Defines the start bit of the PDU inside the frame. - * :any:`Frame.pdu_update_bits`: Defines the update bit for the PDU inside the frame. - If the update bit is not used, set the value to ``-1``. - - Values on the same list position are corresponding. - For example, ``pdus[0]``, ``pdu_start_bits[0]``, - and ``pdu_update_bits[0]`` define the mapping for the first PDU in the frame. - """ - return _props.get_frame_pdu_update_bits(self._handle) - - @pdu_update_bits.setter - def pdu_update_bits(self, value): - # type: (typing.List[int]) -> None - _props.set_frame_pdu_update_bits(self._handle, value) + handles = _props.get_frame_pdu_refs(self._handle) + pdu_tuples = zip(*(handles, + _props.get_frame_pdu_start_bits(self._handle), + _props.get_frame_pdu_update_bits(self._handle))) + for (ref, start_bit, update_bit) in pdu_tuples: + yield types.PduProperties(ref, start_bit, update_bit) + + @pdu_properties.setter + def pdu_properties(self, pdus): + # type: (typing.Iterable[types.PduProperties]) -> None + _props.set_frame_pdu_refs(self._handle, + list(map(lambda p: p.pdu._handle, pdus))) + _props.set_frame_pdu_start_bits(self._handle, + list(map(operator.attrgetter('start_bit'), pdus))) + _props.set_frame_pdu_update_bits(self._handle, + list(map(operator.attrgetter('update_bit'), pdus))) @property def variable_payload(self): diff --git a/nixnet/database/_pdu.py b/nixnet/database/_pdu.py index c0c17c2b..38c3bf2c 100644 --- a/nixnet/database/_pdu.py +++ b/nixnet/database/_pdu.py @@ -105,9 +105,7 @@ def frms(self): A PDU is transmitted within the frames to which it is mapped. To map a PDU to a frame, - use the :any:`Frame.pdus`, - :any:`Frame.pdu_start_bits`, - and :any:`Frame.pdu_update_bits` properties. + use the :any:`Frame.pdu_properties` property. You can map one PDU to multiple frames. """ for handle in _props.get_pdu_frm_refs(self._handle): diff --git a/nixnet/types.py b/nixnet/types.py index efd5ca90..f19fc3b3 100644 --- a/nixnet/types.py +++ b/nixnet/types.py @@ -28,7 +28,8 @@ 'DelayFrame', 'LogTriggerFrame', 'StartTriggerFrame', - 'XnetFrame'] + 'XnetFrame', + 'PduProperties'] DriverVersion_ = collections.namedtuple( @@ -153,6 +154,24 @@ class LinComm(LinComm_): pass +PduProperties_ = collections.namedtuple( + 'PDU_PROPERTIES_', + ['pdu', 'start_bit', 'update_bit']) + + +class PduProperties(PduProperties_): + """Properties that map a PDU onto a frame. + + Mapping PDUs to a frame requires setting three frame properties that are combined into this tuple. + + Attributes: + pdu (:any:`Pdu`): Defines the sequence of values for the other two properties. + start_bit (int): Defines the start bit of the PDU inside the frame. + update_bit (int): Defines the update bit for the PDU inside the frame. + If the update bit is not used, set the value to ``-1``. + """ + + class CanIdentifier(object): """CAN frame arbitration identifier.