update Bits; tests passing
This commit is contained in:
parent
37782f4b8b
commit
e8772e9931
1
Makefile
1
Makefile
|
@ -2,6 +2,7 @@ init:
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
python -m unittest -v tests/test_bit.py
|
||||||
python -m unittest -v tests/test_bits.py
|
python -m unittest -v tests/test_bits.py
|
||||||
|
|
||||||
.PHONY: init test
|
.PHONY: init test
|
||||||
|
|
181
bits/main.py
181
bits/main.py
|
@ -72,8 +72,9 @@ class Bits:
|
||||||
Provide bit operation helpers.
|
Provide bit operation helpers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, var=0):
|
def __init__(self, var=0, msb_last=False):
|
||||||
self.__value = 0
|
self.__value = 0
|
||||||
|
self.__r_to_l = bool(msb_last)
|
||||||
self.__setvalue(var)
|
self.__setvalue(var)
|
||||||
|
|
||||||
def __bytes__(self):
|
def __bytes__(self):
|
||||||
|
@ -86,9 +87,7 @@ class Bits:
|
||||||
return self.__value
|
return self.__value
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
ret = f'{self.__class__.__module__}.{self.__class__.__name__}'
|
return f'{self.__class__.__name__}({self.__value!r})'
|
||||||
ret += f'({bytes(self)})'
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.bin()
|
return self.bin()
|
||||||
|
@ -127,15 +126,165 @@ class Bits:
|
||||||
# we'll take the easy way for now
|
# we'll take the easy way for now
|
||||||
l = self.list()
|
l = self.list()
|
||||||
# str->int->bool->int : accept bool, str, int, return either "0" or "1"
|
# str->int->bool->int : accept bool, str, int, return either "0" or "1"
|
||||||
l[index] = bool(int(value))
|
l[index] = Bit(value)
|
||||||
self.__setvalue(l)
|
self.__setvalue(l)
|
||||||
|
|
||||||
def __get__(self, instance, owner):
|
def __get__(self, instance, owner):
|
||||||
return self.bin()
|
return self.bin()
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
return Bits(int(self) + int(Bits(other)))
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return Bits(int(self) - int(Bits(other)))
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
return Bits(int(self) * int(Bits(other)))
|
||||||
|
|
||||||
|
def __matmul__(self, other):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __floordiv__(self, other):
|
||||||
|
return Bits(int(self) // int(Bits(other)))
|
||||||
|
|
||||||
|
def __mod__(self, other):
|
||||||
|
return Bits(int(self) % int(Bits(other)))
|
||||||
|
|
||||||
|
def __divmod__(self, other):
|
||||||
|
return (self // Bits(other), self % Bits(other))
|
||||||
|
|
||||||
|
def __pow__(self, other, mod=None):
|
||||||
|
ret = Bits(0)
|
||||||
|
if mod is None:
|
||||||
|
ret = Bits(int(self) ** int(Bits(other)))
|
||||||
|
else:
|
||||||
|
ret = Bits(int(self) ** int(Bits(other)) % int(Bits(mod)))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __lshift__(self, other):
|
||||||
|
return Bits(int(self) << int(Bits(other)))
|
||||||
|
|
||||||
|
def __rshift__(self, other):
|
||||||
|
return Bits(int(self) >> int(Bits(other)))
|
||||||
|
|
||||||
|
def __and__(self, other):
|
||||||
|
return Bits(int(self) & int(Bits(other)))
|
||||||
|
|
||||||
|
def __xor__(self, other):
|
||||||
|
return Bits(int(self) ^ int(Bits(other)))
|
||||||
|
|
||||||
|
def __or__(self, other):
|
||||||
|
return Bits(int(self) | int(Bits(other)))
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
return Bits(other) + self
|
||||||
|
|
||||||
|
def __rsub__(self, other):
|
||||||
|
return Bits(other) - self
|
||||||
|
|
||||||
|
def __rmul__(self, other):
|
||||||
|
return Bits(other) * self
|
||||||
|
|
||||||
|
def __rmatmul__(self, other):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __rtruediv__(self, other):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __rfloordiv__(self, other):
|
||||||
|
return Bits(other) // self
|
||||||
|
|
||||||
|
def __rmod__(self, other):
|
||||||
|
return Bits(other) % self
|
||||||
|
|
||||||
|
def __rdivmod__(self, other):
|
||||||
|
return (Bits(other) // self, Bits(other) % self)
|
||||||
|
|
||||||
|
def __rpow__(self, other, mod=None):
|
||||||
|
ret = Bits(0)
|
||||||
|
if mod is None:
|
||||||
|
ret = Bits(other) ** self
|
||||||
|
else:
|
||||||
|
ret = Bits(other) ** self % Bits(mod)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __rlshift__(self, other):
|
||||||
|
return Bits(other) << self
|
||||||
|
|
||||||
|
def __rrshift__(self, other):
|
||||||
|
return Bits(other) >> self
|
||||||
|
|
||||||
|
def __rand__(self, other):
|
||||||
|
return Bits(other) & self
|
||||||
|
|
||||||
|
def __rxor__(self, other):
|
||||||
|
return Bits(other) ^ self
|
||||||
|
|
||||||
|
def __ror__(self, other):
|
||||||
|
return Bits(other) | self
|
||||||
|
|
||||||
|
def __iadd__(self, other):
|
||||||
|
self = self + Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __isub__(self, other):
|
||||||
|
self = self - Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __imul__(self, other):
|
||||||
|
self = self * Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __imatmul__(self, other):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __itruediv__(self, other):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __ifloordiv__(self, other):
|
||||||
|
self = self // Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __imod__(self, other):
|
||||||
|
self = self % Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __ipow__(self, other):
|
||||||
|
self = self ** Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __ilshift__(self, other):
|
||||||
|
self = self << Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __irshift__(self, other):
|
||||||
|
self = self >> Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __iand__(self, other):
|
||||||
|
self = self & Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __ixor__(self, other):
|
||||||
|
self = self ^ Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __ior__(self, other):
|
||||||
|
self = self | Bits(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __contains__(self, item):
|
||||||
|
val = Bits(item) & self
|
||||||
|
return val == Bits(item)
|
||||||
|
|
||||||
def __setvalue(self, var):
|
def __setvalue(self, var):
|
||||||
self.__value = 0
|
self.__value = 0
|
||||||
if isinstance(var, int):
|
if isinstance(var, Bits):
|
||||||
|
self.__value = int(var)
|
||||||
|
elif isinstance(var, int):
|
||||||
if var < 0 or var > 255:
|
if var < 0 or var > 255:
|
||||||
raise ValueError("Integer must be between 0 and 255")
|
raise ValueError("Integer must be between 0 and 255")
|
||||||
self.__value = var
|
self.__value = var
|
||||||
|
@ -166,6 +315,14 @@ class Bits:
|
||||||
def chr(self):
|
def chr(self):
|
||||||
return chr(self.__value)
|
return chr(self.__value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def int(self):
|
||||||
|
return int(self)
|
||||||
|
|
||||||
|
@int.setter
|
||||||
|
def int(self, value):
|
||||||
|
self.__setvalue(value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def byte(self):
|
def byte(self):
|
||||||
return bytes(self)
|
return bytes(self)
|
||||||
|
@ -185,11 +342,19 @@ class Bits:
|
||||||
def nibble(self):
|
def nibble(self):
|
||||||
return [self.bin()[:4], self.bin()[4:]]
|
return [self.bin()[:4], self.bin()[4:]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rtl(self):
|
||||||
|
return self.__r_to_l
|
||||||
|
|
||||||
|
@rtl.setter
|
||||||
|
def rtl(self, msb_last):
|
||||||
|
self.__r_to_l = bool(msb_last)
|
||||||
|
|
||||||
def list(self, pad=True, reverse=False):
|
def list(self, pad=True, reverse=False):
|
||||||
ret = []
|
ret = []
|
||||||
bits = self.bin(pad=pad, reverse=reverse)
|
bits = self.bin(pad=pad, reverse=reverse)
|
||||||
for bit in bits:
|
for b in bits:
|
||||||
ret.append(bool(int(bit)))
|
ret.append(Bit(b))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ class TestBits(TestCase):
|
||||||
with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \
|
with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \
|
||||||
+ " [without leading zeros]"):
|
+ " [without leading zeros]"):
|
||||||
self.assertEqual(testcase["bitsObject"].bin(pad=False),
|
self.assertEqual(testcase["bitsObject"].bin(pad=False),
|
||||||
testcase["bits"].strip("0"))
|
testcase["bits"].lstrip("0"))
|
||||||
|
|
||||||
def test_reverse(self):
|
def test_reverse(self):
|
||||||
"""
|
"""
|
||||||
|
@ -102,6 +102,48 @@ class TestBits(TestCase):
|
||||||
self.assertEqual(testcase["bitsObject"].bin(),
|
self.assertEqual(testcase["bitsObject"].bin(),
|
||||||
testcase["bits"][::-1])
|
testcase["bits"][::-1])
|
||||||
|
|
||||||
|
def test_membership_operators(self):
|
||||||
|
"""
|
||||||
|
Test the membership operator (x in y)
|
||||||
|
"""
|
||||||
|
with self.subTest("should all be True"):
|
||||||
|
for i in range(1, 256):
|
||||||
|
self.assertTrue(i in Bits(255), f"Bits({i}) in Bits(255) fail")
|
||||||
|
with self.subTest("should all be False"):
|
||||||
|
for i in range(1, 256):
|
||||||
|
self.assertFalse(i in Bits(0), f"Bits({i}) in Bits(0) fail")
|
||||||
|
with self.subTest("should pass"):
|
||||||
|
self.assertIn(1, Bits("00100111"), "1 in Bits(39)")
|
||||||
|
self.assertIn(2, Bits(39), "2 in Bits(39)")
|
||||||
|
self.assertIn(4, Bits(39), "4 in Bits(39)")
|
||||||
|
self.assertNotIn(8, Bits(39), "8 in Bits(39)")
|
||||||
|
self.assertNotIn(16, Bits(39), "16 in Bits(39)")
|
||||||
|
self.assertIn(32, Bits(39), "32 in Bits(39)")
|
||||||
|
self.assertNotIn(64, Bits(39), "64 in Bits(39)")
|
||||||
|
self.assertNotIn(128, Bits(39), "128 in Bits(39)")
|
||||||
|
|
||||||
|
def test_binary_operations(self):
|
||||||
|
self.assertEqual((Bits("00000100") << 3), Bits("00100000"),
|
||||||
|
"Bits(4) << 3 == Bits(32)")
|
||||||
|
self.assertEqual((Bits("00100000") << 1), Bits("01000000"),
|
||||||
|
"Bits(32) << 1 == Bits(64)")
|
||||||
|
self.assertEqual((Bits(64) >> 2), Bits(16),
|
||||||
|
"Bits(64) >> 2 == Bits(16)")
|
||||||
|
self.assertEqual(( 2 << Bits(6)), Bits(128),
|
||||||
|
"2 << Bits(6) == Bits(128)")
|
||||||
|
self.assertEqual((Bits(255) & Bits(64)), Bits(64),
|
||||||
|
"Bits(255) and Bits(64) == Bits(64)")
|
||||||
|
self.assertNotEqual((Bits(32) & Bits(64)), Bits(64),
|
||||||
|
"Bits(32) and Bits(64) != Bits(64)")
|
||||||
|
self.assertEqual((Bits(2) | Bits(32)), 34,
|
||||||
|
"Bits(2) or Bits(32) == 34")
|
||||||
|
self.assertEqual((Bits(80) | Bits(64)), Bits(80),
|
||||||
|
"Bits(80) or Bits(64) == Bits(80)")
|
||||||
|
self.assertEqual((Bits(80) ^ Bits(64)), Bits(16),
|
||||||
|
"Bits(80) xor Bits(64) == Bits(16)")
|
||||||
|
self.assertEqual((Bits(80) & Bits(64)), Bits(64),
|
||||||
|
"Bits(80) and Bits(64) == Bits(64)")
|
||||||
|
|
||||||
def test_comparisons(self):
|
def test_comparisons(self):
|
||||||
"""
|
"""
|
||||||
Test the comparison operators
|
Test the comparison operators
|
||||||
|
|
Loading…
Reference in New Issue