Improve doc; add Bit.set and unset methods
This commit is contained in:
parent
1226400c2d
commit
97f7d58dd7
254
src/bits.py
254
src/bits.py
|
@ -1,33 +1,218 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
============================
|
||||||
|
Binary manipulation classes
|
||||||
|
============================
|
||||||
|
|
||||||
|
Provides classes that assist in managing, comparing, transforming and working
|
||||||
|
with binary data in general.
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
Provided Classes
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Bit
|
||||||
|
===
|
||||||
|
The Bit is the smallest representation of binary data and represents True or
|
||||||
|
False. This class provides methods to perform binary comparisons and
|
||||||
|
conversions between different types that can be used to represent a single
|
||||||
|
binary value.
|
||||||
|
|
||||||
|
Byte
|
||||||
|
====
|
||||||
|
A Byte is the representation of 8 Bits. The Byte class provides methods to
|
||||||
|
compare a single binary Byte to other data types. The Class also provides
|
||||||
|
binary math functions and allows getting and setting the state of individual
|
||||||
|
Bits.
|
||||||
|
|
||||||
|
Bytes
|
||||||
|
=====
|
||||||
|
The Bytes class allows an arbitrary amount of binary data to be represented.
|
||||||
|
The Bytes class provides access to each byte using the Byte class, which
|
||||||
|
further allows all the methods to be used on the binary data provided by the
|
||||||
|
Byte and Bit classes. Bytes can be compared and converted between several
|
||||||
|
different data types.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
class Bit:
|
class Bit:
|
||||||
"""
|
"""
|
||||||
Provide a flexible bit representation.
|
====
|
||||||
|
|
||||||
Extended description of function.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
var : bool | int | str | Bit
|
|
||||||
Any of the supported objects which can be converted to a Bit object.
|
|
||||||
bool: True or False
|
|
||||||
int: 0 = False, anything else = True
|
|
||||||
str: "0" = False, anything else = True
|
|
||||||
BIT: Bit = Bit
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Bit
|
Bit
|
||||||
A binary representation of True or False with additional useful
|
====
|
||||||
features.
|
|
||||||
|
A single binary bit representation of True or False
|
||||||
|
|
||||||
|
A Bit object can be compared and converted to int, str, bool and other Bit
|
||||||
|
objects. The Bit class is backed by a single bool variable. This backing
|
||||||
|
bool object is converted as necessary to provide conversions and
|
||||||
|
comparisons with other data types. Keep this in mind as converting an
|
||||||
|
object to Bit and then attempting to convert back to the original object
|
||||||
|
may not yield the exact same value.
|
||||||
|
|
||||||
|
In the case of comparisons, the object being compared is cast as a Bit
|
||||||
|
object, and the two Bit objects are then compared with each other and the
|
||||||
|
result of the comparison is returned.
|
||||||
|
|
||||||
|
----------------
|
||||||
|
Type Conversion
|
||||||
|
----------------
|
||||||
|
The objects that can be converted to and from a Bit include *bool*, *int*,
|
||||||
|
*str* and other *Bit* objects.
|
||||||
|
|
||||||
|
Convert *bool* to *Bit*:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
/>/>/> a_bit = Bit(True)
|
||||||
|
/>/>/> a_bit
|
||||||
|
Bit(1)
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
Convert *Bit* to *bool*:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
/>/>/> a_bool = bool(Bit(True))
|
||||||
|
/>/>/> a_bool
|
||||||
|
True
|
||||||
|
/>/>/> type(a_bool)
|
||||||
|
<class 'bool'>
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
Convert *int* to *Bit*:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
/>/>/> unset_bit = Bit(0)
|
||||||
|
/>/>/> unset_bit
|
||||||
|
Bit(0)
|
||||||
|
/>/>/> set_bit = Bit(1)
|
||||||
|
/>/>/> set_bit
|
||||||
|
Bit(1)
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
Convert *Bit* to *int*:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
/>/>/> my_int = int(Bit(1))
|
||||||
|
/>/>/> my_int
|
||||||
|
1
|
||||||
|
/>/>/> type(my_int)
|
||||||
|
<class 'int'>
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
.. note:: The only values allowed for *int* are **0** and **1**
|
||||||
|
|
||||||
|
Convert *str* to *Bit*:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
/>/>/> unset_bit = Bit("0")
|
||||||
|
/>/>/> unset_bit
|
||||||
|
Bit(0)
|
||||||
|
/>/>/> set_bit = Bit("1")
|
||||||
|
/>/>/> set_bit
|
||||||
|
Bit(1)
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
Convert *Bit* to *str*:
|
||||||
|
.. code-block: python
|
||||||
|
|
||||||
|
/>/>/> my_str = str(Bit(False))
|
||||||
|
/>/>/> my_str
|
||||||
|
'0'
|
||||||
|
/>/>/> type(my_str)
|
||||||
|
<class 'str'>
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
.. note:: The only *str* characters allowed are a single **0** or **1**
|
||||||
|
|
||||||
|
|
||||||
|
------------
|
||||||
|
Comparisons
|
||||||
|
------------
|
||||||
|
A Bit object can be compared to any object which can be cast to a Bit
|
||||||
|
|
||||||
|
.. code-block: python
|
||||||
|
|
||||||
|
/>/>/> 0 == Bit(False) == Bit("0") == Bit(0) == False
|
||||||
|
True
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
.. note:: Comparing an object with a value that cannot be cast to Bit will
|
||||||
|
return a ValueError.
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
Rich Comparisons
|
||||||
|
-----------------
|
||||||
|
Bit objects also support "rich comparisons". For example:
|
||||||
|
|
||||||
|
.. code-block: python
|
||||||
|
|
||||||
|
/>/>/> Bit(False) < 1
|
||||||
|
True
|
||||||
|
/>/>/> Bit(True) <= 1
|
||||||
|
True
|
||||||
|
/>/>/> Bit(False) <= "1"
|
||||||
|
True
|
||||||
|
/>/>/> Bit(False) != True
|
||||||
|
True
|
||||||
|
/>/>/> Bit(True) >= False
|
||||||
|
False
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
|
||||||
|
--------
|
||||||
|
Methods
|
||||||
|
--------
|
||||||
|
The action method `toggle` is provided for convenience.
|
||||||
|
|
||||||
|
.. code-block: python
|
||||||
|
|
||||||
|
/>/>/> Bit(False).toggle()
|
||||||
|
Bit(1)
|
||||||
|
/>/>/> Bit(True).toggle() == False
|
||||||
|
True
|
||||||
|
/>/>/> int(Bit(False).toggle())
|
||||||
|
1
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
The `set` and `unset` methods are also provided to explicitely set the
|
||||||
|
value of Bit.
|
||||||
|
|
||||||
|
.. code-block: python
|
||||||
|
|
||||||
|
/>/>/> a_bit = Bit(0)
|
||||||
|
/>/>/> a_bit
|
||||||
|
Bit(0)
|
||||||
|
/>/>/> a_bit.set()
|
||||||
|
/>/>/> a_bit
|
||||||
|
Bit(1)
|
||||||
|
/>/>/> a_bit.unset()
|
||||||
|
/>/>/> a_bit
|
||||||
|
Bit(0)
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
|
|
||||||
|
-----------
|
||||||
|
Properties
|
||||||
|
-----------
|
||||||
|
The `lie` property returns the opposite value of Bit as a *bool*. Unlike
|
||||||
|
the `toggle` method, `lie` does not change the value of the Bit.
|
||||||
|
|
||||||
|
.. code-block: python
|
||||||
|
|
||||||
|
/>/>/> Bit(1).lie
|
||||||
|
False
|
||||||
|
/>/>/>
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, var):
|
def __init__(self, var):
|
||||||
"""
|
"""
|
||||||
var: Any supported type
|
var: Any supported type
|
||||||
Supported types: (bool, int, str, Bit)
|
Supported types: (bool, int, str, Bit)
|
||||||
bool: True or False
|
bool: True or False
|
||||||
int: 0 = False, anything else = True
|
int: 0 = False, 1 = True
|
||||||
str: "0" = False, anything else = True
|
str: "0" = False, "1" = True
|
||||||
Bit: Bit = Bit
|
Bit: Bit = Bit
|
||||||
"""
|
"""
|
||||||
if not isinstance(var, (bool, int, str, Bit)):
|
if not isinstance(var, (bool, int, str, Bit)):
|
||||||
|
@ -45,25 +230,22 @@ class Bit:
|
||||||
self.__bit = var
|
self.__bit = var
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""
|
"""Return '0' or '1'"""
|
||||||
Return "0" or "1"
|
|
||||||
"""
|
|
||||||
return str(int(self.__bit))
|
return str(int(self.__bit))
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
|
"""Return 0 or 1"""
|
||||||
return int(self.__bit)
|
return int(self.__bit)
|
||||||
|
|
||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
|
"""Returns True or False"""
|
||||||
return self.__bit
|
return self.__bit
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.__class__.__name__}({int(self.__bit)})'
|
return f'{self.__class__.__name__}({int(self.__bit)})'
|
||||||
|
|
||||||
def __eq__(self, compare):
|
def __eq__(self, compare):
|
||||||
"""
|
"""compare (self) to any supported object"""
|
||||||
compare (self) to any supported object
|
|
||||||
"""
|
|
||||||
# Massage compare to bool
|
|
||||||
return bool(self) == bool(Bit(compare))
|
return bool(self) == bool(Bit(compare))
|
||||||
|
|
||||||
def __ne__(self, compare):
|
def __ne__(self, compare):
|
||||||
|
@ -85,22 +267,24 @@ class Bit:
|
||||||
return self.__bit
|
return self.__bit
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
"""
|
"""Not very useful, but provided nonetheless"""
|
||||||
Not very useful, but provided nonetheless
|
|
||||||
"""
|
|
||||||
return hash(self.__bit)
|
return hash(self.__bit)
|
||||||
|
|
||||||
def toggle(self):
|
def toggle(self):
|
||||||
"""
|
"""Change the state of (self) to Not (self)"""
|
||||||
(self) = Not (Self)
|
|
||||||
"""
|
|
||||||
self.__bit = not self.__bit
|
self.__bit = not self.__bit
|
||||||
|
|
||||||
|
def set(self):
|
||||||
|
"""Set Bit to True"""
|
||||||
|
self.__bit = True
|
||||||
|
|
||||||
|
def unset(self):
|
||||||
|
"""Set Bit to False"""
|
||||||
|
self.__bit = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lie(self):
|
def lie(self):
|
||||||
"""
|
"""Return the opposite of bit, without changing the state of (self)"""
|
||||||
Return the opposite of bit, without changing the state of (self)
|
|
||||||
"""
|
|
||||||
return not self.__bit
|
return not self.__bit
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,24 @@ class TestBit(TestCase):
|
||||||
var.toggle()
|
var.toggle()
|
||||||
self.assertTrue(var, "Bit(False).toggle() == True")
|
self.assertTrue(var, "Bit(False).toggle() == True")
|
||||||
|
|
||||||
|
def test_set(self):
|
||||||
|
"""Test the set() method"""
|
||||||
|
var = Bit(False)
|
||||||
|
var.set()
|
||||||
|
self.assertTrue(var, "Bit(False).set() == True")
|
||||||
|
var = Bit(True)
|
||||||
|
var.set()
|
||||||
|
self.assertTrue(var, "Bit(True).set() == True")
|
||||||
|
|
||||||
|
def test_unset(self):
|
||||||
|
"""Test the unset() method"""
|
||||||
|
var = Bit(True)
|
||||||
|
var.unset()
|
||||||
|
self.assertFalse(var, "Bit(True).unset() == False")
|
||||||
|
var = Bit(False)
|
||||||
|
var.unset()
|
||||||
|
self.assertFalse(var, "Bit(False).unset() == False")
|
||||||
|
|
||||||
def test_errors(self):
|
def test_errors(self):
|
||||||
"""
|
"""
|
||||||
Test that errors are raised for invalid values
|
Test that errors are raised for invalid values
|
||||||
|
|
Loading…
Reference in New Issue