Skip to content

Commit 6bc90a8

Browse files
authored
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.
1 parent 273bab1 commit 6bc90a8

File tree

3 files changed

+20
-11
lines changed

3 files changed

+20
-11
lines changed

Diff for: canopen/sdo/base.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,12 @@ def __getitem__(self, subindex: Union[int, str]) -> SdoVariable:
105105
return SdoVariable(self.sdo_node, self.od[subindex])
106106

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

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

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

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

132135
def __len__(self) -> int:

Diff for: doc/sdo.rst

+15-8
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ API
189189

190190
.. describe:: iter(record)
191191

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

194197
.. describe:: subindex in record
195198

@@ -198,7 +201,9 @@ API
198201

199202
.. describe:: len(record)
200203

201-
Return the number of subindexes in the record.
204+
Return the number of subindexes in the record, not counting the "highest
205+
subindex" entry itself. Only those with a matching object dictionary
206+
entry are considered.
202207

203208
.. method:: values()
204209

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

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

226232
.. describe:: subindex in array
227233

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

233239
.. describe:: len(array)
234240

235-
Return the length of the array.
236-
This will make a SDO read operation on subindex 0.
241+
Return the length of the array, not counting the "highest subindex" entry
242+
itself.
243+
This will make an SDO read operation on subindex 0.
237244

238245
.. method:: values()
239246

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

244251

Diff for: test/test_sdo.py

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ def setUp(self):
2020
node = canopen.LocalNode(1, SAMPLE_EDS)
2121
self.sdo_node = node.sdo
2222

23-
@unittest.expectedFailure
2423
def test_record_iter_length(self):
2524
"""Assume the "highest subindex supported" entry is not counted.
2625

0 commit comments

Comments
 (0)