fix: Bits.__getitem__/__setitem__ ignore msb_last (rtl) as documented

list() always used MSB-first bit order regardless of the msb_last
constructor flag, so indexing/slicing on an instance built with
msb_last=True silently behaved identically to the default -- the
documented "swap bit order for indexing and slicing" never happened.
__setitem__ needed a matching fix: since __setvalue() always expects
a MSB-first list, a mutated LSB-first list from list() has to be
reversed back before being passed in.

Found while wiring bits.Bits into progpib's GPIB status-byte handling
(IEEE-488.2 bit numbering is LSB-first, e.g. RQS = bit 6).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 18:27:58 -05:00
parent 49ef87f8c9
commit 741fc41f07

View File

@@ -605,6 +605,9 @@ class Bits:
l = self.list()
# str->int->bool->int : accept bool, str, int, return either "0" or "1"
l[index] = Bit(value)
if self.__r_to_l:
# list() returned LSB-first order; __setvalue expects MSB-first
l = l[::-1]
self.__setvalue(l)
def __get__(self, instance, owner):
@@ -911,10 +914,15 @@ class Bits:
"""
self.__r_to_l = bool(msb_last)
def list(self, pad=True, reverse=False):
def list(self, pad=True, reverse=None):
"""
Return self as list(of Bit)
reverse: True/False to force bit order for this call; None (the
default) uses self.rtl, so indexing/slicing on an instance
constructed with msb_last=True is LSB-first as documented.
"""
if reverse is None:
reverse = self.__r_to_l
ret = []
bits = self.bin(pad=pad, reverse=reverse)
for b in bits: