Restore list semantics in CaselessList

TL;DR

  • tango.utils.CaselessList.index() now raises ValueError when the item is absent, instead of IndexError, and honours the exclusive upper bound.
  • entries += [...] no longer sets the name to None.
  • [...] + entries no longer returns its operands swapped.

Reported in #789.

Key Facts

  • All three are departures from the list interface the class reimplements, and all three are stated correctly in the class's own docstrings. None had a test.
  • index() had one off-by-one with two symptoms. It started the scan at minindex - 1 and incremented before indexing, so the final iteration read self[maxindex]. With the default bound that is one past the end, which is why a missing item raised IndexError and the trailing raise ValueError was unreachable. With an explicit bound it matched the element at maxindex, although s.index(x, i, j) excludes it.
  • __iadd__ returning None means the bug destroys data rather than just misbehaving: the list is correctly appended to in place, then the name is rebound to None and the result thrown away.
  • No in-tree caller is affected. CaselessList is used inside CaselessDict.keys(), which does not touch any of these three methods. The class is exported from tango.utils but is not re-exported from tango and is not in the published API docs.

Caveats

  • The first commit adds the tests and fails on its own; the second makes them pass.
  • Two tests carry # noqa: RUF005. The concatenation operator is the thing under test, so it must not be rewritten as unpacking.
  • Builds on !1073 (merged) and targets its branch. Retarget to develop once that merges.

🤖 Generated with Claude Code

Merge request reports

Loading
Loading