easybits 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
easybits/__init__.py ADDED
@@ -0,0 +1,111 @@
1
+ from bitarray import bitarray
2
+ from bitarray.util import (
3
+ zeros,
4
+ ones,
5
+ int2ba,
6
+ ba2int,
7
+ )
8
+ from easybits.util import is_bit_string
9
+ from easybits.errors import (
10
+ NotEnoughBits,
11
+ IntegersRequireLength,
12
+ IntegerAdditionRequiresSameLength,
13
+ )
14
+
15
+ class Bits(bitarray):
16
+ """A wrapper around bitarray with a more idiomatic interface for beginners.
17
+ - Integers are always signed.
18
+ """
19
+
20
+ @classmethod
21
+ def zeros(cls, length):
22
+ return Bits(zeros(length))
23
+
24
+ @classmethod
25
+ def ones(cls, length):
26
+ return Bits(ones(length))
27
+
28
+ def __new__(cls, value, length=None, encoding='ascii'):
29
+ if isinstance(value, bytes):
30
+ bits = bitarray()
31
+ bits.frombytes(value)
32
+ elif isinstance(value, bool):
33
+ bits = bitarray([value])
34
+ elif isinstance(value, int):
35
+ if not length:
36
+ raise IntegersRequireLength()
37
+ bits = int2ba(value, length=length, signed=True)
38
+ elif isinstance(value, str):
39
+ if is_bit_string(value):
40
+ bits = bitarray(value)
41
+ else:
42
+ bits = bitarray()
43
+ bits.frombytes(value.encode(encoding))
44
+ elif isinstance(value, list):
45
+ bits = bitarray(value)
46
+ elif isinstance(value, bitarray):
47
+ bits = value
48
+ else:
49
+ raise ValueError(f"Can't create bits from {value}")
50
+ if length:
51
+ if length < len(bits):
52
+ raise NotEnoughBits(value, length)
53
+ else:
54
+ sized_bits = bitarray(length)
55
+ sized_bits[-len(bits):] = bits
56
+ else:
57
+ sized_bits = bits
58
+ return super().__new__(cls, sized_bits)
59
+
60
+ def __str__(self):
61
+ bits = self.to01()
62
+
63
+ def __repr__(self):
64
+ return self.to01()
65
+
66
+ @property
67
+ def bool(self):
68
+ return [bool(b) for b in self.tolist()]
69
+
70
+ @property
71
+ def int(self):
72
+ return ba2int(self, signed=True)
73
+
74
+ @property
75
+ def bytes(self):
76
+ return self.tobytes()
77
+
78
+ @property
79
+ def ascii(self):
80
+ return self.bytes.decode("ascii")
81
+
82
+ def __add__(self, other):
83
+ """Performs bitwise addition on `self` and `other`. Does not
84
+ check for overflow.
85
+ """
86
+ a, b = self, Bits(other)
87
+ if not len(a) == len(b):
88
+ raise IntegerAdditionRequiresSameLength()
89
+ result = Bits.zeros(len(a))
90
+ carry = 0
91
+ for i in reversed(range(len(a))):
92
+ result[i] = a[i] ^ b[i] ^ carry
93
+ carry = (a[i] & b[i]) | (a[i] & carry) | (b[i] & carry)
94
+ return result
95
+
96
+ def __sub__(self, other):
97
+ """Performs bitwise addition on `self` and `other`. Does not
98
+ check for overflow.
99
+ """
100
+ a, b = self, Bits(other)
101
+ if not len(a) == len(b):
102
+ raise IntegerAdditionRequiresSameLength()
103
+ return a + (-b)
104
+
105
+ def __neg__(self):
106
+ """Treats `self` as an integer, and flips its sign.
107
+ """
108
+ if self[0]:
109
+ return ~self + Bits(1, length=len(self))
110
+ else:
111
+ return ~(self + Bits(-1, length=len(self)))
easybits/errors.py ADDED
@@ -0,0 +1,15 @@
1
+ class BitsError(Exception):
2
+ message = "Bits error"
3
+
4
+ def __str__(self):
5
+ return self.message
6
+
7
+ class NotEnoughBits(BitsError):
8
+ def __init__(self, obj, length):
9
+ self.message = f"{obj} cannot fit into {length} bits."
10
+
11
+ class IntegersRequireLength(BitsError):
12
+ message = "Binary representations of integers require that a length be provided."
13
+
14
+ class IntegerAdditionRequiresSameLength(BitsError):
15
+ message = "Can only add integers of the same length."
easybits/util.py ADDED
@@ -0,0 +1,5 @@
1
+
2
+ def is_bit_string(value):
3
+ bit_chars = {'1', '0', ' '}
4
+ return not (set(value) - bit_chars)
5
+
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.1
2
+ Name: easybits
3
+ Version: 0.1.0
4
+ Summary: A friendly interface for exploring bits.
5
+ Author: Chris Proctor
6
+ Author-email: chris@chrisproctor.net
7
+ Requires-Python: >=3.9,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Requires-Dist: bitarray (>=3.0.0,<4.0.0)
13
+ Description-Content-Type: text/markdown
14
+
15
+ # Easybits
16
+
17
+ A friendly interface for exploring bits.
18
+
@@ -0,0 +1,6 @@
1
+ easybits/__init__.py,sha256=qnmlE5N3MkBB6_pQavtgAK6uzV0dj0zi50puMmUwRGQ,3144
2
+ easybits/errors.py,sha256=MPQGCYUave-PCKP4IkfIS2NJzL2j2KH2W3rlPofsigo,478
3
+ easybits/util.py,sha256=GYlFDgqk1sBkFidKsoo9xaO7QZ8_v7KFavP2KnV0mZ8,100
4
+ easybits-0.1.0.dist-info/METADATA,sha256=XnRyaeO0SiTqzWd6Q2GX0B7DWciDl38iylJbQgP_5Sc,525
5
+ easybits-0.1.0.dist-info/WHEEL,sha256=kLuE8m1WYU0Ig0_YEGrXyTtiJvKPpLpDEiChiNyei5Y,88
6
+ easybits-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.5.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any