Skip to content

Frame.pdu_* properties should be considered for a tuple#245

Merged
jashnani merged 1 commit intoni:masterfrom
chlc3d:pdu
Apr 23, 2018
Merged

Frame.pdu_* properties should be considered for a tuple#245
jashnani merged 1 commit intoni:masterfrom
chlc3d:pdu

Conversation

@chlc3d
Copy link

@chlc3d chlc3d commented Mar 28, 2018

  • This contribution adheres to CONTRIBUTING.md.
  • New tests have been created for any new features or regression tests for bugfixes.
  • tox successfully runs, including unit tests and style checks (see CONTRIBUTING.md).

What does this Pull Request accomplish?

This PR implements issue #53 by removing the pdu_* properties with a single pdu properties. The old interface required parallel lists, this implementation uses a single list of namedtuples.

Why should this Pull Request be merged?

#53

What testing has been done?

I tested this with my CAN device by creating a PDU that met the requirements of PDUs Required?. I verified I could configure and take measurements without any warnings. If I didn't conform to PDUs required, I got either a warning or error depending on the case.

@chlc3d
Copy link
Author

chlc3d commented Mar 28, 2018

Since CAN/LIN currently only supports a subset of PDU features (one PDU per frame, a start bit of 0, and an update bit of -1), an alternative implementation would be to only have a pdu_ref function which takes a PDU item. We could assume the start bit of 0 and update bit of -1. However, this would be a departure from the XNET C interface, and we'd need to switch back to something like namedtuples if CAN/LIN ever supported more types of PDUs.

@coveralls
Copy link

coveralls commented Mar 28, 2018

Coverage Status

Coverage increased (+9.5%) to 68.172% when pulling f52ce6c on trstamper:pdu into 4004cd3 on ni:master.

@coveralls
Copy link

coveralls commented Mar 28, 2018

Coverage Status

Coverage increased (+3.2%) to 67.766% when pulling 043b296 on trstamper:pdu into 29f23de on ni:master.

Copy link
Contributor

@epage epage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to clean up your commits

_props.set_frame_pdu_update_bits(self._handle, value)
def pdus(self):
handles = [_pdu.Pdu(handle)
for handle in _props.get_frame_pdu_refs(self._handle)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While acceptable by flake8, I personally discourage this style because it leads to unnecessarily deep nesting, and simple refactors (like renaming handles) cause other lines to change (updating indentation)

Alternatively you can do

handles = [
    _pdu.Pdu(handle)
    for handle in _props.get_frame_pdu_refs(self._handle)]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I was sticking with what autopep8 did, I don't have any horse in this fight.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to get an auto formatter setup. I hear good things about yapf. A new one recently came out but I can't find it.

_props.get_frame_pdu_update_bits(self._handle)))
for pdu in [types.PduFrameReference(ref, start_bit, update_bit)
for (ref, start_bit, update_bit) in pdu_tuples]:
yield pdu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why create a list, then iterate over it, yielding the results? That feels overly complicated.

Instead you could just

return (
    types.PduFrameReference(ref, start_bit, update_bit)
    for (ref, start_bit, update_bit) in pdu_tuples
)

or

for (ref, start_bit, update_bit) in pdu_tuples]:
    yield types.PduFrameReference(ref, start_bit, update_bit)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the last one looks cleaner to me too.

@pdu_update_bits.setter
def pdu_update_bits(self, value):
_props.set_frame_pdu_update_bits(self._handle, value)
def pdus(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't Damon creating documentation for these? Are you two's commits going to step on each others toes?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. I'll coordinate with damon on how to order these.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trstamper #237 has been pulled, so whenever you're ready, you'll want to pull down master and merge it with your changes. There will be conflicts to resolve.

""":any:`nixnet.database._dbc_attributes.DbcAttributeCollection`: Access the frame's DBC attributes."""
if self._dbc_attributes is None:
self._dbc_attributes = _dbc_attributes.DbcAttributeCollection(self._handle)
self._dbc_attributes = _dbc_attributes.DbcAttributeCollection(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commit including an unrelated change?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured I would fix the pep8 violation (over the max line length) while I was in the file. I just looked at tox.ini and saw it's set to 120 characters max, so I'll change this back.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our official guideline is to aim for below 80 characters but only enforce below 120.

... we still need to get that guideline published publicly.

@jashnani jashnani self-requested a review March 29, 2018 14:03

from nixnet.database import _collection
from nixnet.database import _dbc_attributes
from nixnet.database import _pdu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import will need to be moved down into the methods that use PDUs, else we will get circular imports when combined with #237.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed this circular important but ran into another one trying to import nixnet.database._pdu in types.py because the PduProperties class has a Pdu object as one of its values and I wanted to reference it in the documentation. Why are we importing stuff for sphinx in every file instead of adding our whole library to the path in sphinx's conf.py?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we importing stuff for sphinx in every file instead of adding our whole library to the path in sphinx's conf.py?

I don't follow. What imports are you talking about?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damon and I talked about this offline and I found out I could avoid importing a class for sphinx to see it by not using the fully qualified name.

yield pdu

@pdus.setter
def pdus(self, pdus):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#237 changes all ref methods from object_ref(s) to object(s) and returns the object instead of a ref. Thus, #237 has changed pdu_refs to pdus. Given that pattern applies to all the other database objects, calling your tuple pdus implies the method should return an iterable of PDU objects. Should we perhaps find another name then? Something like pdu_properties or pdu_info?

Also, you should return a PDU object instead of a handle as well. Just do something like Pdu(p.ref._handle)

#237 adds annotations and docstrings for all methods. Moving forward, these will be required for all methods, so you should add these things for your changes as well.

nixnet/types.py Outdated

PduFrameReference_ = collections.namedtuple(
'PDU_',
['ref', 'start_bit', 'update_bit'])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per my previous comment, this could probably use some renaming since we are moving away from references to objects. My suggestions:

PduFrameReference_ -> PduProperties_
PDU_ -> PduProperties_
ref -> pdu

Copy link
Contributor

@d-bohls d-bohls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Just a few requests.

# type: () -> typing.Iterable[typing.Any]
def pdu_properties(self):
# type: () -> typing.Iterable[types.PduProperties]
"""list of :any:`Pdu`: Get or set a list that maps existing PDUs to a frame.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list of :any:`PduProperties`

""":any:`DbcAttributeCollection`: Access the frame's DBC attributes."""
if self._dbc_attributes is None:
self._dbc_attributes = _dbc_attributes.DbcAttributeCollection(self._handle)
self._dbc_attributes = _dbc_attributes.DbcAttributeCollection(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to make this change.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah whoops, must have missed that this got redone in the merge

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:`nixnet.types.PduProperties.ref`: Defines the sequence of values for the other two properties.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with other db docs

:any:`PduProperties.pdu`
:any:`PduProperties.start_bit`
:any:`PduProperties.update_bit`

Rename ref to pdu, per my comment later in the review.

nixnet/types.py Outdated


PduProperties_ = collections.namedtuple(
'PDU_',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the typename of the named tuple should be something like PDU_PROPERTIES_ instead of PDU_. Not sure if this naming really matters.

We use handle/ref to talk about an integer that the driver uses for the object. We are dealing with an actual Pdu object here; not a ref. Change to:

['pdu', 'start_bit', 'update_bit'])

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't true anymore. Maybe something like:

Mapping PDUs to a frame requires modifying this list of :any:`PduProperties`,
each of which requires the following three properties:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeahthat makes more sense. I was referring to the underlying driver calls here but that's not necessary at this spot.

def pdu_update_bits(self, value):
# type: (typing.List[int]) -> None
_props.set_frame_pdu_update_bits(self._handle, value)
handles = [_pdu.Pdu(handle) for handle in _props.get_frame_pdu_refs(self._handle)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pdus = [_pdu.Pdu(handle) for handle in ...

The handles have been converted to pdu objects.

@chlc3d
Copy link
Author

chlc3d commented Apr 20, 2018

Updated review to address comments.

Copy link

@jashnani jashnani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. We should add unit tests for pdu_properties. This could be done part of #238 also. I'll leave it up to you, if you want to do it in this PR or coordinate with @d-bohls and do it in #238

  2. I think you're introducing breaking changes. Its helpful if we call out API breakages in our commit messages. Also, it'll make it easier for us to find them (with a handy tool) when creating the release notes. Ideally, you include what someone needs to do to correct their code.

“””
Breaking Changes should start with the word BREAKING CHANGE: with a space or two newlines. The rest of the commit message is then used for this.
“””
From https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-changelog-angular/convention.md

Example: 66e741f

BREAKING CHANGE: 'pdus', 'pdu_start_bits', and 'pdu_update_bits'
properties have been removed from the Frame class. Use 'pdu_properties'
instead.
@chlc3d
Copy link
Author

chlc3d commented Apr 20, 2018

Updated description to add BREKAING CHANGE tag

@jashnani
Copy link

For future reference, you can add Fixes #issue in the commit description and it will automatically close the issue when the commit is pulled into mainline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants