easybits 0.1.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,3 @@
1
+ # Easybits
2
+
3
+ A friendly interface for exploring bits.
@@ -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)))
@@ -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."
@@ -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,14 @@
1
+ [tool.poetry]
2
+ name = "easybits"
3
+ version = "0.1.0"
4
+ description = "A friendly interface for exploring bits."
5
+ authors = ["Chris Proctor <chris@chrisproctor.net>"]
6
+ readme = "README.md"
7
+
8
+ [tool.poetry.dependencies]
9
+ python = "^3.9"
10
+ bitarray = "^3.0.0"
11
+
12
+ [build-system]
13
+ requires = ["poetry-core"]
14
+ build-backend = "poetry.core.masonry.api"