From 6bc90a817f049b52fbeb1201c699e90ca36a6136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Sat, 17 Aug 2024 23:05:14 +0200 Subject: [PATCH] Skip the "highest subindex" entry when iterating over SdoRecord (#538) 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. --- canopen/sdo/base.py | 7 +++++-- doc/sdo.rst | 23 +++++++++++++++-------- test/test_sdo.py | 1 - 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/canopen/sdo/base.py b/canopen/sdo/base.py index 0bb068b4..81d5e710 100644 --- a/canopen/sdo/base.py +++ b/canopen/sdo/base.py @@ -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 @@ -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: diff --git a/doc/sdo.rst b/doc/sdo.rst index a1436572..29314028 100644 --- a/doc/sdo.rst +++ b/doc/sdo.rst @@ -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 @@ -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() @@ -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. diff --git a/test/test_sdo.py b/test/test_sdo.py index 212fc7f5..993d4acc 100644 --- a/test/test_sdo.py +++ b/test/test_sdo.py @@ -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.