Skip to content

Commit

Permalink
Skip the "highest subindex" entry when iterating over SdoRecord (#538)
Browse files Browse the repository at this point in the history
The count entry itself is not part of the data (according to CiA 301),
thus should not be yielded from an iterator.  That matches the
behavior of SdoArray, which also yields only the array contents.

Note that the basis of returned record sub-objects is still the subset
described by the OD, which might be smaller than the actual entries
accessible on the node, and less than indicated by the record's
subindex 0.  Thus the count (and iteration set) is reduced by one
element only if the subindex 0 was actually part of this subset.

* No need to expect test failure anymore.
  • Loading branch information
acolomb committed Aug 17, 2024
1 parent 273bab1 commit 6bc90a8
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 11 deletions.
7 changes: 5 additions & 2 deletions canopen/sdo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ def __getitem__(self, subindex: Union[int, str]) -> SdoVariable:
return SdoVariable(self.sdo_node, self.od[subindex])

def __iter__(self) -> Iterator[int]:
return iter(self.od)
# Skip the "highest subindex" entry, which is not part of the data
return filter(None, iter(self.od))

def __len__(self) -> int:
return len(self.od)
# Skip the "highest subindex" entry, which is not part of the data
return len(self.od) - int(0 in self.od)

def __contains__(self, subindex: Union[int, str]) -> bool:
return subindex in self.od
Expand All @@ -127,6 +129,7 @@ def __getitem__(self, subindex: Union[int, str]) -> SdoVariable:
return SdoVariable(self.sdo_node, self.od[subindex])

def __iter__(self) -> Iterator[int]:
# Skip the "highest subindex" entry, which is not part of the data
return iter(range(1, len(self) + 1))

def __len__(self) -> int:
Expand Down
23 changes: 15 additions & 8 deletions doc/sdo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ API

.. describe:: iter(record)

Return an iterator over the subindexes from the record.
Return an iterator over the subindexes from the record. Only those with
a matching object dictionary entry are considered. The "highest
subindex" entry is officially not part of the data and thus skipped in
the yielded values.

.. describe:: subindex in record

Expand All @@ -198,7 +201,9 @@ API

.. describe:: len(record)

Return the number of subindexes in the record.
Return the number of subindexes in the record, not counting the "highest
subindex" entry itself. Only those with a matching object dictionary
entry are considered.

.. method:: values()

Expand All @@ -220,25 +225,27 @@ API
.. describe:: iter(array)

Return an iterator over the subindexes from the array.
This will make a SDO read operation on subindex 0 in order to get the
actual length of the array.
This will make an SDO read operation on subindex 0 in order to get the
actual length of the array. This "highest subindex" entry is officially
not part of the data and thus skipped in the yielded values.

.. describe:: subindex in array

Return ``True`` if the subindex (as int) or name (as string) exists in
the array.
This will make a SDO read operation on subindex 0 in order to get the
This will make an SDO read operation on subindex 0 in order to get the
actual length of the array.

.. describe:: len(array)

Return the length of the array.
This will make a SDO read operation on subindex 0.
Return the length of the array, not counting the "highest subindex" entry
itself.
This will make an SDO read operation on subindex 0.

.. method:: values()

Return a list of :class:`canopen.sdo.SdoVariable` in the array.
This will make a SDO read operation on subindex 0 in order to get the
This will make an SDO read operation on subindex 0 in order to get the
actual length of the array.


Expand Down
1 change: 0 additions & 1 deletion test/test_sdo.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def setUp(self):
node = canopen.LocalNode(1, SAMPLE_EDS)
self.sdo_node = node.sdo

@unittest.expectedFailure
def test_record_iter_length(self):
"""Assume the "highest subindex supported" entry is not counted.
Expand Down

0 comments on commit 6bc90a8

Please sign in to comment.