Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-bitstring for
openSUSE:Factory checked in at 2022-01-15 20:05:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-bitstring (Old)
and /work/SRC/openSUSE:Factory/.python-bitstring.new.1892 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-bitstring"
Sat Jan 15 20:05:14 2022 rev:5 rq:946638 version:3.1.9
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-bitstring/python-bitstring.changes
2020-09-17 15:09:07.840954417 +0200
+++
/work/SRC/openSUSE:Factory/.python-bitstring.new.1892/python-bitstring.changes
2022-01-15 20:05:26.409770251 +0100
@@ -1,0 +2,12 @@
+Sat Jan 15 15:22:21 UTC 2022 - Dirk M??ller <[email protected]>
+
+- update to 3.1.9:
+ * Fixed a couple of outdated results in the readme (Issue 214).
+ * Some more documentation tidying.
+ * Turned off some debug code by default.
+ * Fixed a couple of failing tests in different Python versions.
+ * Fix for consistent pos initialisation semantics for different types.
+ * Change to allow wheels to be uploaded to PyPI.
+ * More work for LSB0 mode, but still not finished or documented (sorry).
+
+-------------------------------------------------------------------
Old:
----
bitstring-3.1.7.tar.gz
New:
----
bitstring-3.1.9.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-bitstring.spec ++++++
--- /var/tmp/diff_new_pack.PPEtZz/_old 2022-01-15 20:05:26.913770644 +0100
+++ /var/tmp/diff_new_pack.PPEtZz/_new 2022-01-15 20:05:26.921770650 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-bitstring
#
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-bitstring
-Version: 3.1.7
+Version: 3.1.9
Release: 0
Summary: Python module for the construction, analysis and modification
of binary data
License: MIT
++++++ bitstring-3.1.7.tar.gz -> bitstring-3.1.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/LICENSE
new/bitstring-bitstring-3.1.9/LICENSE
--- old/bitstring-bitstring-3.1.7/LICENSE 2020-05-05 22:05:19.000000000
+0200
+++ new/bitstring-bitstring-3.1.9/LICENSE 2021-07-20 19:37:11.000000000
+0200
@@ -1,6 +1,6 @@
The MIT License
-Copyright (c) 2006-2016 Scott Griffiths ([email protected])
+Copyright (c) 2006 Scott Griffiths ([email protected])
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/README.rst
new/bitstring-bitstring-3.1.9/README.rst
--- old/bitstring-bitstring-3.1.7/README.rst 2020-05-05 22:05:19.000000000
+0200
+++ new/bitstring-bitstring-3.1.9/README.rst 2021-07-20 19:37:11.000000000
+0200
@@ -14,7 +14,7 @@
bitstring is open source software, and has been released under the MIT
licence.
-This module works in both Python 2.7 and Python 3.
+This module works in both Python 2.7 and Python 3.6+.
Installation
------------
@@ -23,12 +23,6 @@
pip install bitstring
-Alternatively if you have downloaded and unzipped the package then you need to
run the
-``setup.py`` script with the 'install' argument::
-
- python setup.py install
-
-You may need to run this with root privileges on Unix-like systems.
Documentation
-------------
@@ -56,8 +50,8 @@
('1af', '000110101111', 431)
>>> a[10:3:-1].bin
'1110101'
- >>> 3*a + '0b100'
- BitArray('0o0657056705674')
+ >>> '0b100' + 3*a
+ BitArray('0x835e35e35, 0b111')
Reading data sequentially::
@@ -76,7 +70,7 @@
>>> c.find('0x48')
(8,)
>>> c.replace('0b001', '0xabc')
- >>> c.insert('0b0000')
+ >>> c.insert('0b0000', pos=3)
>>> del c[12:16]
Unit Tests
@@ -90,7 +84,7 @@
----
The bitstring module has been released as open source under the MIT License.
-Copyright (c) 2008-2020 Scott Griffiths
+Copyright (c) 2006 Scott Griffiths
For more information see the project's homepage on GitHub:
<https://github.com/scott-griffiths/bitstring>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/bitstring.py
new/bitstring-bitstring-3.1.9/bitstring.py
--- old/bitstring-bitstring-3.1.7/bitstring.py 2020-05-05 22:05:19.000000000
+0200
+++ new/bitstring-bitstring-3.1.9/bitstring.py 2021-07-20 19:37:11.000000000
+0200
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-"""
+r"""
This package defines classes that simplify bit-wise creation, manipulation and
interpretation of data.
@@ -38,7 +38,7 @@
__licence__ = """
The MIT License
-Copyright (c) 2006-2020 Scott Griffiths ([email protected])
+Copyright (c) 2006 Scott Griffiths ([email protected])
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -59,7 +59,7 @@
THE SOFTWARE.
"""
-__version__ = "3.1.7"
+__version__ = "3.1.9"
__author__ = "Scott Griffiths"
@@ -93,6 +93,9 @@
# Maximum size of caches used for speed optimisations.
CACHE_SIZE = 1000
+# Set this to True for extra assertions for debugging.
+_debug = False
+
class Error(Exception):
"""Base class for errors in the bitstring module."""
@@ -228,7 +231,7 @@
if bit_offset:
# first do the byte with the join.
joinval = (store.getbyte(-1) & (255 ^ (255 >> bit_offset)) |
- (self._rawarray[self.byteoffset] & (255 >>
bit_offset)))
+ (self._rawarray[self.byteoffset] & (255 >> bit_offset)))
store._rawarray[-1] = joinval
store._rawarray.extend(self._rawarray[self.byteoffset + 1:
self.byteoffset + self.bytelength])
else:
@@ -312,19 +315,17 @@
shiftleft = s.offset % 8 - newoffset
# First deal with everything except for the final byte
for x in range(s.byteoffset, s.byteoffset + s.bytelength - 1):
- newdata.append(((d[x] << shiftleft) & 0xff) +\
- (d[x + 1] >> (8 - shiftleft)))
+ newdata.append(((d[x] << shiftleft) & 0xff) + (d[x + 1] >> (8
- shiftleft)))
bits_in_last_byte = (s.offset + s.bitlength) % 8
if not bits_in_last_byte:
bits_in_last_byte = 8
if bits_in_last_byte > shiftleft:
newdata.append((d[s.byteoffset + s.bytelength - 1] <<
shiftleft) & 0xff)
- else: # newoffset > s._offset % 8
+ else: # newoffset > s._offset % 8
shiftright = newoffset - s.offset % 8
newdata.append(s.getbyte(0) >> shiftright)
for x in range(s.byteoffset + 1, s.byteoffset + s.bytelength):
- newdata.append(((d[x - 1] << (8 - shiftright)) & 0xff) +\
- (d[x] >> shiftright))
+ newdata.append(((d[x - 1] << (8 - shiftright)) & 0xff) + (d[x]
>> shiftright))
bits_in_last_byte = (s.offset + s.bitlength) % 8
if not bits_in_last_byte:
bits_in_last_byte = 8
@@ -504,26 +505,28 @@
# Python 2.x octals start with '0', in Python 3 it's '0o'
LEADING_OCT_CHARS = len(oct(1)) - 1
+
def tidy_input_string(s):
"""Return string made lowercase and with all whitespace removed."""
s = ''.join(s.split()).lower()
return s
+
INIT_NAMES = ('uint', 'int', 'ue', 'se', 'sie', 'uie', 'hex', 'oct', 'bin',
'bits',
'uintbe', 'intbe', 'uintle', 'intle', 'uintne', 'intne',
'float', 'floatbe', 'floatle', 'floatne', 'bytes', 'bool', 'pad')
TOKEN_RE = re.compile(r'(?P<name>' + '|'.join(INIT_NAMES) +
- r')((:(?P<len>[^=]+)))?(=(?P<value>.*))?$',
re.IGNORECASE)
+ r')(:(?P<len>[^=]+))?(=(?P<value>.*))?$', re.IGNORECASE)
DEFAULT_UINT = re.compile(r'(?P<len>[^=]+)?(=(?P<value>.*))?$', re.IGNORECASE)
MULTIPLICATIVE_RE = re.compile(r'(?P<factor>.*)\*(?P<token>.+)')
# Hex, oct or binary literals
-LITERAL_RE = re.compile(r'(?P<name>0(x|o|b))(?P<value>.+)', re.IGNORECASE)
+LITERAL_RE = re.compile(r'(?P<name>0([xob]))(?P<value>.+)', re.IGNORECASE)
# An endianness indicator followed by one or more struct.pack codes
-STRUCT_PACK_RE =
re.compile(r'(?P<endian><|>|@)?(?P<fmt>(?:\d*[bBhHlLqQfd])+)$')
+STRUCT_PACK_RE =
re.compile(r'(?P<endian>[<>@])?(?P<fmt>(?:\d*[bBhHlLqQfd])+)$')
# A number followed by a single character struct.pack code
STRUCT_SPLIT_RE = re.compile(r'\d*[bBhHlLqQfd]')
@@ -550,6 +553,7 @@
'0o': 'oct', '0O': 'oct', 'bin': 'bin', '0b':
'bin',
'0B': 'bin', 'bits': 'auto', 'bytes': 'bytes',
'pad': 'pad'}
+
def structparser(token):
"""Parse struct-like format string token into sub-token list."""
m = STRUCT_PACK_RE.match(token)
@@ -561,7 +565,7 @@
return [token]
# Split the format string into a list of 'q', '4h' etc.
formatlist = re.findall(STRUCT_SPLIT_RE, m.group('fmt'))
- # Now deal with mulitiplicative factors, 4h -> hhhh etc.
+ # Now deal with multiplicative factors, 4h -> hhhh etc.
fmt = ''.join([f[-1] * int(f[:-1]) if len(f) != 1 else
f for f in formatlist])
if endian == '@':
@@ -578,6 +582,7 @@
tokens = [REPLACEMENTS_BE[c] for c in fmt]
return tokens
+
def tokenparser(fmt, keys=None, token_cache={}):
"""Divide the format string into tokens and parse them.
@@ -679,9 +684,11 @@
token_cache[token_key] = stretchy_token, return_values
return stretchy_token, return_values
+
# Looks for first number*(
BRACKET_RE = re.compile(r'(?P<factor>\d+)\*\(')
+
def expand_brackets(s):
"""Remove whitespace and expand all brackets."""
s = ''.join(s.split())
@@ -689,7 +696,7 @@
start = s.find('(')
if start == -1:
break
- count = 1 # Number of hanging open brackets
+ count = 1 # Number of hanging open brackets
p = start + 1
while p < len(s):
if s[p] == '(':
@@ -828,6 +835,10 @@
_, tokens = tokenparser(auto)
except ValueError as e:
raise CreationError(*e.args)
+ if offset is not None:
+ raise CreationError("offset should not be specified
when using string initialisation.")
+ if length is not None:
+ raise CreationError("length should not be specified
when using string initialisation.")
x._datastore = ConstByteStore(bytearray(0), 0, 0)
for token in tokens:
x._datastore._appendstore(Bits._init_with_token(*token)._datastore)
@@ -914,11 +925,11 @@
bs = Bits(bs)
if bs.len <= self.len:
s = self._copy()
- s._append(bs)
+ s._addright(bs)
else:
s = bs._copy()
s = self.__class__(s)
- s._prepend(self)
+ s._addleft(self)
return s
def __radd__(self, bs):
@@ -1017,19 +1028,25 @@
"""
length = self.len
+ try:
+ pos = self._pos
+ pos_string = "" if pos == 0 else ", pos={0}".format(pos)
+ except AttributeError:
+ pos_string = ""
if isinstance(self._datastore._rawarray, MmapByteArray):
offsetstring = ''
if self._datastore.byteoffset or self._offset:
offsetstring = ", offset=%d" %
(self._datastore._rawarray.byteoffset * 8 + self._offset)
lengthstring = ", length=%d" % length
- return "{0}(filename='{1}'{2}{3})".format(self.__class__.__name__,
- self._datastore._rawarray.source.name, lengthstring,
offsetstring)
+ return
"{0}(filename='{1}'{2}{3}{4})".format(self.__class__.__name__,
+
self._datastore._rawarray.source.name,
+ lengthstring,
offsetstring, pos_string)
else:
s = self.__str__()
lengthstring = ''
if s.endswith('...'):
lengthstring = " # length={0}".format(length)
- return "{0}('{1}'){2}".format(self.__class__.__name__, s,
lengthstring)
+ return "{0}('{1}'{2}){3}".format(self.__class__.__name__, s,
pos_string, lengthstring)
def __eq__(self, bs):
"""Return True if two bitstrings have the same binary representation.
@@ -1077,7 +1094,7 @@
raise ValueError("Cannot shift an empty bitstring.")
n = min(n, self.len)
s = self._slice(n, self.len)
- s._append(Bits(n))
+ s._addright(Bits(n))
return s
def __rshift__(self, n):
@@ -1093,7 +1110,7 @@
if not n:
return self._copy()
s = self.__class__(length=min(n, self.len))
- s._append(self[:-n])
+ s._addright(self[:-n])
return s
def __mul__(self, n):
@@ -1247,12 +1264,17 @@
# ...whereas this is used in Python 3.x
__bool__ = __nonzero__
- def _assertsanity(self):
- """Check internal self consistency as a debugging aid."""
- assert self.len >= 0
- assert 0 <= self._offset, "offset={0}".format(self._offset)
- assert (self.len + self._offset + 7) // 8 ==
self._datastore.bytelength + self._datastore.byteoffset, "len={0}, offset={1},
bytelength={2}, byteoffset={3}".format(self.len, self._offset,
self._datastore.bytelength, self._datastore.byteoffset)
- return True
+ if _debug is True:
+ def _assertsanity(self):
+ """Check internal self consistency as a debugging aid."""
+ assert self.len >= 0
+ assert 0 <= self._offset, "offset={0}".format(self._offset)
+ assert (self.len + self._offset + 7) // 8 ==
self._datastore.bytelength + self._datastore.byteoffset, "len={0}, offset={1},
bytelength={2}, byteoffset={3}".format(self.len, self._offset,
self._datastore.bytelength, self._datastore.byteoffset)
+ return True
+ else:
+ @staticmethod
+ def _assertsanity():
+ return True
@classmethod
def _init_with_token(cls, name, token_length, value):
@@ -1438,7 +1460,7 @@
"The allowed range is [0, {2}]."
raise CreationError(msg, uint, length, (1 << length) - 1)
if uint < 0:
- raise CreationError("uint cannot be initialsed by a negative
number.")
+ raise CreationError("uint cannot be initialised by a negative
number.")
s = hex(uint)[2:]
s = s.rstrip('L')
if len(s) & 1:
@@ -1457,7 +1479,11 @@
offset = 0
self._setbytes_unsafe(bytearray(data), length, offset)
- def _readuint(self, length, start):
+ def _readuint_lsb0(self, length, start):
+ # TODO: This needs a complete rewrite - can't delegate to
_readuint_msb0
+ return self._readuint_msb0(length, self.len - start - length)
+
+ def _readuint_msb0(self, length, start):
"""Read bits and interpret as an unsigned int."""
if not length:
raise InterpretError("Cannot interpret a zero length bitstring "
@@ -1831,7 +1857,7 @@
self._setbin_unsafe('1')
else:
self._setuie(abs(i))
- self._append(Bits([i < 0]))
+ self._addright(Bits([i < 0]))
def _getsie(self):
"""Return data as signed interleaved exponential-Golomb code.
@@ -2027,10 +2053,10 @@
except ValueError as e:
raise CreationError(*e.args)
if tokens:
- b._append(Bits._init_with_token(*tokens[0]))
+ b._addright(Bits._init_with_token(*tokens[0]))
b._datastore = offsetcopy(b._datastore, offset)
for token in tokens[1:]:
- b._append(Bits._init_with_token(*token))
+ b._addright(Bits._init_with_token(*token))
assert b._assertsanity()
assert b.len == 0 or b._offset == offset
if len(cache) < CACHE_SIZE:
@@ -2080,11 +2106,11 @@
# This is for the 'ue', 'se' and 'bool' tokens. They will also
return the new pos.
return name_to_read[name](self, pos)
- def _append(self, bs):
- """Append a bitstring to the current bitstring."""
+ def _addright(self, bs):
+ """Add a bitstring to the RHS of the current bitstring."""
self._datastore._appendstore(bs._datastore)
- def _prepend(self, bs):
+ def _addleft(self, bs):
"""Prepend a bitstring to the current bitstring."""
self._datastore._prependstore(bs._datastore)
@@ -2101,30 +2127,34 @@
self._setbytes_unsafe(bytearray().join(n), self.length, newoffset)
def _truncateleft(self, bits):
- """Truncate bits from the LHS of the bitstring."""
+ """Truncate bits from the start of the bitstring."""
assert 0 <= bits <= self.len
if not bits:
- return
+ return Bits()
+ truncated_bits = self._slice_msb0(0, bits)
if bits == self.len:
self._clear()
- return
+ return truncated_bits
bytepos, offset = divmod(self._offset + bits, 8)
self._setbytes_unsafe(self._datastore.getbyteslice(bytepos,
self._datastore.bytelength), self.len - bits,
offset)
assert self._assertsanity()
+ return truncated_bits
def _truncateright(self, bits):
- """Truncate bits from the RHS of the bitstring."""
+ """Truncate bits from the end of the bitstring."""
assert 0 <= bits <= self.len
if not bits:
- return
+ return Bits()
+ truncated_bits = self._slice_lsb0(0, bits)
if bits == self.len:
self._clear()
- return
+ return truncated_bits
newlength_in_bytes = (self._offset + self.len - bits + 7) // 8
self._setbytes_unsafe(self._datastore.getbyteslice(0,
newlength_in_bytes), self.len - bits,
self._offset)
assert self._assertsanity()
+ return truncated_bits
def _insert_lsb0(self, bs, pos):
"""Insert bs at pos (LSB0)."""
@@ -2135,16 +2165,16 @@
assert 0 <= pos <= self.len
if pos > self.len // 2:
# Inserting nearer end, so cut off end.
- end = self._slice(pos, self.len)
- self._truncateright(self.len - pos)
- self._append(bs)
- self._append(end)
+ # end = self._slice(pos, self.len)
+ end = self._truncateright(self.len - pos)
+ self._addright(bs)
+ self._addright(end)
else:
# Inserting nearer start, so cut off start.
start = self._slice(0, pos)
self._truncateleft(pos)
- self._prepend(bs)
- self._prepend(start)
+ self._addleft(bs)
+ self._addleft(start)
try:
self._pos = pos + bs.len
except AttributeError:
@@ -2210,12 +2240,12 @@
end = self._slice_msb0(pos + bits, self.len)
assert self.len - pos > 0
self._truncateright(self.len - pos)
- self._append(end)
+ self._addright(end)
return
# More bits after the cut point than before it.
start = self._slice_msb0(0, pos)
self._truncateleft(pos + bits)
- self._prepend(start)
+ self._addleft(start)
return
def _reversebytes(self, start, end):
@@ -2254,14 +2284,14 @@
def _ilshift(self, n):
"""Shift bits by n to the left in place. Return self."""
assert 0 < n <= self.len
- self._append(Bits(n))
+ self._addright(Bits(n))
self._truncateleft(n)
return self
def _irshift(self, n):
"""Shift bits by n to the right in place. Return self."""
assert 0 < n <= self.len
- self._prepend(Bits(n))
+ self._addleft(Bits(n))
self._truncateright(n)
return self
@@ -2274,9 +2304,9 @@
m = 1
old_len = self.len
while m * 2 < n:
- self._append(self)
+ self._addright(self)
m *= 2
- self._append(self[0:(n - m) * old_len])
+ self._addright(self[0:(n - m) * old_len])
return self
def _inplace_logical_helper(self, bs, f):
@@ -2308,7 +2338,7 @@
"""Read some bits from the bitstring and return newly constructed
bitstring."""
return self._slice(start, start + length)
- def _validate_slice(self, start, end):
+ def _validate_slice_msb0(self, start, end):
"""Validate start and end and return them as positive bit positions."""
if start is None:
start = 0
@@ -2326,6 +2356,10 @@
raise ValueError("end must not be less than start.")
return start, end
+ def _validate_slice_lsb0(self, start, end):
+ start, end = self._validate_slice_msb0(start, end)
+ return self.len - end, self.len - start
+
def unpack(self, fmt, **kwargs):
"""Interpret the whole bitstring using fmt and return list.
@@ -2478,13 +2512,7 @@
# Not found, return empty tuple
return ()
- def _find_lsb0(self, bs, start=None, end=None, bytealigned=None):
- bs = Bits(bs)
- p = self.rfind(bs, start, end, bytealigned)
- if p:
- return (self.len - p[0] - bs.length,)
-
- def _find_msb0(self, bs, start=None, end=None, bytealigned=None):
+ def find(self, bs, start=None, end=None, bytealigned=None):
"""Find first occurrence of substring bs.
Returns a single item tuple with the bit position if found, or an
@@ -2505,6 +2533,16 @@
(6,)
"""
+ return self._find(bs, start, end, bytealigned)
+
+ def _find_lsb0(self, bs, start=None, end=None, bytealigned=None):
+ bs = Bits(bs)
+ start, end = self._validate_slice_lsb0(start, end)
+ p = self.rfind(bs, start, end, bytealigned)
+ if p:
+ return (self.len - p[0] - bs.length,)
+
+ def _find_msb0(self, bs, start=None, end=None, bytealigned=None):
bs = Bits(bs)
if not bs.len:
raise ValueError("Cannot find an empty bitstring.")
@@ -2706,11 +2744,11 @@
s = self.__class__()
i = iter(sequence)
try:
- s._append(Bits(next(i)))
+ s._addright(Bits(next(i)))
while True:
n = next(i)
- s._append(self)
- s._append(Bits(n))
+ s._addright(self)
+ s._addright(Bits(n))
except StopIteration:
pass
return s
@@ -2736,7 +2774,7 @@
"""
# If the bitstring is file based then we don't want to read it all
# in to memory.
- chunksize = 1024 * 1024 # 1 MB chunks
+ chunksize = 1024 * 1024 # 1 MiB chunks
if not self._offset:
a = 0
bytelen = self._datastore.bytelength
@@ -2771,7 +2809,7 @@
"""
prefix = Bits(prefix)
- start, end = self._validate_slice(start, end)
+ start, end = self._validate_slice_msb0(start, end) # the _slice deals
with msb0/lsb0
if end < start + prefix.len:
return False
end = start + prefix.len
@@ -2954,59 +2992,7 @@
""")
-# Dictionary that maps token names to the function that reads them.
-name_to_read = {'uint': Bits._readuint,
- 'uintle': Bits._readuintle,
- 'uintbe': Bits._readuintbe,
- 'uintne': Bits._readuintne,
- 'int': Bits._readint,
- 'intle': Bits._readintle,
- 'intbe': Bits._readintbe,
- 'intne': Bits._readintne,
- 'float': Bits._readfloat,
- 'floatbe': Bits._readfloat, # floatbe is a synonym for float
- 'floatle': Bits._readfloatle,
- 'floatne': Bits._readfloatne,
- 'hex': Bits._readhex,
- 'oct': Bits._readoct,
- 'bin': Bits._readbin,
- 'bits': Bits._readbits,
- 'bytes': Bits._readbytes,
- 'ue': Bits._readue,
- 'se': Bits._readse,
- 'uie': Bits._readuie,
- 'sie': Bits._readsie,
- 'bool': Bits._readbool,
- }
-
-# Dictionaries for mapping init keywords with init functions.
-init_with_length_and_offset = {'bytes': Bits._setbytes_safe,
- 'filename': Bits._setfile,
- }
-
-init_with_length_only = {'uint': Bits._setuint,
- 'int': Bits._setint,
- 'float': Bits._setfloat,
- 'uintbe': Bits._setuintbe,
- 'intbe': Bits._setintbe,
- 'floatbe': Bits._setfloat,
- 'uintle': Bits._setuintle,
- 'intle': Bits._setintle,
- 'floatle': Bits._setfloatle,
- 'uintne': Bits._setuintne,
- 'intne': Bits._setintne,
- 'floatne': Bits._setfloatne,
- }
-init_without_length_or_offset = {'bin': Bits._setbin_safe,
- 'hex': Bits._sethex,
- 'oct': Bits._setoct,
- 'ue': Bits._setue,
- 'se': Bits._setse,
- 'uie': Bits._setuie,
- 'sie': Bits._setsie,
- 'bool': Bits._setbool,
- }
class BitArray(Bits):
@@ -3140,7 +3126,7 @@
bs -- the bitstring to append.
"""
- self.append(bs)
+ self._append(bs)
return self
def __copy__(self):
@@ -3176,7 +3162,6 @@
raise ValueError("Cannot set a single bit with integer
{0}.".format(value))
value = Bits(value)
if value.len == 1:
- # TODO: this can't be optimal
if value[0]:
self._set(key)
else:
@@ -3199,7 +3184,6 @@
# value rather than initialise a new bitstring of that length.
if not isinstance(value, numbers.Integral):
try:
- # TODO: Better way than calling constructor here?
value = Bits(value)
except TypeError:
raise TypeError("Bitstring, integer or string expected. "
@@ -3277,7 +3261,6 @@
temp.__delitem__(key)
self._setbin_unsafe(''.join(temp))
return
- stop = key.stop
if key.start is not None:
start = key.start
if key.start < 0:
@@ -3394,7 +3377,7 @@
lengths = [s.len for s in sections]
if len(lengths) == 1:
# Didn't find anything to replace.
- return 0 # no replacements done
+ return 0 # no replacements done
if new is self:
# Prevent self assignment woes
new = copy.copy(self)
@@ -3444,7 +3427,7 @@
try:
pos = self._pos
except AttributeError:
- raise TypeError("insert require a bit position for this type.")
+ raise TypeError("insert needs a bit position specified when
used on a BitArray.")
if pos < 0:
pos += self.len
if not 0 <= pos <= self.len:
@@ -3467,7 +3450,7 @@
try:
pos = self._pos
except AttributeError:
- raise TypeError("overwrite require a bit position for this
type.")
+ raise TypeError("overwrite needs a bit position specified when
used on a BitArray.")
if pos < 0:
pos += self.len
if pos < 0 or pos + bs.len > self.len:
@@ -3484,8 +3467,6 @@
bs -- The bitstring to append.
"""
- # The offset is a hint to make bs easily appendable.
- bs = self._converttobitstring(bs, offset=(self.len + self._offset) % 8)
self._append(bs)
def prepend(self, bs):
@@ -3494,9 +3475,17 @@
bs -- The bitstring to prepend.
"""
- bs = Bits(bs)
self._prepend(bs)
+ def _append_msb0(self, bs):
+ # The offset is a hint to make bs easily appendable.
+ bs = self._converttobitstring(bs, offset=(self.len + self._offset) % 8)
+ self._addright(bs)
+
+ def _append_lsb0(self, bs):
+ bs = Bits(bs)
+ self._addleft(bs)
+
def reverse(self, start=None, end=None):
"""Reverse bits in-place.
@@ -3583,8 +3572,11 @@
if not self.len:
raise Error("Cannot rotate an empty bitstring.")
if bits < 0:
- raise ValueError("Cannot rotate right by negative amount.")
- start, end = self._validate_slice(start, end)
+ raise ValueError("Cannot rotate by negative amount.")
+ self._ror(bits, start, end)
+
+ def _ror_msb0(self, bits, start=None, end=None):
+ start, end = self._validate_slice_msb0(start, end) # the _slice deals
with msb0/lsb0
bits %= (end - start)
if not bits:
return
@@ -3605,8 +3597,11 @@
if not self.len:
raise Error("Cannot rotate an empty bitstring.")
if bits < 0:
- raise ValueError("Cannot rotate left by negative amount.")
- start, end = self._validate_slice(start, end)
+ raise ValueError("Cannot rotate by negative amount.")
+ self._rol(bits, start, end)
+
+ def _rol_msb0(self, bits, start=None, end=None):
+ start, end = self._validate_slice_msb0(start, end)
bits %= (end - start)
if not bits:
return
@@ -3811,9 +3806,9 @@
"""
- __slots__ = ('_pos')
+ __slots__ = ('_pos',)
- def __init__(self, auto=None, length=None, offset=None, **kwargs):
+ def __init__(self, auto=None, length=None, offset=None, pos=0, **kwargs):
"""Either specify an 'auto' initialiser:
auto -- a string of comma separated tokens, an integer, a file object,
a bytearray, a boolean iterable or another bitstring.
@@ -3848,13 +3843,17 @@
offset -- bit offset to the data. These offset bits are
ignored and this is intended for use when
initialising using 'bytes' or 'filename'.
+ pos -- Initial bit position, defaults to 0.
"""
- self._pos = 0
+ pass
- def __new__(cls, auto=None, length=None, offset=None, **kwargs):
+ def __new__(cls, auto=None, length=None, offset=None, pos=0, **kwargs):
x = super(ConstBitStream, cls).__new__(cls)
x._initialise(auto, length, offset, **kwargs)
+ x._pos = x._datastore.bitlength + pos if pos < 0 else pos
+ if x._pos < 0 or x._pos > x._datastore.bitlength:
+ raise CreationError("Cannot set pos to {0} when length is
{1}".format(pos, x._datastore.bitlength))
return x
def _setbytepos(self, bytepos):
@@ -3868,7 +3867,7 @@
return self._pos // 8
def _setbitpos(self, pos):
- """Move to absolute postion bit in bitstream."""
+ """Move to absolute position bit in bitstream."""
if pos < 0:
raise ValueError("Bit position cannot be negative.")
if pos > self.len:
@@ -4069,9 +4068,6 @@
""")
-
-
-
class BitStream(ConstBitStream, BitArray):
"""A container or stream holding a mutable sequence of bits
@@ -4150,7 +4146,7 @@
# As BitStream objects are mutable, we shouldn't allow them to be hashed.
__hash__ = None
- def __init__(self, auto=None, length=None, offset=None, **kwargs):
+ def __init__(self, auto=None, length=None, offset=None, pos=0, **kwargs):
"""Either specify an 'auto' initialiser:
auto -- a string of comma separated tokens, an integer, a file object,
a bytearray, a boolean iterable or another bitstring.
@@ -4185,19 +4181,20 @@
offset -- bit offset to the data. These offset bits are
ignored and this is intended for use when
initialising using 'bytes' or 'filename'.
+ pos -- Initial bit position, defaults to 0.
"""
- self._pos = 0
# For mutable BitStreams we always read in files to memory:
if not isinstance(self._datastore, (ByteStore, ConstByteStore)):
self._ensureinmemory()
- def __new__(cls, auto=None, length=None, offset=None, **kwargs):
+ def __new__(cls, auto=None, length=None, offset=None, pos=0, **kwargs):
x = super(BitStream, cls).__new__(cls)
- y = ConstBitStream.__new__(BitStream, auto, length, offset, **kwargs)
+ y = ConstBitStream.__new__(BitStream, auto, length, offset, pos,
**kwargs)
x._datastore = ByteStore(y._datastore._rawarray[:],
y._datastore.bitlength,
y._datastore.offset)
+ x._pos = y._pos
return x
def __copy__(self):
@@ -4221,7 +4218,7 @@
"""
bs = self._converttobitstring(bs)
- self._prepend(bs)
+ self._addleft(bs)
self._pos += bs.len
@@ -4281,14 +4278,14 @@
length = kwargs[length]
# Also if we just have a dictionary name then we want to use it
if name in kwargs and length is None and value is None:
- s.append(kwargs[name])
+ s._append(kwargs[name])
continue
if length is not None:
length = int(length)
if value is None and name != 'pad':
# Take the next value from the ones provided
value = next(value_iter)
- s._append(BitStream._init_with_token(name, length, value))
+ s._addright(BitStream._init_with_token(name, length, value))
except StopIteration:
raise CreationError("Not enough parameters present to pack according
to the "
"format. {0} values are needed.", len(tokens))
@@ -4299,44 +4296,123 @@
return s
raise CreationError("Too many parameters present to pack according to the
format.")
+
# Whether to label the Least Significant Bit as bit 0. Default is False.
Experimental feature.
_lsb0 = False
-def _switch_lsb0_methods():
- if _lsb0:
+# Dictionary that maps token names to the function that reads them. Is set in
next function.
+name_to_read = {}
+
+
+def _switch_lsb0_methods(lsb0):
+ global _lsb0
+ _lsb0 = lsb0
+ if lsb0:
ConstByteStore.getbit = ConstByteStore._getbit_lsb0
- Bits.find = Bits._find_lsb0
+ Bits._find = Bits._find_lsb0
Bits._slice = Bits._slice_lsb0
BitArray._overwrite = BitArray._overwrite_lsb0
BitArray._insert = BitArray._insert_lsb0
BitArray._delete = BitArray._delete_lsb0
+ BitArray._ror = BitArray._rol_msb0
+ BitArray._rol = BitArray._ror_msb0
ByteStore.setbit = ByteStore._setbit_lsb0
ByteStore.unsetbit = ByteStore._unsetbit_lsb0
ByteStore.invertbit = ByteStore._invertbit_lsb0
+ BitArray._append = BitArray._append_lsb0
+ BitArray._prepend = BitArray._append_msb0 # An LSB0 prepend is an
MSB0 append
+ Bits._readuint = Bits._readuint_lsb0
+ Bits._truncatestart = Bits._truncateright
+ Bits._truncateend = Bits._truncateleft
+ Bits._validate_slice = Bits._validate_slice_lsb0
else:
ConstByteStore.getbit = ConstByteStore._getbit_msb0
- Bits.find = Bits._find_msb0
+ Bits._find = Bits._find_msb0
Bits._slice = Bits._slice_msb0
BitArray._overwrite = BitArray._overwrite_msb0
BitArray._insert = BitArray._insert_msb0
BitArray._delete = BitArray._delete_msb0
+ BitArray._ror = BitArray._ror_msb0
+ BitArray._rol = BitArray._rol_msb0
ByteStore.setbit = ByteStore._setbit_msb0
ByteStore.unsetbit = ByteStore._unsetbit_msb0
ByteStore.invertbit = ByteStore._invertbit_msb0
+ BitArray._append = BitArray._append_msb0
+ BitArray._prepend = BitArray._append_lsb0
+ Bits._readuint = Bits._readuint_msb0
+ Bits._truncatestart = Bits._truncateleft
+ Bits._truncateend = Bits._truncateright
+ Bits._validate_slice = Bits._validate_slice_msb0
+
+ global name_to_read
+ name_to_read = {'uint': Bits._readuint,
+ 'uintle': Bits._readuintle,
+ 'uintbe': Bits._readuintbe,
+ 'uintne': Bits._readuintne,
+ 'int': Bits._readint,
+ 'intle': Bits._readintle,
+ 'intbe': Bits._readintbe,
+ 'intne': Bits._readintne,
+ 'float': Bits._readfloat,
+ 'floatbe': Bits._readfloat, # floatbe is a synonym for
float
+ 'floatle': Bits._readfloatle,
+ 'floatne': Bits._readfloatne,
+ 'hex': Bits._readhex,
+ 'oct': Bits._readoct,
+ 'bin': Bits._readbin,
+ 'bits': Bits._readbits,
+ 'bytes': Bits._readbytes,
+ 'ue': Bits._readue,
+ 'se': Bits._readse,
+ 'uie': Bits._readuie,
+ 'sie': Bits._readsie,
+ 'bool': Bits._readbool,
+ }
+
def set_lsb0(v=True):
"""Experimental method changing the bit numbering so that the least
significant bit is bit 0"""
- global _lsb0
- _lsb0 = bool(v)
- _switch_lsb0_methods()
+ _switch_lsb0_methods(v)
+
def set_msb0(v=True):
"""Experimental method to reset the bit numbering so that the most
significant bit is bit 0"""
- global _lsb0
- _lsb0 = not bool(v)
- _switch_lsb0_methods()
+ set_lsb0(not v)
+
+
+# Initialise the default behaviour
+set_msb0()
+
+
+# Dictionaries for mapping init keywords with init functions.
+init_with_length_and_offset = {'bytes': Bits._setbytes_safe,
+ 'filename': Bits._setfile,
+ }
+
+init_with_length_only = {'uint': Bits._setuint,
+ 'int': Bits._setint,
+ 'float': Bits._setfloat,
+ 'uintbe': Bits._setuintbe,
+ 'intbe': Bits._setintbe,
+ 'floatbe': Bits._setfloat,
+ 'uintle': Bits._setuintle,
+ 'intle': Bits._setintle,
+ 'floatle': Bits._setfloatle,
+ 'uintne': Bits._setuintne,
+ 'intne': Bits._setintne,
+ 'floatne': Bits._setfloatne,
+ }
+
+init_without_length_or_offset = {'bin': Bits._setbin_safe,
+ 'hex': Bits._sethex,
+ 'oct': Bits._setoct,
+ 'ue': Bits._setue,
+ 'se': Bits._setse,
+ 'uie': Bits._setuie,
+ 'sie': Bits._setsie,
+ 'bool': Bits._setbool,
+ }
-_switch_lsb0_methods()
# Aliases for backward compatibility
ConstBitArray = Bits
@@ -4346,32 +4422,33 @@
'Bits', 'BitString', 'pack', 'Error', 'ReadError', 'InterpretError',
'ByteAlignError', 'CreationError', 'bytealigned', 'set_lsb0',
'set_msb0']
-if __name__ == '__main__':
- """Create and interpret a bitstring from command-line parameters.
-
- Command-line parameters are concatenated and a bitstring created
- from them. If the final parameter is either an interpretation string
- or ends with a '.' followed by an interpretation string then that
- interpretation of the bitstring will be used when printing it.
-
- Typical usage might be invoking the Python module from a console
- as a one-off calculation:
-
- $ python -m bitstring int:16=-400
- 0xfe70
- $ python -m bitstring float:32=0.2 bin
- 00111110010011001100110011001101
- $ python -m bitstring 0xff 3*0b01,0b11 uint
- 65367
- $ python -m bitstring hex=01, uint:12=352.hex
- 01160
-
- This feature is experimental and is subject to change or removal.
- """
+def main():
# check if final parameter is an interpretation string
fp = sys.argv[-1]
- if fp in name_to_read.keys():
+ if fp == '--help' or len(sys.argv) == 1:
+ print("""Create and interpret a bitstring from command-line parameters.
+
+Command-line parameters are concatenated and a bitstring created
+from them. If the final parameter is either an interpretation string
+or ends with a '.' followed by an interpretation string then that
+interpretation of the bitstring will be used when printing it.
+
+Typical usage might be invoking the Python module from a console
+as a one-off calculation:
+
+$ python -m bitstring int:16=-400
+0xfe70
+$ python -m bitstring float:32=0.2 bin
+00111110010011001100110011001101
+$ python -m bitstring 0xff 3*0b01,0b11 uint
+65367
+$ python -m bitstring hex=01, uint:12=352.hex
+01160
+
+This feature is experimental and is subject to change or removal.
+ """)
+ elif fp in name_to_read.keys():
# concatenate all other parameters and interpret using the final one
b1 = Bits(','.join(sys.argv[1: -1]))
print(b1._readtoken(fp, 0, b1.__len__())[0])
@@ -4386,3 +4463,7 @@
# No interpretation - just use default print
b1 = Bits(','.join(sys.argv[1:]))
print(b1)
+
+
+if __name__ == '__main__':
+ main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/bitstream.rst
new/bitstring-bitstring-3.1.9/doc/bitstream.rst
--- old/bitstring-bitstring-3.1.7/doc/bitstream.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/bitstream.rst 2021-07-20
19:37:11.000000000 +0200
@@ -3,9 +3,9 @@
The BitStream class
-------------------
-.. class:: BitStream([auto, length, offset, **kwargs])
+.. class:: BitStream([auto, length, offset, pos, **kwargs])
- Both the :class:`BitArray` and the :class:`ConstBitStream` classes are
base classes for :class:`BitStream` and so all of their methods are also
available for :class:`BitStream` objects. The initialiser is also the same as
for :class:`Bits` and so won't be repeated here.
+ Both the :class:`BitArray` and the :class:`ConstBitStream` classes are
base classes for :class:`BitStream` and so all of their methods are also
available for :class:`BitStream` objects. The initialiser is the same as for
:class:`ConstBitStream`.
A :class:`BitStream` is a mutable container of bits with methods and
properties that allow it to be parsed as a stream of bits. There are no
additional methods or properties in this class - see its base classes
(:class:`Bits`, :class:`BitArray` and :class:`ConstBitStream`) for details.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/constbitstream.rst
new/bitstring-bitstring-3.1.9/doc/constbitstream.rst
--- old/bitstring-bitstring-3.1.7/doc/constbitstream.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/constbitstream.rst 2021-07-20
19:37:11.000000000 +0200
@@ -3,9 +3,9 @@
The ConstBitStream class
------------------------
-.. class:: ConstBitStream([auto, length, offset, **kwargs])
+.. class:: ConstBitStream([auto, length, offset, pos, **kwargs])
- The :class:`Bits` class is the base class for :class:`ConstBitStream` and
so all of its methods are also available for :class:`ConstBitStream` objects.
The initialiser is also the same as for :class:`Bits` and so won't be repeated
here.
+ The :class:`Bits` class is the base class for :class:`ConstBitStream` and
so all of its methods are also available for :class:`ConstBitStream` objects.
The initialiser is the same as for :class:`Bits` except that an initial bit
position :attr:`pos` can be given (defaults to 0).
A :class:`ConstBitStream` is a :class:`Bits` with added methods and
properties that allow it to be parsed as a stream of bits.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/creation.rst
new/bitstring-bitstring-3.1.9/doc/creation.rst
--- old/bitstring-bitstring-3.1.7/doc/creation.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/creation.rst 2021-07-20
19:37:11.000000000 +0200
@@ -5,7 +5,7 @@
Creation
========
-You can create bitstrings in a variety of ways. Internally they are stored as
byte arrays, which means that no space is wasted, and a bitstring containing
10MB of binary data will only take up 10MB of memory.
+You can create bitstrings in a variety of ways. Internally they are stored as
byte arrays, which means that no space is wasted, and a bitstring containing
10MiB of binary data will only take up 10MiB of memory.
The bitstring classes
---------------------
@@ -27,7 +27,7 @@
* If you need to change the contents of the bitstring then you must use
:class:`BitArray` or :class:`BitStream`. Truncating, replacing, inserting,
appending etc. are not available for the const classes.
* If you need to use a bitstring as the key in a dictionary or as a member of
a ``set`` then you must use :class:`Bits` or a :class:`ConstBitStream`. As
:class:`BitArray` and :class:`BitStream` objects are mutable they do not
support hashing and so cannot be used in these ways.
-* If you are creating directly from a file then a :class:`BitArray` or
:class:`BitStream` will read the file into memory whereas a :class:`Bits` or
:class:`ConstBitStream` will not, so using the const classes allows extremely
large files to be examined.
+* If you are creating directly from a file then a :class:`BitArray` or
:class:`BitStream` will read the whole file into memory whereas a :class:`Bits`
or :class:`ConstBitStream` will not, so using the const classes allows
extremely large files to be examined.
* If you don't need the extra functionality of a particular class then the
simpler ones might be faster and more memory efficient. The fastest and most
memory efficient class is :class:`Bits`.
The :class:`Bits` class is the base class of the other three class. This means
that ``isinstance(s, Bits)`` will be true if ``s`` is an instance of any of the
four classes.
@@ -38,7 +38,7 @@
When initialising a bitstring you need to specify at most one initialiser.
These will be explained in full below, but briefly they are:
* ``auto`` : Either a specially formatted string, a list or tuple, a file
object, integer, bytearray, array, bytes or another bitstring.
-* ``bytes`` : A ``bytes`` object (a ``str`` in Python 2), for example read
from a binary file.
+* ``bytes`` : A ``bytes`` object (a ``str`` in Python 2.7), for example read
from a binary file.
* ``hex``, ``oct``, ``bin``: Hexadecimal, octal or binary strings.
* ``int``, ``uint``: Signed or unsigned bit-wise big-endian binary integers.
* ``intle``, ``uintle``: Signed or unsigned byte-wise little-endian binary
integers.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/examples.rst
new/bitstring-bitstring-3.1.9/doc/examples.rst
--- old/bitstring-bitstring-3.1.7/doc/examples.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/examples.rst 2021-07-20
19:37:11.000000000 +0200
@@ -74,21 +74,4 @@
>>> print(sps.constraint_flags)
[0, 0, 0, 1]
-Sieve of Eratosthenes
----------------------
-
-This classic (though inefficient) method of calculating prime numbers uses a
bitstring to store whether each bit position represents a prime number. This
takes much less memory than an ordinary array. ::
-
-
- def prime_sieve(top=1000000):
- b = BitArray(top) # bitstring of '0' bits
- for i in xrange(2, top):
- if not b[i]:
- yield i
- # i is prime, so set all its multiples to '1'.
- b.set(True, xrange(i*i, top, i))
-
-
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/index.rst
new/bitstring-bitstring-3.1.9/doc/index.rst
--- old/bitstring-bitstring-3.1.7/doc/index.rst 2020-05-05 22:05:19.000000000
+0200
+++ new/bitstring-bitstring-3.1.9/doc/index.rst 2021-07-20 19:37:11.000000000
+0200
@@ -7,7 +7,7 @@
Features
--------
-* Supports Python 2.7 and Python 3.
+* Supports Python 2.7 and Python 3.6 and later.
* Rich API - chances are that whatever you want to do there's a simple and
elegant way of doing it.
* Bit level slicing, joining, searching, replacing and more.
* Create bitstrings from hex, octal, binary, files, formatted strings, bytes,
integers and floats of different endiannesses.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/interpretation.rst
new/bitstring-bitstring-3.1.9/doc/interpretation.rst
--- old/bitstring-bitstring-3.1.7/doc/interpretation.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/interpretation.rst 2021-07-20
19:37:11.000000000 +0200
@@ -8,7 +8,7 @@
Several Python properties are used to create interpretations for the
bitstring. These properties call private functions which will calculate and
return the appropriate interpretation. These don???t change the bitstring in
any way and it remains just a collection of bits. If you use the property again
then the calculation will be repeated.
-Note that these properties can potentially be very expensive in terms of both
computation and memory requirements. For example if you have initialised a
bitstring from a 10 GB file object and ask for its binary string representation
then that string will be around 80 GB in size!
+Note that these properties can potentially be very expensive in terms of both
computation and memory requirements. For example if you have initialised a
bitstring from a 10 GiB file object and ask for its binary string
representation then that string will be around 80 GiB in size!
For the properties described below we will use these::
@@ -99,7 +99,7 @@
bytes
^^^^^
-A common need is to retrieve the raw bytes from a bitstring for further
processing or for writing to a file. For this use the :attr:`~Bits.bytes`
interpretation, which returns a ``bytes`` object (which is equivalent to an
ordinary ``str`` in Python 2.6/2.7).
+A common need is to retrieve the raw bytes from a bitstring for further
processing or for writing to a file. For this use the :attr:`~Bits.bytes`
interpretation, which returns a ``bytes`` object (which is equivalent to an
ordinary ``str`` in Python 2.7).
If the length of the bitstring isn't a multiple of eight then a
:exc:`ValueError` will be raised. This is because there isn't an unequivocal
representation as ``bytes``. You may prefer to use the method
:meth:`~Bits.tobytes` as this will be pad with between one and seven zero bits
up to a byte boundary if necessary. ::
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/introduction.rst
new/bitstring-bitstring-3.1.9/doc/introduction.rst
--- old/bitstring-bitstring-3.1.7/doc/introduction.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/introduction.rst 2021-07-20
19:37:11.000000000 +0200
@@ -6,7 +6,7 @@
While it is not difficult to manipulate binary data in Python, for example
using the :mod:`struct` and :mod:`array` modules, it can be quite fiddly and
time consuming even for quite small tasks, especially if you are not dealing
only with whole-byte data.
-The bitstring module provides four classes, :class:`BitStream`,
:class:`BitArray`, :class:`ConstBitStream` and :class:`Bits`, instances of
which can be constructed from integers, floats, hex, octal, binary, strings or
files, but they all just represent a string of binary digits. I shall use the
general term 'bitstring' when referring generically to any of the classes, and
use the class names for parts that apply to only one or another.
+The bitstring module provides four classes, :class:`BitStream`,
:class:`BitArray`, :class:`ConstBitStream` and :class:`Bits`, instances of
which can be constructed from integers, floats, hex, octal, binary, strings or
files, but they all just represent a string of binary digits. I shall use the
term 'bitstring' when referring generically to any of the classes, and use the
class names for parts that apply to only one or another.
:class:`BitArray` objects can be sliced, joined, reversed, inserted into,
overwritten, packed, unpacked etc. with simple functions or slice notation.
:class:`BitStream` objects can also be read from, searched in, and navigated
in, similar to a file or stream.
@@ -75,11 +75,11 @@
python setup.py install
-You might need to add a 'sudo' to the start of that command, depending on your
system. This will copy the source files to your Python installation's
``site-packages`` directory.
+You might need to add a 'sudo' to the start of that command, depending on your
system, if you're not using a virtualenv. This will copy the source files to
your Python installation's ``site-packages`` directory.
The module comes with comprehensive unit tests. To run them yourself use your
favourite unit test running method, mine is::
python -m unittest discover
-which when run in the `test` folder should run all the tests (almost 500) and
say OK. If tests fail then either your version of Python isn't supported (you
need Python 2.7 or 3.x) or something unexpected has happened - in which case
please tell me about it.
+which when run in the `test` folder should run all the tests (over 500) and
say OK. If tests fail then either your version of Python isn't supported (you
need Python 2.7 or 3.6+) or something unexpected has happened - in which case
please tell me about it.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/misc.rst
new/bitstring-bitstring-3.1.9/doc/misc.rst
--- old/bitstring-bitstring-3.1.7/doc/misc.rst 2020-05-05 22:05:19.000000000
+0200
+++ new/bitstring-bitstring-3.1.9/doc/misc.rst 2021-07-20 19:37:11.000000000
+0200
@@ -39,7 +39,7 @@
Returns the byte data contained in the bitstring as a ``bytes`` object
(equivalent to a ``str`` if you're using Python 2.7). This differs from using
the plain :attr:`~Bits.bytes` property in that if the bitstring isn't a whole
number of bytes long then it will be made so by appending up to seven zero
bits. ::
>>> BitArray('0b1').tobytes()
- '\x80'
+ b'\x80'
``tofile``
^^^^^^^^^^
@@ -82,7 +82,7 @@
This implements the :func:`len` function and returns the length of the
bitstring in bits.
-It's recommended that you use the :attr:`~Bits.len` property instead of the
function as a limitation of Python means that the function will raise an
:exc:`OverflowError` if the bitstring has more than ``sys.maxsize`` elements
(that's typically 256MB of data with 32-bit Python).
+It's recommended that you use the :attr:`~Bits.len` property instead of the
function if you're using a 32-bit Python installation as the len function will
raise an :exc:`OverflowError` if the bitstring has more than ``sys.maxsize``
elements (that's typically 256MiB of data with 32-bit Python).
There's not much more to say really, except to emphasise that it is always in
bits and never bytes. ::
@@ -110,7 +110,7 @@
``__eq__ / __ne__``
^^^^^^^^^^^^^^^^^^^
-The equality of two bitstring objects is determined by their binary
representations being equal. If you have a different criterion you wish to use
then code it explicitly, for example ``a.int == b.int`` could be true even if
``a == b`` wasn't (as they could be different lengths). ::
+The equality of two bitstring objects is determined by their binary
representations being equal. If you have a different criterion you wish to use
then code it explicitly, for example ``a.int == b.int`` could be true even if
``a == b`` wasn't (as they could be different lengths). ::
>>> BitArray('0b0010') == '0x2'
True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/reading.rst
new/bitstring-bitstring-3.1.9/doc/reading.rst
--- old/bitstring-bitstring-3.1.7/doc/reading.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/reading.rst 2021-07-20
19:37:11.000000000 +0200
@@ -11,7 +11,7 @@
The :class:`BitStream` and :class:`ConstBitStream` classes contain number of
methods for reading the bitstring as if it were a file or stream. Depending on
how it was constructed the bitstream might actually be contained in a file
rather than stored in memory, but these methods work for either case.
-In order to behave like a file or stream, every bitstream has a property
:attr:`~ConstBitStream.pos` which is the current position from which reads
occur. :attr:`~ConstBitStream.pos` can range from zero (its value on
construction) to the length of the bitstream, a position from which all reads
will fail as it is past the last bit. Note that the :attr:`~ConstBitStream.pos`
property isn't considered a part of the bitstream's identity; this allows it to
vary for immutable :class:`ConstBitStream` objects and means that it doesn't
affect equality or hash values.
+In order to behave like a file or stream, every bitstream has a property
:attr:`~ConstBitStream.pos` which is the current position from which reads
occur. :attr:`~ConstBitStream.pos` can range from zero (its default value on
construction) to the length of the bitstream, a position from which all reads
will fail as it is past the last bit. Note that the :attr:`~ConstBitStream.pos`
property isn't considered a part of the bitstream's identity; this allows it to
vary for immutable :class:`ConstBitStream` objects and means that it doesn't
affect equality or hash values.
The property :attr:`~ConstBitStream.bytepos` is also available, and is useful
if you are only dealing with byte data and don't want to always have to divide
the bit position by eight. Note that if you try to use
:attr:`~ConstBitStream.bytepos` and the bitstring isn't byte aligned (i.e.
:attr:`~ConstBitStream.pos` isn't a multiple of 8) then a :exc:`ByteAlignError`
exception will be raised.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/doc/walkthrough.rst
new/bitstring-bitstring-3.1.9/doc/walkthrough.rst
--- old/bitstring-bitstring-3.1.7/doc/walkthrough.rst 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/doc/walkthrough.rst 2021-07-20
19:37:11.000000000 +0200
@@ -16,7 +16,7 @@
Prerequisites
-------------
-* Python 2.7 or 3.x.
+* Python 2.7 or 3.6 or later.
* An installed bitstring module.
* A rudimentary knowledge of binary concepts.
* A little free time.
@@ -61,12 +61,12 @@
>>> b.int
-2
>>> a.bytes
- '\xff\x01'
+ b'\xff\x01'
There are a few things to note here:
* To get the different interpretations of the binary data we use properties
such as :attr:`~Bits.bin`, :attr:`~Bits.hex`, :attr:`~Bits.oct`,
:attr:`~Bits.int` and :attr:`~Bits.bytes`. You can probably guess what these
all mean, but you don't need to know quite yet. The properties are calculated
when you ask for them rather than being stored as part of the object itself.
-* The :attr:`~Bits.bytes` property returns a ``bytes`` object. This is
slightly different in Python 2.7 to Python 3 - in Python 3 you would get
``b'\xff\x01'`` returned instead.
+* The :attr:`~Bits.bytes` property returns a ``bytes`` object. This is
slightly different in Python 2.7 to Python 3 - in Python 2.7 you would get
``'\xff\x01'`` returned instead.
Great - let's try some more::
@@ -265,10 +265,10 @@
# create a BitArray with a million zero bits.
# The bits will be set to indicate that the bit position isn't prime.
has_factors = BitArray(1000000)
- for i in xrange(2, 1000000):
+ for i in range(2, 1000000):
if not has_factors[i]:
print(i)
# Set all multiples of our prime to 1.
- has_factors.set(True, xrange(i*2, 1000000, i))
+ has_factors.set(True, range(i*2, 1000000, i))
I'll leave optimising the algorithm as an exercise for the reader, but it
illustrates both bit checking and setting. One reason you might want to use a
bitstring for this purpose (instead of a plain list for example) is that the
million bits only take up a million bits in memory, whereas for a list of
integers it would be much more. Try asking for a billion elements in a list -
unless you've got some really nice hardware it will fail, whereas a billion
element bitstring only takes 125MB.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/release_notes.txt
new/bitstring-bitstring-3.1.9/release_notes.txt
--- old/bitstring-bitstring-3.1.7/release_notes.txt 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/release_notes.txt 2021-07-20
19:37:11.000000000 +0200
@@ -3,6 +3,20 @@
--------------------------------
---------------------------------------
+July 20th 2021: version 3.1.9 released
+---------------------------------------
+(version 3.1.8 was pulled due to serious issues)
+Another maintenance release.
+
+* Fixed a couple of outdated results in the readme (Issue 214).
+* Some more documentation tidying.
+* Turned off some debug code by default.
+* Fixed a couple of failing tests in different Python versions.
+* Fix for consistent pos initialisation semantics for different types.
+* Change to allow wheels to be uploaded to PyPI.
+* More work for LSB0 mode, but still not finished or documented (sorry).
+
+---------------------------------------
May 5th 2020: version 3.1.7 released
---------------------------------------
This is a maintenance release with a few bug fixes plus an experimental
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/setup.py
new/bitstring-bitstring-3.1.9/setup.py
--- old/bitstring-bitstring-3.1.7/setup.py 2020-05-05 22:05:19.000000000
+0200
+++ new/bitstring-bitstring-3.1.9/setup.py 2021-07-20 19:37:11.000000000
+0200
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+import setuptools
from distutils.core import setup
import sys
@@ -10,7 +11,7 @@
raise Exception('This version of bitstring needs Python 2.7 or later.')
setup(name='bitstring',
- version='3.1.7',
+ version='3.1.9',
description='Simple construction, analysis and modification of binary
data.',
author='Scott Griffiths',
author_email='[email protected]',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/test/test_bitarray.py
new/bitstring-bitstring-3.1.9/test/test_bitarray.py
--- old/bitstring-bitstring-3.1.7/test/test_bitarray.py 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/test/test_bitarray.py 2021-07-20
19:37:11.000000000 +0200
@@ -390,9 +390,9 @@
def testAppendingBits(self):
a = BitArray('0b111')
a.append('0b000')
- self.assertEqual(a.bin, '111000')
+ self.assertEqual(a.bin, '000111')
a += '0xabc'
- self.assertEqual(a, '0b111000, 0xabc')
+ self.assertEqual(a, '0xabc, 0b000111')
def testSettingSlice(self):
a = BitArray('0x012345678')
@@ -434,14 +434,13 @@
self.assertEqual(l, ['0x2222', '0x11ff', '0xff11', '0xff00'])
def testFind(self):
- pass
- # a = BitArray('0b10101010, 0xabcd, 0b10101010, 0x0')
- # p, = a.find('0b10101010', bytealigned=False)
- # self.assertEqual(p, 4)
- # p, = a.find('0b10101010', start=4, bytealigned=False)
- # self.assertEqual(p, 4)
- # p, = a.find('0b10101010', start=5, bytealigned=False)
- # self.assertEqual(p, 28)
+ a = BitArray('0b10101010, 0xabcd, 0b10101010, 0x0')
+ p, = a.find('0b10101010', bytealigned=False)
+ self.assertEqual(p, 4)
+ p, = a.find('0b10101010', start=4, bytealigned=False)
+ self.assertEqual(p, 4)
+ p, = a.find('0b10101010', start=5, bytealigned=False)
+ self.assertEqual(p, 22)
def testRfind(self):
pass
@@ -450,16 +449,25 @@
pass
def testSplit(self):
- pass
+ a = BitArray('0x4700004711472222')
+ l = list(a.split('0x47', bytealigned=True))
+ self.assertEqual(l, ['', '0x472222', '0x4711', '0x470000'])
def testByteSwap(self):
- pass
+ a = BitArray('0xff00ff00ff00')
+ n = a.byteswap(2, end=32, repeat=True)
+ self.assertEqual(n, 2)
+ self.assertEqual(a, '0xff0000ff00ff')
def testInsert(self):
- pass
+ a = BitArray('0x0123456')
+ a.insert('0xf', 4)
+ self.assertEqual(a, '0x012345f6')
def testOverwrite(self):
- pass
+ a = BitArray('0x00000000')
+ a.overwrite('0xdead', 4)
+ self.assertEqual(a, '0x000dead0')
def testReplace(self):
pass
@@ -468,10 +476,28 @@
pass
def testRor(self):
- pass
+ a = BitArray('0b111000')
+ a.ror(1)
+ self.assertEqual(a, '0b011100')
+ a = BitArray('0b111000')
+ a.ror(1, start=2, end=6)
+ self.assertEqual(a, '0b011100')
def testRol(self):
pass
def testSet(self):
- pass
+ a = BitArray(100)
+ a.set(1, [0, 2, 4])
+ self.assertTrue(a[0])
+ self.assertTrue(a.startswith('0b000010101'))
+ a = BitArray('0b111')
+ a.set(False, 0)
+ self.assertEqual(a, '0b110')
+
+
+class Repr(unittest.TestCase):
+
+ def testStandardRepr(self):
+ a = BitArray('0o12345')
+ self.assertEqual(repr(a), "BitArray('0b001010011100101')")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/test/test_bits.py
new/bitstring-bitstring-3.1.9/test/test_bits.py
--- old/bitstring-bitstring-3.1.7/test/test_bits.py 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/test/test_bits.py 2021-07-20
19:37:11.000000000 +0200
@@ -47,11 +47,10 @@
Bits(hex='0Xx0')
with self.assertRaises(bitstring.CreationError):
Bits(hex='-2e')
- # These really should fail, but it's awkward and not a big deal...
- # with self.assertRaises(bitstring.CreationError):
- # Bits('0x2', length=2)
- # with self.assertRaises(bitstring.CreationError):
- # Bits('0x3', offset=1)
+ with self.assertRaises(bitstring.CreationError):
+ Bits('0x2', length=2)
+ with self.assertRaises(bitstring.CreationError):
+ Bits('0x3', offset=1)
def testCreationFromBin(self):
s = Bits(bin='1010000011111111')
@@ -581,3 +580,19 @@
a = Bits('0x1234abcd')
self.assertTrue(a.endswith('0x123'))
self.assertFalse(a.endswith('0xabcd'))
+
+
+class Lsb0Interpretations(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ bitstring.set_lsb0(True)
+
+ @classmethod
+ def tearDownClass(cls):
+ bitstring.set_lsb0(False)
+
+ def testUint(self):
+ a = Bits('0x01')
+ self.assertEqual(a, '0b00000001')
+ self.assertEqual(a.uint, 1)
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/test/test_bitstream.py
new/bitstring-bitstring-3.1.9/test/test_bitstream.py
--- old/bitstring-bitstring-3.1.7/test/test_bitstream.py 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/test/test_bitstream.py 2021-07-20
19:37:11.000000000 +0200
@@ -1930,7 +1930,9 @@
a = BitStream('0b1')
self.assertEqual(repr(a), "BitStream('0b1')")
a += '0b11'
- self.assertEqual(repr(a), "BitStream('0b111')")
+ a.pos = 2
+ self.assertEqual(repr(a), "BitStream('0b111', pos=2)")
+ a.pos = 0
a += '0b1'
self.assertEqual(repr(a), "BitStream('0xf')")
a *= max
@@ -2829,10 +2831,10 @@
c = BitStream(a)
self.assertEqual(a, c)
a = ConstBitStream('0b1')
- a._append(a)
+ a._addright(a)
self.assertEqual(a, '0b11')
self.assertEqual(type(a), ConstBitStream)
- a._prepend(a)
+ a._addleft(a)
self.assertEqual(a, '0b1111')
self.assertEqual(type(a), ConstBitStream)
@@ -3991,7 +3993,11 @@
bitstring.set_msb0()
def testSimpleBitPositions(self):
- pass
+ s = BitStream('0x0000ff')
+ self.assertEqual(s.pos, 0)
+ v = s.read('uint:8')
+ self.assertEqual(v, 255)
+ self.assertEqual(s.pos, 8)
def testBitPosAfterFind(self):
pass
@@ -4009,4 +4015,21 @@
pass
def testBitPosAfterReplace(self):
- pass
\ No newline at end of file
+ pass
+
+ def testReadList(self):
+ a = BitStream('0x0123456789abcdef')
+
+ vals = a.readlist('uint:4, uint:4, uint:24, uint:12, uint:12, uint:8')
+ self.assertEqual(vals, [15, 14, 0x89abcd, 0x567, 0x234, 1])
+
+class testRepr(unittest.TestCase):
+
+ def testWithoutPos(self):
+ a = BitStream('0x12345', pos=0)
+ self.assertEqual(repr(a), "BitStream('0x12345')")
+
+ def testWithPos(self):
+ a = BitStream('0b00111', pos=-1)
+ self.assertEqual(a.pos, 4)
+ self.assertEqual(repr(a), "BitStream('0b00111', pos=4)")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/bitstring-bitstring-3.1.7/test/test_bitstring.py
new/bitstring-bitstring-3.1.9/test/test_bitstring.py
--- old/bitstring-bitstring-3.1.7/test/test_bitstring.py 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/test/test_bitstring.py 2021-07-20
19:37:11.000000000 +0200
@@ -12,7 +12,7 @@
class ModuleData(unittest.TestCase):
def testVersion(self):
- self.assertEqual(bitstring.__version__, '3.1.7')
+ self.assertEqual(bitstring.__version__, '3.1.9')
def testAll(self):
exported = ['ConstBitArray', 'ConstBitStream', 'BitStream', 'BitArray',
@@ -95,13 +95,13 @@
class LSB0(unittest.TestCase):
def testGettingAndSetting(self):
self.assertEqual(bitstring._lsb0, False)
- bitstring.set_lsb0(True)
+ bitstring.set_lsb0()
self.assertEqual(bitstring._lsb0, True)
bitstring.set_lsb0(False)
self.assertEqual(bitstring._lsb0, False)
bitstring.set_msb0(False)
self.assertEqual(bitstring._lsb0, True)
- bitstring.set_msb0(True)
+ bitstring.set_msb0()
self.assertEqual(bitstring._lsb0, False)
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/bitstring-bitstring-3.1.7/test/test_constbitstream.py
new/bitstring-bitstring-3.1.9/test/test_constbitstream.py
--- old/bitstring-bitstring-3.1.7/test/test_constbitstream.py 2020-05-05
22:05:19.000000000 +0200
+++ new/bitstring-bitstring-3.1.9/test/test_constbitstream.py 2021-07-20
19:37:11.000000000 +0200
@@ -162,4 +162,39 @@
with self.assertRaises(bitstring.CreationError):
s = CBS(f, length=9*8 + 1)
with self.assertRaises(bitstring.CreationError):
- s = CBS(f, length=9*8, offset=1)
\ No newline at end of file
+ s = CBS(f, length=9*8, offset=1)
+
+
+class CreationWithPos(unittest.TestCase):
+
+ def testDefaultCreation(self):
+ s = CBS('0xabc')
+ self.assertEqual(s.pos, 0)
+
+ def testPositivePos(self):
+ s = CBS('0xabc', pos=0)
+ self.assertEqual(s.pos, 0)
+ s = CBS('0xabc', pos=1)
+ self.assertEqual(s.pos, 1)
+ s = CBS('0xabc', pos=12)
+ self.assertEqual(s.pos, 12)
+ with self.assertRaises(bitstring.CreationError):
+ s = CBS('0xabc', pos=13)
+
+ def testNegativePos(self):
+ s = CBS('0xabc', pos=-1)
+ self.assertEqual(s.pos, 11)
+ s = CBS('0xabc', pos=-12)
+ self.assertEqual(s.pos, 0)
+ with self.assertRaises(bitstring.CreationError):
+ s = CBS('0xabc', pos=-13)
+
+ def testStringRepresentation(self):
+ s = CBS('0b110', pos=2)
+ self.assertEqual(s.__repr__(), "ConstBitStream('0b110', pos=2)")
+
+ def testStringRepresentationFromFile(self):
+ s = CBS(filename='test.m1v', pos=2001)
+ self.assertEqual(s.__repr__(), "ConstBitStream(filename='test.m1v',
length=1002400, pos=2001)")
+ s.pos = 0
+ self.assertEqual(s.__repr__(), "ConstBitStream(filename='test.m1v',
length=1002400)")
\ No newline at end of file