NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #2024 most downloaded on PyPI
Simple construction, analysis and modification of binary data.
Last release 6 months ago
10 Mar 2026
Release timing varies
gaps range from 2 weeks to 12 months
Nearly every release is documented
notes for 44 of 46 stable releases
2 versions withdrawn
withdrawn after publishing
18 years old
55 releases · first in 2009
This version adds a new optional Rust-based backend. This is turned off by default so shouldn't affect users. The new backend uses the tibs library, w
This version adds a new optional Rust-based backend. This is turned off by default so shouldn't affect users. The new backend uses the tibs library, which is by the same author as bitstring and should allow some nice optimisations as the whole stack can work together.
For now the Rust backend is about the same speed as the C backend (which uses bitarray) so there are no real advantages to use it yet. If you do want to try it then you'll need to set the BITSTRING_USE_RUST_CORE environment variable.
BITSTRING_USE_RUST_CORE=1 python your_script.py
You can check which backend is being used using bitstring.options.using_rust_core which should be False unless you've enabled it as detailed above.
The plan is to remove the C backend in version 5, which will allow lots of code simplifications and further performance improvements.
The tibs dependency is a bit experimental and difficult to test on every possible platform. If you experience any issues with installation then please file a bug report.
The only other change is explicit support for Python 3.14.
Tagging a release candidate.
One column per quarter.
Tagging a release candidate.
Updated bitarray dependency to allow for v3.x. Issue #355 .
Updated bitarray dependency to allow for v3.x. Issue #355.
A minor update, fixing a few issues and updating dependencies.
A minor update, fixing a few issues and updating dependencies.
i and I struct codes for 32-bit ints. Bug #340.More small bug fixes related to some of the new (beta) float formats.
Sometimes a ValueError was being raised instead of a ReadError . Bug #325 .
A couple more minor bug fixes.
ValueError was being raised instead of a ReadError. Bug #325.None now raises a TypeError rather than generatingfind / findall in some situations. Bug #326.AttributeError bug when combining Bits with BitStream. Bug #329.Fixing a few regressions introduced in 4.2.0.
Fixing a few regressions introduced in 4.2.0.
This release contains a fairly large refactor of how different types are managed. This shouldn't affect the end user, and the main noticeable change should be the new Dtype class, which is optional to use.
Support for 8-bit and smaller floats has been reworked and expanded. These are still a 'beta' feature.
':' is now compulsory rather than
recommended. For example use 'uint:foo' instead of 'uintfoo'.e4m3float and e5m2float formats have become the slightly modified
p4binary8 and p3binary8 formats.auto in constructors.The Array class is no longer 'beta'.
A new Dtype class can be optionally used to specify types.
The bitstring.options object is now the preferred method for changing module options.
The bitstring.lsb0 and bitstring.bytealigned variables are now deprecated, use
bitstring.options.lsb0 and bitstring.options.bytealigned instead.
New fromstring method as another way to create bitstrings from formatted strings.
Instead of relying on the auto parameter you can now optionally use fromstring.
>>> s1 = BitArray('u24=1000') # This is still fine.
>>> s2 = BitArray.fromstring('u24=1000') # This may be clearer and more efficient.
More types can now be pretty printed. For example integer and float formats can be used.
>>> s.pp('u15, bin')
Pretty printing is now prettier - optional terminal colours added.
A range of 8-bit, 6-bit and even 4-bit float formats added (beta):
p3binary8: IEEE 8-bit floating point with 3 bit precision.p4binary8: IEEE 8-bit floating point with 4 bit precision.e5m2mxfp: OCP 8-bit floating point with 3 bit precision.e4m3mxfp: OCP 8-bit floating point with 4 bit precision.e2m3mxfp: OCP 6-bit floating point with 4 bit precision.e3m2mxfp: OCP 6-bit floating point with 3 bit precision.e2m1mxfp: OCP 4-bit floating point with 2 bit precision.e8m0mxfp: OCP 8-bit unsigned floating point designed to scale the other formats.mxint: OCP 8-bit floating point that is a scaled integer representation.Performance improvements.
The bitstring.lsb0 and bitstring.bytealigned variables are now deprecated, use bitstring.options.lsb0 and bitstring.options.bytealigned instead.
This release contains a fairly large refactor of how different types are managed. This
shouldn't affect the end user, and the main noticeable change should be the new Dtype
class, which is optional to use.
Support for 8-bit and smaller floats has been reworked and expanded. These are still
a 'beta' feature.
Backwardly incompatible changes:
'uint:foo' instead of 'uintfoo'.auto in constructors.Other changes:
The Array class is no longer 'beta'.
A new Dtype class can be optionally used to specify types.
The bitstring.options object is now the preferred method for changing module options.
The bitstring.lsb0 and bitstring.bytealigned variables are now deprecated, use
bitstring.options.lsb0 and bitstring.options.bytealigned instead.
New fromstring method as another way to create bitstrings from formatted strings.
Instead of relying on the auto parameter you can now optionally use fromstring.
>>> s1 = BitArray('u24=1000') # This is still fine
>>> s2 = BitArray.fromstring('u24=1000') # This may be clearer and more efficient.
>>> s.pp('u15, bin')
Pretty printing is now prettier - optional terminal colours added.
A range of 8-bit, 6-bit and even 4-bit float formats added (beta):
p3binary8: IEEE 8-bit floating point with 3 bit precision.
p4binary8: IEEE 8-bit floating point with 4 bit precision.
e5m2mxfp: OCP 8-bit floating point with 3 bit precision.
e4m3mxfp: OCP 8-bit floating point with 4 bit precision.
e2m3mxfp: OCP 6-bit floating point with 4 bit precision.
e3m2mxfp: OCP 6-bit floating point with 3 bit precision.
e2m1mxfp: OCP 4-bit floating point with 2 bit precision.
e8m0mxfp: OCP 8-bit unsigned floating point designed to scale the other formats.
mxint: OCP 8-bit floating point that is a scaled integer representation.
Performance improvements.
Nothing published for this version
Nothing published for this version
Fixing a regression introduced in 4.1.3
Fixing a regression introduced in 4.1.3
A maintenance release, with some changes to the beta features introduced in 4.1.
A maintenance release, with some changes to the beta features introduced in 4.1.
Another maintenance release. Once again some small changes to the 'beta' Array class, plus new Array functionality.
Another maintenance release. Once again some small changes to the 'beta' Array class, plus new Array functionality.
== will now return an Array (see above item).A maintenance release, with some changes to the Array class which is still in 'beta'.
A maintenance release, with some changes to the Array class which is still in 'beta'.
A maintenance release, with some changes to the Array class which is still in beta.
">=2.8.0, <3.0.0" rather than a specific version. Bug #283.+ operator. Use the extend method instead.Array.count() can now count float('nan') values for floating point types.This has turned into a surprisingly big release, with a major refactor and a brand-new class (the first for 12 years!)
There are also a couple of small possibly breaking changes detailed below, in particular 'auto' initialising bitstrings from integers is now disallowed.
The major weakness of bitstring has been its poor performance for computationally intensive tasks relative to lower level alternatives. This was principally due to relying on pure Python code to achieve things that the base language often didn't have fast ways of doing.
This release starts to address that problem with a fairly extensive rewrite to replace much of the pure Python low-level bit operations with methods from the bitarray package. This is a package that does many of the same things as bitstring, and the two packages have co-existed for a long time. While bitarray doesn't have all of the options and facilities of bitstring it has the advantage of being very fast as it is implemented in C. By replacing the internal datatypes I can speed up bitstring's operations while keeping the same API.
Huge kudos to Ilan Schnell for all his work on bitarray.
If your data is all of a single type you can make use of the new Array class, which
mirrors much of the functionality of the standard array.array type, but doesn't restrict
you to just a dozen formats.
>>> from bitstring import Array
>>> a = Array('uint7', [9, 100, 3, 1])
>>> a.data
BitArray('0x1390181')
>>> b = Array('float16', a.tolist())
>>> b.append(0.25)
>>> b.tobytes()
b'H\x80V@B\x00<\x004\x00'
>>> b.tolist()
[9.0, 100.0, 3.0, 1.0, 0.25]
The data is stored efficiently in a BitArray object, and you can manipulate both the
data and the Array format freely. See the main documentation for more details. Note that
this feature carries the 'beta' flag so may change in future point versions.
Added two new floating point interpretations: float8_143 and float8_152. These are 8-bit
floating point formats, with very limited range and precision, but useful in some fields,
particularly machine learning. This is an experimental feature - the formats haven't
even been standardised yet.
>>> a = Bits(float8_143=16.5)
>>> a.bin
'01100000'
>>> a.float8_143
16.0
Auto initialization from ints has been removed and now raises a TypeError. Creating a
bitstring from an int still creates a zeroed bitstring of that length but ints won't
be promoted to bitstrings as that has been a constant source of errors and confusion.
>>> a = BitArray(100) # Fine - create with 100 zeroed bits
>>> a += 0xff # TypeError - previously this would have appended 0xff (=255) zero bits.
>>> a += '0xff' # Probably what was meant - append eight '1' bits.
>>> a += Bits(255) # Fine, append 255 zero bits.
This is a breaking change, but it breaks loudly with an exception, it is easily recoded, and it removes a confusing wrinkle.
Explicitly specifying the auto parameter is now disallowed rather than discouraged.
It was always meant to be a positional-only parameter (and will be once I can drop
Python 3.7 support) but for now it's renamed to __auto. In the unlikely event
this breaks code, the fix should be just to delete the auto= if it's already the
first parameter.
>>> s = Bits(auto='0xff') # Now raises a CreationError
>>> s = Bits('0xff') # Fine, as always
Deleting, replacing or inserting into a bitstring resets the bit position to 0 if the bitstring's length has been changed. Previously the bit position was adjusted but this was not well-defined.
Only empty bitstring are now considered false in a boolean sense. Previously s was
False if no bits in s were set to 1, but this goes against what it means to be a
container in Python, so I consider this to be a bug, even if it was documented. I'm
guessing it's related to __nonzero__ in Python 2 becoming __bool__ in Python 3, and
it's never been fixed before now.
Casting to bytes now behaves as expected, so that bytes(s) gives the same result as
s.tobytes(). Previously it created a byte per bit.
Pretty printing with the 'bytes' format now uses characters from the 'Latin Extended-A'
unicode block for non-ASCII and unprintable characters instead of replacing them with '.'
When using struct-like codes you can now use '=' instead of '@' to signify native-
endianness. They behave identically, but the new '=' is now preferred.
More fixes for LSB0 mode. There are now no known issues with this feature.
…There are also a couple of small possibly breaking changes detailed below, in particular 'auto' initialising bitstrings from integers is now disallowe…
This has turned into a suprisingly big release, with a major refactor and a brand new class (the first for 12 years!) There are also a couple of small possibly breaking changes detailed below, in particular 'auto' initialising bitstrings from integers is now disallowed.
The major weakness of bitstring has been its poor performance for computationally intensive tasks relative to lower level alternatives. This was principally due to relying on pure Python code to achieve things that the base language often didn't have fast ways of doing.
This release starts to address that problem with a fairly extensive rewrite to replace much of the pure Python low-level bit operations with methods from the bitarray package. This is a package that does many of the same things as bitstring, and the two packages have co-existed for a long time. While bitarray doesn't have all of the options and facilities of bitstring it has the advantage of being very fast as it is implemented in C. By replacing the internal datatypes I can speed up bitstring's operations while keeping the same API.
Huge kudos to Ilan Schnell for all his work on bitarray.
If your data is all of the same type you can make use of the new Array class, which mirrors much of the functionality of the standard array.array type, but doesn't restrict you to just a dozen formats.
>>> from bitstring import Array
>>> a = Array('uint7', [9, 100, 3, 1])
>>> a.data
BitArray('0x1390181')
>>> b = Array('float16', a.tolist())
>>> b.append(0.25)
>>> b.tobytes()
b'H\x80V@B\x00<\x004\x00'
>>> b.tolist()
[9.0, 100.0, 3.0, 1.0, 0.25]
The data is stored efficiently in a BitArray object, and you can manipulate both the data and the Array format freely. See the main documentation for more details. Note that this feature carries the 'beta' flag so may change in future point versions.
>>> a = Bits(float8_143=16.5)
>>> a.bin
'01100000'
>>> a.float8_143
16.0
>>> a = BitArray(100) # Fine - create with 100 zeroed bits
>>> a += 0xff # TypeError - previously this would have appended 0xff (=255) zero bits.
>>> a += '0xff' # Probably what was meant - append eight '1' bits.
>>> a += Bits(255) # Fine, append 255 zero bits.
This is a breaking change, but it breaks loudly with an exception, it is easily recoded, and it removes a confusing wrinkle.
__auto. In the unlikely event
this breaks code, the fix should be just to delete the auto= if it's already the
first parameter. >>> s = Bits(auto='0xff') # Now raises a CreationError
>>> s = Bits('0xff') # Fine, as always
Deleting, replacing or inserting into a bitstring resets the bit position to 0 if the bitstring's length has been changed. Previously the bit position was adjusted but this was not well defined.
Only empty bitstring are now considered False in a boolean sense. Previously s was
False is no bits in s were set to 1, but this goes against what it means to be a
container in Python so I consider this to be a bug, even if it was documented. I'm
guessing it's related to __nonzero__ in Python 2 becoming __bool__ in Python 3, and
it's never been fixed before now.
Casting to bytes now behaves as expected, so that bytes(s) gives the same result as
s.tobytes(). Previously it created a byte per bit.
Pretty printing with the 'bytes' format now uses characters from the 'Latin Extended-A' unicode block for non-ASCII and unprintable characters instead of replacing them with '.'
When using struct-like codes you can now use '=' instead of '@' to signify native- endianness. They behave identically, but the new '=' is now preferred.
More fixes for LSB0 mode. There are now no known issues with this feature.
Nothing published for this version
Added py.typed file and converted the module to a package to let mypy find type annotations. Bug 248.
A maintenance release.
py.typed file and converted the module to a package to let mypy find type
annotations. Bug 248.pyproject.toml. Bug 243.This is a major release which drops support for Python 2.7 and has a new minimum requirement of Python 3.7. Around 95% of downloads satisfy this - users of older versions can continue to use bitstring 3.1, which will still be supported with fixes, but no new features.
Other breaking changes are minimal, and there are a few cool features added.
ConstBitArray and BitString class aliases. Use Bits and BitStream instead.cut() method will now also yield the final bits of a bitstring, even if they
are shorter than the requested cut size.uint interpretation. This wasn't being applied uniformly - the default
is now always to return a bitstring object of the given length and not to interpret
it as a uint. Bug 220.Type hints added throughout the code.
Underscores are now allowed in strings representing number literals.
The copy() method now works on Bits as well as BitArray objects.
The experimental command-line feature is now official. 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.
$ python -m bitstring int:16=-400
0xfe70
$ python -m bitstring float:32=0.2 bin
00111110010011001100110011001101
New pp() method that pretty-prints the bitstring in various formats - useful
especially in interactive sessions. Thanks to Omer Barak for the suggestion
and discussion.
>>> s.pp()
0: 10001000 01110110 10001110 01110110 11111000 01110110 10000111 00101000
64: 01110010 11111001 10000111 10011000 11110111 10011110 10000111 11111101
128: 11111001 10001100 01111111 10111100 10111111 11011011 11101011 11111011
192: 1100
>>> s.pp('bin, hex')
0: 10001000 01110110 10001110 01110110 11111000 01110110 88 76 8e 76 f8 76
48: 10000111 00101000 01110010 11111001 10000111 10011000 87 28 72 f9 87 98
96: 11110111 10011110 10000111 11111101 11111001 10001100 f7 9e 87 fd f9 8c
144: 01111111 10111100 10111111 11011011 11101011 11111011 7f bc bf db eb fb
192: 1100 c
Shorter and more versatile properties. The bin, oct, hex, float, uint and int
properties can now be shortened to just their first letter. They can also have
a length in bits after them - allowing Rust-like data types.
>>> s = BitArray('0x44961000')
>>> s.h
'44961000'
>>> s.f32
1200.5
>>> s.u
1150685184
>>> s.i7 = -60
>>> s.b
'1000100'
>>> t = Bits('u12=160, u12=120, b=100')
Other types with bit lengths can also be used as properties:
>>> s.floatle64 = 10.511
A colon is no longer required in format strings before a bit length. So for
example Bits('int:15=-101') could be written as Bits('int15=-101'). This is
now the preferred usage in the documentation except where the colon improves
readability.
Support for IEEE 16 bit floats. Floating point types can now be 16 bits long as well
as 32 and 64 bits. This is using the 'e' format from the struct module.
Support for bfloats. This is a specialised 16-bit floating point format mostly used in machine learning. It's essentially a truncated IEEE 32-bit format that keeps its range but only has a couple of significant figures of accuracy.
November 2022: version 4.0.1 released
This is a major release which drops support for Python 2.7 and has a new minimum requirement of Python 3.7. Around 95% of downloads satisfy this - users of older versions can continue to use bitstring 3.1, which will still be supported with fixes, but no new features.
Other changes are minimal, with a few features added.
Type hints added throughout the code.
Underscores are now allowed in strings representing number literals.
The copy() method now works on Bits as well as BitArray objects.
The experimental command-line feature is now official. 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. ::
$ python -m bitstring int:16=-400
0xfe70
$ python -m bitstring float:32=0.2 bin
00111110010011001100110011001101
New pp() method that pretty-prints the bitstring in various formats - useful especially in interactive sessions. Thanks to Omer Barak for the suggestion and discussion.
>>> s.pp()
0: 10001000 01110110 10001110 01110110 11111000 01110110 10000111 00101000
64: 01110010 11111001 10000111 10011000 11110111 10011110 10000111 11111101
128: 11111001 10001100 01111111 10111100 10111111 11011011 11101011 11111011
192: 1100
>>> s.pp('bin, hex')
0: 10001000 01110110 10001110 01110110 11111000 01110110 88 76 8e 76 f8 76
48: 10000111 00101000 01110010 11111001 10000111 10011000 87 28 72 f9 87 98
96: 11110111 10011110 10000111 11111101 11111001 10001100 f7 9e 87 fd f9 8c
144: 01111111 10111100 10111111 11011011 11101011 11111011 7f bc bf db eb fb
192: 1100 c
Shorter and more versatile properties. The bin, oct, hex, float, uint and int properties can now be shortened to just their first letter. They can also have a length in bits after them - allowing Rust-like data types. ::
>>> s = BitArray('0x44961000')
>>> s.h
'44961000'
>>> s.f32
1200.5
>>> s.u
1150685184
>>> s.i7 = -60
>>> s.b
'1000100'
>>> t = Bits('u12=160, u12=120, b=100')
Support for IEEE 16 bit floats. Floating point types can now be 16 bits long as well as 32 and 64 bits. This is using the 'e' format from the struct module.
Support for the bfloat format. This is a specialised 16-bit floating point format mostly used in machine learning. It is essentially a truncated IEEE 32-bit floating point number that has the same range but much less accuracy.
Removed requirement to have a colon before lengths in format strings. So for example
'uint:12=100' can be just 'uint12=100'. The colon is still recommended for
readability if the length isn't given as a number literal.
Pulled due to a bug when using Python 3.7.
Pulled due to a bug when using Python 3.7.
Nothing published for this version
Nothing published for this version
July 20th 2021: version 3.1.9 released
(version 3.1.8 was pulled due to serious issues) Another maintenance release.
Nothing published for this version
Removed deprecated direct import of ABC from collections module (Issue #196)
This is a maintenance release with a few bug fixes plus an experimental feature to allow bits to be indexed in the opposite direction.
This is a maintenance release with a few bug fixes plus an experimental feature to allow bits to be indexed in the opposite direction.
This feature allows bitstring to use Least Significant Bit Zero
(LSB0) bit numbering; that is the final bit in the bitstring will
be bit 0, and the first bit will be bit (n-1), rather than the
other way around. LSB0 is a more natural numbering
system in many fields, but is the opposite to Most Significant Bit
Zero (MSB0) numbering which is the natural option when thinking of
bitstrings as standard Python containers.
To switch from the default MSB0, use the module level function
>>> bitstring.set_lsb0(True)
Getting and setting bits should work in this release, as will some other methods. Many other methods are not tested yet and might not work as expected. This is mostly a release to get feedback before finalising the interface.
Slicing is still done with the start bit smaller than the end bit. For example:
>>> s = Bits('0b000000111')
>>> s[0:5]
Bits('0b00111')
>>> s[0]
True
Negative indices work as (hopefully) you'd expect, with the first stored
bit being s[-1] and the final stored bit being s[-n].
See https://github.com/scott-griffiths/bitstring/issues/156 for discussions and to add any further comments.
July 9th 2019: version 3.1.6 released
A long overdue maintenace release with some fixes.
__contains__ in some circumstances. Bug 180.Support initialisation from an array.
This is another bug fix release.
This is another bug fix release.
This is another bug fix release.
This is another bug fix release.
This is another bug fix release.
This is another bug fix release.
Fix for problem where concatenating bitstrings sometimes modified method's arguments
This is a bug fix release.
This is a bug fix release.
This is a minor release with a couple of new features and some bug fixes.
This token can be used in reads and when packing/unpacking to indicate that you don't care about the contents of these bits. Any padding bits will just be skipped over when reading/unpacking or zero-filled when packing.
>>> a, b = s.readlist('pad:5, uint:3, pad:1, uint:3')
Here only two items are returned in the list - the padding bits are ignored.
These methods have been introduced in Python 3.3 for lists and bytearrays, as more obvious ways of clearing and copying, and we mirror that change here.
t = s.copy() is equivalent to t = s[:], and s.clear() is equivalent to del s[:].
This is a minor release with a couple of new features and some bug fixes.
This is a minor release with a couple of new features and some bug fixes.
This token can be used in reads and when packing/unpacking to indicate that you don't care about the contents of these bits. Any padding bits will just be skipped over when reading/unpacking or zero-filled when packing.
>>> a, b = s.readlist('pad:5, uint:3, pad:1, uint:3')
Here only two items are returned in the list - the padding bits are ignored.
These methods have been introduced in Python 3.3 for lists and bytearrays, as more obvious ways of clearing and copying, and we mirror that change here.
t = s.copy() is equivalent to t = s[:], and s.clear() is equivalent to del s[:].
This is a minor update that fixes a few bugs.
This is a minor update that fixes a few bugs.
There has also been a reorganisation of the code to return it to a single
bitstring.py file rather than the package that has been used for the past
several releases. This change shouldn't affect users directly.
This release fixed a small but very visible bug in bitstring printing.
This release fixed a small but very visible bug in bitstring printing.
This release fixed a small but very visible bug in bitstring printing.
This is a major release which breaks backward compatibility in a few places.
This is a major release which breaks backward compatibility in a few places.
This is a major release which breaks backward compatibility in a few places.
0x, 0o and 0bIf you ask for the hex, octal or binary representations of a bitstring then
they will no longer be prefixed with 0x, 0o or 0b. This was done as it
was noticed that the first thing a lot of user code does after getting these
representations was to cut off the first two characters before further
processing.
>>> a = BitArray('0x123')
>>> a.hex, a.oct, a.bin
('123', '0443', '000100100011')
Previously this would have returned ('0x123', '0o0443', '0b000100100011')
This change might require some recoding, but it should all be simplifications.
Previously Bits was an alias for ConstBitStream (for backward compatibility).
This has now changed so that Bits and BitArray loosely correspond to the
built-in types bytes and bytearray.
If you were using streaming/reading methods on a Bits object then you will have to change it to a ConstBitStream.
The ConstBitArray name is kept as an alias for Bits.
The step parameter in __getitem__, __setitem__ and __delitem__ used to act
as a multiplier for the start and stop parameters. No one seemed to use it
though and so it has now reverted to the conventional meaning for containers.
If you are using step then recoding is simple: s[a:b:c] becomes s[a*c:b*c].
Some examples of the new usage:
>>> s = BitArray('0x0000')
s[::4] = [1, 1, 1, 1]
>>> s.hex
'8888'
>>> del s[8::2]
>>> s.hex
'880'
readto methodThis method is a mix between a find and a read - it searches for a bitstring and then reads up to and including it. For example:
>>> s = ConstBitStream('0x47000102034704050647')
>>> s.readto('0x47', bytealigned=True)
BitStream('0x47')
>>> s.readto('0x47', bytealigned=True)
BitStream('0x0001020347')
>>> s.readto('0x47', bytealigned=True)
BitStream('0x04050647')
pack function accepts an iterable as its formatPreviously only a string was accepted as the format in the pack function. This was an oversight as it broke the symmetry between pack and unpack. Now you can use formats like this:
fmt = ['hex:8', 'bin:3']
a = pack(fmt, '47', '001')
a.unpack(fmt)
This is a minor upgrade with a couple of new features.
This is a minor upgrade with a couple of new features.
New bit interpretations for interleaved exponential-Golomb (as used in the Dirac video codec) are supplied via 'uie' and 'sie':
>>> s = BitArray(uie=41)
>>> s.uie
41
>>> s.bin
'0b00010001001'
These are pretty similar to the non-interleaved versions - see the manual for more details. Credit goes to Paul Sargent for the patch.
A number of methods take a 'bytealigned' parameter to indicate that they should only work on byte boundaries (e.g. find, replace, split). Previously this parameter defaulted to 'False'. Instead it now defaults to 'bitstring.bytealigned', which itself defaults to 'False', but can be changed to modify the default behaviour of the methods. For example:
>>> a = BitArray('0x00 ff 0f ff')
>>> a.find('0x0f')
(4,) # found first not on a byte boundary
>>> a.find('0x0f', bytealigned=True)
(16,) # forced looking only on byte boundaries
>>> bitstring.bytealigned = True # Change default behaviour
>>> a.find('0x0f')
(16,)
>>> a.find('0x0f', bytealigned=False)
(4,)
If you're only working with bytes then this can help avoid some errors and save some typing!
This is a release to fix a couple of bugs that were introduced in 2.1.0.
This is a release to fix a couple of bugs that were introduced in 2.1.0.
Previously there were just two classes, the immutable Bits which was the base class for the mutable BitString class. Both of these classes have the co
Previously there were just two classes, the immutable Bits which was the base class for the mutable BitString class. Both of these classes have the concept of a bit position, from which reads etc. take place so that the bitstring could be treated as if it were a file or stream.
Two simpler classes have now been added which are purely bit containers and don't have a bit position. These are called ConstBitArray and BitArray. As you can guess the former is an immutable version of the latter.
The other classes have also been renamed to better reflect their capabilities. Instead of BitString you can use BitStream, and instead of Bits you can use ConstBitStream. The old names are kept as aliases for backward compatibility.
The classes hierarchy is:
ConstBitArray
/ \
/ \
BitArray ConstBitStream (formerly Bits)
\ /
\ /
BitStream (formerly BitString)
A lot of internal reorganisation has taken place since the previous version, most of which won't be noticed by the end user. Some things you might see are:
Bug fix: Using peek and read for a single bit now returns a new bitstring as was intended, rather than the old behaviour of returning a bool.
This is a major release, with a number of backwardly incompatible changes. The main change is the removal of many methods, all of which have simple alternatives. Other changes are quite minor but may need some recoding.
There are a few new features, most of which have been made to help the stream-lining of the API. As always there are performance improvements and some API changes were made purely with future performance in mind.
Many of these methods have been deprecated for the last few releases, but there are some new removals too. Any recoding needed should be quite straigh…
This is a major release, with a number of backwardly incompatible changes. The main change is the removal of many methods, all of which have simple alternatives. Other changes are quite minor but may need some recoding.
There are a few new features, most of which have been made to help the stream-lining of the API. As always there are performance improvements and some API changes were made purely with future performance in mind.
About half of the class methods have been removed from the API. They all have simple alternatives, so what remains is more powerful and easier to remember. The removed methods are listed here on the left, with their equivalent replacements on the right:
s.advancebit() -> s.pos += 1
s.advancebits(bits) -> s.pos += bits
s.advancebyte() -> s.pos += 8
s.advancebytes(bytes) -> s.pos += 8*bytes
s.allunset([a, b]) -> s.all(False, [a, b])
s.anyunset([a, b]) -> s.any(False, [a, b])
s.delete(bits, pos) -> del s[pos:pos+bits]
s.peekbit() -> s.peek(1)
s.peekbitlist(a, b) -> s.peeklist([a, b])
s.peekbits(bits) -> s.peek(bits)
s.peekbyte() -> s.peek(8)
s.peekbytelist(a, b) -> s.peeklist([8*a, 8*b])
s.peekbytes(bytes) -> s.peek(8*bytes)
s.readbit() -> s.read(1)
s.readbitlist(a, b) -> s.readlist([a, b])
s.readbits(bits) -> s.read(bits)
s.readbyte() -> s.read(8)
s.readbytelist(a, b) -> s.readlist([8*a, 8*b])
s.readbytes(bytes) -> s.read(8*bytes)
s.retreatbit() -> s.pos -= 1
s.retreatbits(bits) -> s.pos -= bits
s.retreatbyte() -> s.pos -= 8
s.retreatbytes(bytes) -> s.pos -= 8*bytes
s.reversebytes(start, end) -> s.byteswap(0, start, end)
s.seek(pos) -> s.pos = pos
s.seekbyte(bytepos) -> s.bytepos = bytepos
s.slice(start, end, step) -> s[start:end:step]
s.tell() -> s.pos
s.tellbyte() -> s.bytepos
s.truncateend(bits) -> del s[-bits:]
s.truncatestart(bits) -> del s[:bits]
s.unset([a, b]) -> s.set(False, [a, b])
Many of these methods have been deprecated for the last few releases, but there are some new removals too. Any recoding needed should be quite straightforward, so while I apologise for the hassle, I had to take the opportunity to streamline and rationalise what was becoming a bit of an overblown API.
The set/unset methods have been combined in a single method, which now takes a boolean as its first argument:
s.set([a, b]) -> s.set(1, [a, b])
s.unset([a, b]) -> s.set(0, [a, b])
s.allset([a, b]) -> s.all(1, [a, b])
s.allunset([a, b]) -> s.all(0, [a, b])
s.anyset([a, b]) -> s.any(1, [a, b])
s.anyunset([a, b]) -> s.any(0, [a, b])
The all and any methods (previously called allset, allunset, anyset and anyunset) no longer accept a single bit position. The recommended way of testing a single bit is just to index it, for example instead of:
>>> if s.all(True, i):
just use
>>> if s[i]:
If you really want to you can of course use an iterable with a single element, such as 's.any(False, [i])', but it's clearer just to write 'not s[i]'.
If a read or peek goes beyond the end of the bitstring then a ReadError will be raised. The previous behaviour was that the rest of the bitstring would be returned and no exception raised.
The base class for errors in the bitstring module is now just Error, so it will likely appears in your code as bitstring.Error instead of the rather repetitive bitstring.BitStringError.
A single index slice (such as s[5]) will now return a bool (i.e. True or False) rather than a single bit bitstring. This is partly to reflect the style of the bytearray type, which returns an integer for single items, but mostly to avoid common errors like:
>>> if s[0]:
... do_something()
While the intent of this code snippet is quite clear (i.e. do_something if the first bit of s is set) under the old rules s[0] would be true as long as s wasn't empty. That's because any one-bit bitstring was true as it was a non-empty container. Under the new rule s[0] is True if s starts with a '1' bit and False if s starts with a '0' bit.
The change does not affect reads and peeks, so s.peek(1) will still return a single bit bitstring, which leads on to the next item...
Previously a bitstring was False if it had no elements, otherwise it was True. This is standard behaviour for containers, but wasn't very useful for a container of just 0s and 1s. The new behaviour means that the bitstring is False if it has no 1 bits. This means that code like this:
>>> if s.peek(1):
... do_something()
should work as you'd expect. It also means that Bits(1000), Bits(0x00) and Bits('uint:12=0') are all also False. If you need to check for the emptiness of a bitstring then instead check the len property:
if s -> if s.len
if not s -> if not s.len
Previously you could create bitstring using expressions like:
>>> s = Bits(hex='0xabcde', offset=4, length=13)
This has now been disallowed, and the offset and length parameters may only be used when initialising with bytes or a file. To replace the old behaviour you could instead use
>>> s = Bits(hex='0xabcde')[4:17]
Methods with a 'format' parameter have had it renamed to 'fmt', to prevent hiding the built-in 'format'. Affects methods unpack, read, peek, readlist, peeklist and byteswap and the pack function.
This means that for the affected methods (unpack, readlist and peeklist) you will need to use an iterable to specify multiple items. This is easier to show than to describe, so instead of
>>> a, b, c, d = s.readlist('uint:12', 'hex:4', 'bin:7')
you would instead write
>>> a, b, c, d = s.readlist(['uint:12', 'hex:4', 'bin:7'])
Note that you could still use the single string 'uint:12, hex:4, bin:7' if you preferred.
You can no longer use True and False to initialise single bit bitstrings. The reasoning behind this is that as bool is a subclass of int, it really is bad practice to have Bits(False) be different to Bits(0) and to have Bits(True) different to Bits(1).
If you have used bool auto-initialisation then you will have to be careful to replace it as the bools will now be interpreted as ints, so Bits(False) will be empty (a bitstring of length 0), and Bits(True) will be a single zero bit (a bitstring of length 1). Sorry for the confusion, but I think this will prevent bigger problems in the future.
There are a few alternatives for creating a single bit bitstring. My favourite it to use a list with a single item:
Bits(False) -> Bits([0])
Bits(True) -> Bits([1])
Previously if you created a bitstring from a file, either by auto-initialising with a file object or using the filename parameter, the file would not be read into memory unless you tried to modify it, at which point the whole file would be read.
The new behaviour depends on whether you create a Bits or a BitString from the file. If you create a Bits (which is immutable) then the file will never be read into memory. This allows very large files to be opened for examination even if they could never fit in memory.
If however you create a BitString, the whole of the referenced file will be read to store in memory. If the file is very big this could take a long time, or fail, but the idea is that in saying you want the mutable BitString you are implicitly saying that you want to make changes and so (for now) we need to load it into memory.
The new strategy is a bit more predictable in terms of performance than the old. The main point to remember is that if you want to open a file and don't plan to alter the bitstring then use the Bits class rather than BitString.
Just to be clear, in neither case will the contents of the file ever be changed - if you want to output the modified BitString then use the tofile method, for example.
If a find is unsuccessful then an empty tuple is returned (which is False in a boolean sense) otherwise a single item tuple with the bit position is returned (which is True in a boolean sense). You shouldn't need to recode unless you explicitly compared the result of a find to True or False, for example this snippet doesn't need to be altered:
>>> if s.find('0x23'):
... print(s.bitpos)
but you could now instead use
>>> found = s.find('0x23')
>>> if found:
... print(found[0])
The reason for returning the bit position in a tuple is so that finding at position zero can still be True - it's the tuple (0,) - whereas not found can be False - the empty tuple ().
This method just counts the number of 1 or 0 bits in the bitstring.
>>> s = Bits('0x31fff4')
>>> s.count(1)
16
The read, readlist, peek and peeklist methods now accept integers as parameters to mean "read this many bits and return a bitstring". This has allowed a number of methods to be removed from this release, so for example instead of:
>>> a, b, c = s.readbits(5, 6, 7)
>>> if s.peekbit():
... do_something()
you should write:
>>> a, b, c = s.readlist([5, 6, 7])
>>> if s.peek(1):
... do_something()
The byteswap method now allows a format specifier of 0 (the default) to signify that all of the whole bytes should be reversed. This means that calling just byteswap() is almost equivalent to the now removed bytereverse() method (a small difference is that byteswap won't raise an exception if the bitstring isn't a whole number of bytes long).
So rather than writing:
>>> a = Bits(bytes=some_bytearray)
you can just write
>>> a = Bits(some_bytearray)
This also works for the bytes type, but only if you're using Python 3. For Python 2 it's not possible to distinguish between a bytes object and a str. For this reason this method should be used with some caution as it will make you code behave differently with the different major Python versions.
>>> b = Bits(b'abcd\x23\x00') # Only Python 3!
This means that you can for example write:
>>> a = BitString(100) # 100 zero bits
>>> a.set(1) # set all bits to 1
>>> a.all(1) # are all bits set to 1?
True
>>> a.any(0) # are any set to 0?
False
>>> a.invert() # invert every bit
As well as renaming BitStringError to just Error there are also new exceptions which use Error as a base class.
These can be caught in preference to Error if you need finer control. The new exceptions sometimes also derive from built-in exceptions:
ByteAlignError(Error) - whole byte position or length needed.
ReadError(Error, IndexError) - reading or peeking off the end of the bitstring.
CreationError(Error, ValueError) - inappropriate argument during bitstring creation.
InterpretError(Error, ValueError) - inappropriate interpretation of binary data.
Nothing published for this version
Nothing published for this version
Also its parameter has changed from 'bitstringlist' to 'sequence'. This is technically a backward incompatibility in the unlikely event that you are r…
New features:
Changes the endianness in-place according to a format string or integer(s) giving the byte pattern. See the manual for details.
>>> s = BitString('0x00112233445566')
>>> s.byteswap(2)
3
>>> s
BitString('0x11003322554466')
>>> s.byteswap('h')
3
>>> s
BitString('0x00112233445566')
>>> s.byteswap([2, 5])
1
>>> s
BitString('0x11006655443322')
For example:
>>> s = Bits('100*0x123')
For example:
>>> s = Bits('3*(uint:6=3, 0b1)')
The start and end parameters of many methods may now be negative, with the same meaning as for negative slice indices. Affects all methods with these parameters.
The Bits class now derives from collections.Sequence, while the BitString class derives from collections.MutableSequence.
Keywords for token lengths are now permitted when reading. So for example, you can write
>>> s = bitstring.pack('4*(uint:n)', 2, 3, 4, 5, n=7)
>>> s.unpack('4*(uint:n)', n=7)
[2, 3, 4, 5]
Also its parameter has changed from 'bitstringlist' to 'sequence'. This is technically a backward incompatibility in the unlikely event that you are referring to the parameter by name.
Rather than a long list of initialisers the init methods now use a **kwargs dictionary for all initialisers except 'auto'. This should have no effect, except that this is a small backward incompatibility if you use positional arguments when initialising with anything other than auto (which would be rather unusual).
A number of methods have been flagged for removal in version 2. Deprecation warnings will now be given, which include an alternative way to do the sam…
Bits class.Introducing a brand new class, Bits, representing an immutable sequence of
bits.
The Bits class is the base class for the mutable BitString. The differences
between Bits and BitStrings are:
Bits are immutable, so once they have been created their value cannot change.
This of course means that mutating methods (append, replace, del etc.) are not
available for Bits.
Bits are hashable, so they can be used in sets and as keys in dictionaries.
Bits are potentially more efficient than BitStrings, both in terms of
computation and memory. The current implementation is only marginally
more efficient though - this should improve in future versions.
You can switch from Bits to a BitString or vice versa by constructing a new
object from the old.
>>> s = Bits('0xabcd')
>>> t = BitString(s)
>>> t.append('0xe')
>>> u = Bits(t)
The relationship between Bits and BitString is supposed to loosely mirror that
between bytes and bytearray in Python 3.
A number of methods have been flagged for removal in version 2. Deprecation warnings will now be given, which include an alternative way to do the same thing. All of the deprecated methods have simpler equivalent alternatives.
>>> t = s.slice(0, 2)
__main__:1: DeprecationWarning: Call to deprecated function slice.
Instead of 's.slice(a, b, c)' use 's[a:b:c]'.
The deprecated methods are: advancebit, advancebits, advancebyte, advancebytes,
retreatbit, retreatbits, retreatbyte, retreatbytes, tell, seek, slice, delete,
tellbyte, seekbyte, truncatestart and truncateend.
Booleans have been added to the list of types that can 'auto' initialise a bitstring.
>>> zerobit = BitString(False)
>>> onebit = BitString(True)
More methods have been sped up, in particular some deletions and insertions.
A rare problem with truncating the start of bitstrings was fixed.
A possible problem outputting the final byte in tofile() was fixed.
This version hopefully fixes an installation problem for platforms with case-sensitive file systems. There are no new features or other bug fixes.
This version hopefully fixes an installation problem for platforms with case-sensitive file systems. There are no new features or other bug fixes.
This is a minor update with (almost) no new features.
This is a minor update with (almost) no new features.
The speed of many typical operations has been increased, some substantially.
A BitString of '0' bits can be created using just an integer to give the length in bits. So instead of
>>> s = BitString(length=100)
you can write just
>>> s = BitString(100)
This matches the behaviour of bytearrays and (in Python 3) bytes.
set / unset functions on BitStrings initialised
from a file has been fixed.Nothing published for this version
Note that this version will not work for Python 2.4 or 2.5. There may be an update for these Python versions some time next year, but it's not a prior
Note that this version will not work for Python 2.4 or 2.5. There may be an update for these Python versions some time next year, but it's not a priority quite yet. Also note that only one version is now provided, which works for Python 2.6 and 3.x (done with the minimum of hackery!)
A fair number of functions have improved efficiency, some quite dramatically.
Although these functions don't do anything that couldn't be done before, they do make some common use cases much more efficient. If you need to set or check single bits then these are the functions you need.
set / unset : Set bit(s) to 1 or 0 respectively.
allset / allunset : Check if all bits are 1 or all 0.
anyset / anyunset : Check if any bits are 1 or any 0.
For example
>>> s = BitString(length=1000)
>>> s.set((10, 100, 44, 12, 1))
>>> s.allunset((2, 22, 222))
True
>>> s.anyset(range(7, 77))
True
ror / rol : Rotate bits to the right or left respectively.
>>> s = BitString('0b100000000')
>>> s.ror(2)
>>> s.bin
'0b001000000'
>>> s.rol(5)
>>> s.bin
'0b000000100'
New float initialisations and interpretations are available. These only work for BitStrings of length 32 or 64 bits.
>>> s = BitString(float=0.2, length=64)
>>> s.float
0.200000000000000001
>>> t = bitstring.pack('<3f', -0.4, 1e34, 17.0)
>>> t.hex
'0xcdccccbedf84f67700008841'
This token returns a bytes object (equivalent to a str in Python 2.6).
>>> s = BitString('0x010203')
>>> s.unpack('bytes:2, bytes:1')
['\x01\x02', '\x03']
So for example these are equivalent:
a, b = s.readlist('uint:12, uint:12')
a, b = s.readlist('12, 12')
Nothing published for this version
Finally some tools for dealing with endianness!
Finally some tools for dealing with endianness!
>>> big = BitString(intbe=1, length=16) # or BitString('intbe:16=1') if you prefer.
>>> little = BitString(intle=1, length=16)
>>> print big.hex, little.hex
0x0001 0x0100
>>> print big.intbe, little.intle
1 1
To save some typing when using pack, unpack, read and peek, compact format codes based on those used in the struct and array modules have been added. These must start with a character indicating the endianness (>, < or @ for big, little and native-endian), followed by characters giving the format:
b 1-byte signed int
B 1-byte unsigned int
h 2-byte signed int
H 2-byte unsigned int
l 4-byte signed int
L 4-byte unsigned int
q 8-byte signed int
Q 8-byte unsigned int
For example:
>>> s = bitstring.pack('<4h', 0, 1, 2, 3)
creates a BitString with four little-endian 2-byte integers. While
>>> x, y, z = s.read('>hhl')
reads them back as two big-endian two-byte integers and one four-byte big endian integer.
Of course you can combine this new format with the old ones however you like:
>>> s.unpack('<h, intle:24, uint:5, bin')
[0, 131073, 0, '0b0000000001100000000']
This update introduces pack and unpack functions for creating and dissembling BitStrings.
This update introduces pack and unpack functions for creating and dissembling BitStrings.
The module level pack function provides a flexible new method for creating BitStrings. Tokens for BitString 'literals' can be used in the same way as in the constructor.
>>> from bitstring import BitString, pack
>>> a = pack('0b11, 0xff, 0o77, int:5=-1, se=33')
You can also leave placeholders in the format, which will be filled in by the values provided.
>>> b = pack('uint:10, hex:4', 33, 'f')
Finally, you can use a dictionary or keywords.
>>> c = pack('bin=a, hex=b, bin=a', a='010', b='ef')
The unpack function is similar to the read function except that it always unpacks from the start of the BitString.
>>> x, y = b.unpack('uint:10, hex')
If a token is given without a length (as above) then it will expand to fill the remaining bits in the BitString. This also now works with read() and peek().
tostring() and tofile() functions.The tostring() function just returns the data as a string, with up to seven
zero bits appended to byte align. The tofile() function does the same except
writes to a file object.
>>> f = open('myfile', 'wb')
>>> BitString('0x1234ff').tofile(f)
The use of '=' is now mandatory in 'auto' initialisers. Tokens like 'uint12 100' will
no longer work. Also, the use of a ':' before the length is encouraged, but not yet
mandated. So the previous example should be written as 'uint:12=100'.
The 'auto' initialiser will now take a file object.
>>> f = open('myfile', 'rb')
>>> s = BitString(f)
This update breaks backward compatibility in a couple of areas. The only one you probably need to be concerned about is the change to the default for
This update breaks backward compatibility in a couple of areas. The only one
you probably need to be concerned about is the change to the default for
bytealigned in find, replace, split, etc.
See the user manual for more details on each of these items.
More types can be initialised through the 'auto' initialiser. For example instead of
>>> a = BitString(uint=44, length=16)
you can write
>>> a = BitString('uint16=44')
Also, different comma-separated tokens will be joined together, e.g.
>>> b = BitString('0xff') + 'int8=-5'
can be written
>>> b = BitString('0xff, int8=-5')
read() and peek() functions.These takes a format string similar to that used in the auto initialiser. If only one token is provided then a single value is returned, otherwise a list of values is returned.
>>> start_code, width, height = s.read('hex32, uint12, uint12')
is equivalent to
>>> start_code = s.readbits(32).hex
>>> width = s.readbits(12).uint
>>> height = s.readbits(12).uint
The tokens are:
int n : n bits as an unsigned integer.
uint n : n bits as a signed integer.
hex n : n bits as a hexadecimal string.
oct n : n bits as an octal string.
bin n : n bits as a binary string.
ue : next bits as an unsigned exp-Golomb.
se : next bits as a signed exp-Golomb.
bits n : n bits as a new BitString.
bytes n : n bytes as a new BitString.
See the user manual for more details.
hex() and oct() functions removed.The special functions for hex() and oct() have been removed. Please use the
hex and oct properties instead.
>>> hex(s)
becomes
>>> s.hex
The join function must now be called on a BitString object, which will be
used to join the list together. You may need to recode slightly:
>>> s = bitstring.join('0x34', '0b1001', '0b1')
becomes
>>> s = BitString().join('0x34', '0b1001', '0b1')
readbits, readbytes, peekbits and peekbytesIf you specify more than one bit or byte length then a list of BitStrings will be returned.
>>> a, b, c = s.readbits(10, 5, 5)
is equivalent to
>>> a = readbits(10)
>>> b = readbits(5)
>>> c = readbits(5)
bytealigned defaults to False, and is at the end of the parameter listFunctions that have a bytealigned parameter have changed so that it now
defaults to False rather than True. Also, its position in the parameter list
has changed to be at the end. You may need to recode slightly (sorry!)
readue and readse functions have been removedInstead you should use the new read function with a 'ue' or 'se' token:
>>> i = s.readue()
becomes
>>> i = s.read('ue')
This is more flexible as you can read multiple items in one go, plus you can
now also use the peek function with ue and se.
See the issue tracker for more details.
This is a minor update. This release is the first to bundle the bitstring manual. This is a PDF and you can find it in the docs directory.
This is a minor update. This release is the first to bundle the bitstring manual. This is a PDF and you can find it in the docs directory.
Changes in version 0.4.3
This function returns a generator for constant sized chunks of a BitString.
>>> for byte in s.cut(8):
... do_something_with(byte)
You can also specify a startbit and endbit, as well as a count, which limits
the number of items generated:
>>> first100TSPackets = list(s.cut(188*8, count=100))
slice function now equivalent to __getitem__.This means that a step can also be given to the slice function so that the
following are now the same thing, and it's just a personal preference which
to use:
>>> s1 = s[a:b:c]
>>> s2 = s.slice(a, b, c)
So now
>>> list(a.findall(s, count=n))
is equivalent to
>>> list(a.findall(s))[:n]
except that it won't need to generate the whole list and so is much more efficient.
The split function now has a 'count' parameter rather than 'maxsplit'. This
makes the interface closer to that for cut, replace and findall. The final item
generated is now no longer the whole of the rest of the BitString.
This is a minor update, and almost doesn't break compatibility with version 0.4.0, but with the slight exception of findall() returning a generator, d
This is a minor update, and almost doesn't break compatibility with version
0.4.0, but with the slight exception of findall() returning a generator,
detailed below.
Changes in version 0.4.2
The use of the step parameter (also known as the stride) in slices has been added. Its use is a little non-standard as it effectively gives a multiplicative factor to apply to the start and stop parameters, rather than skipping over bits.
For example this makes it much more convenient if you want to give slices in
terms of bytes instead of bits. Instead of writing s[a*8:b*8] you can use
s[a:b:8].
When using a step the BitString is effectively truncated to a multiple of the
step, so s[::8] is equal to s if s is an integer number of bytes, otherwise it
is truncated by up to 7 bits. So the final seven complete 16-bit words could be
written as s[-7::16]
Negative slices are also allowed, and should do what you'd expect. So for
example s[::-1] returns a bit-reversed copy of s (which is similar to
s.reversebits(), which does the same operation on s in-place). As another
example, to get the first 10 bytes in reverse byte order you could use
s_bytereversed = s[0:10:-8].
You can now specify an offset of greater than 7 bits when creating a BitString,
and the use of offset is also now permitted when using the filename initialiser.
This is useful when you want to create a BitString from the middle of a file
without having to read the file into memory.
>>> f = BitString(filename='reallybigfile', offset=8000000, length=32)
You can now assign an integer to a slice of a BitString. If the integer doesn't
fit in the size of slice given then a ValueError exception is raised. So this
is now allowed and works as expected:
>>> s[8:16] = 106
and is equivalent to
>>> s[8:16] = BitString(uint=106, length=8)
Some changes have been made to slicing so that fewer exceptions are raised,
bringing the interface closer to that for lists. So for example trying to delete
past the end of the BitString will now just delete to the end, rather than
raising a ValueError.
A new option for the auto initialiser is to pass it a list or tuple. The items
in the list or tuple are evaluated as booleans and the bits in the BitString are
set to 1 for True items and 0 for False items. This can be used anywhere the
auto initialiser can currently be used. For example:
>>> a = BitString([True, 7, False, 0, ()]) # 0b11000
>>> b = a + ['Yes', ''] # Adds '0b10'
>>> (True, True, False) in a
True
reversebits() now has optional startbit and endbit parameters.
As an optimisation findall() will return a generator, rather than a list. If you
still want the whole list then of course you can just call list() on the
generator.
Improved efficiency of rfind().
A couple of minor bugs were fixed. See the issue tracker for details.
There are some small backward incompatibilities relative to version 0.3.2:
Changes in version 0.4.0
Added rfind(), findall(), replace(). These do pretty much what you'd expect -
see the docstrings or the wiki for more information.
Some missing functions were added: __repr__, __contains__, __rand__,
__ror__, __rxor__ and __delitem__.
A couple of small bugs were fixed (see the issue tracker).
There are some small backward incompatibilities relative to version 0.3.2:
find and findbytealignedfindbytealigned has been removed, and becomes part of find. The default
start position has changed on both find and split to be the start of the
BitString. You may need to recode:
>>> s1.find(bs)
>>> s2.findbytealigned(bs)
>>> s2.split(bs)
becomes
>>> s1.find(bs, bytealigned=False, startbit=s1.bitpos)
>>> s2.find(bs, startbit=s1.bitpos) # bytealigned defaults to True
>>> s2.split(bs, startbit=s2.bitpos)
Previously a read or peek function that encountered the end of the BitString
would raise a ValueError. It will now instead return the remainder of the
BitString, which could be an empty BitString. This is closer to the file
object interface.
The offset property was previously read-only, and has now been removed from
public view altogether. As it is used internally for efficiency reasons you
shouldn't really have needed to use it. If you do then use the _offset parameter
instead (with caution).
A number of functions (especially find and findbytealigned) have been sped up considerably.
Changes in version 0.3.2
A number of functions (especially find and findbytealigned) have been sped
up considerably.
Added support for bit-wise AND (&), OR (|) and XOR (^). For example:
>>> a = BitString('0b00111')
>>> print a & '0b10101'
0b00101
Added seekbit and seekbyte functions. These complement the advance and
retreat functions, although you can still just use bitpos and bytepos
properties directly.
>>> a.seekbit(100) # Equivalent to a.bitpos = 100
Allowed comparisons between BitString objects and strings. For example this
will now work:
>>> a = BitString('0b00001111')
>>> a == '0x0f'
True
Your coding agent can read these notes before it upgrades. Set up the MCP server →