bytemaker
What is it?
bytemaker is a Python 3.8-compatible library for bit-manipulation and byte serialization/deserialization. It brings C bitfield functionality over to Python version 3.8+. To that end, it provides methods and types for converting @dataclass-decorated classes.
What can you do with it?
- A
BitVectorclass analogous to Python'sbytearrayclass, but for sub-byte bit quantities.BitVectorsupports all the methods you'd expect to have in a bit-centricbytearraywith a few extras, to boot. - A set of
BitTypesclasses, including various-sized buffers, unsigned/signed ints, floats, and strings, that have underlyingBitVectorrepresentations. - Support for serializing/deserializing
@dataclassannotated classes, where the annotations can beytypes, Pythonctypes(c_uint8,ctypes.STRUCTURE, etc.), or Python native typespytypes(int,bool,char,float). Nested types? No problem! - Automagic support for handling any of the aforementioned objects via
aggregate_types.to_bits_aggregateandaggregate_types.from_bits_aggregate.
How do I install it?
Run python -m pip install bytemaker.
For faster, C-backed bit manipulation, install with the optional bitarray dependency by running python -m pip install bytemaker[speedups] instead. Without it, bytemaker uses a pure-Python BitVector implementation with identical behavior.
Project intent
The main goal of the project is to ease development of projects working with compiled code (e.g. ROM hacking). As such, streaming features are currently deemphasized, although I may implement them at some later date.
Changelog
Version 0.11.0
(11 June 2026)
Major changes
- bitarray is now an optional dependency. bytemaker includes a pure-Python
BitVectorimplementation that is used automatically when bitarray is not installed; installbytemaker[speedups]to get the faster, C-backed bitarray implementation. Both implementations conform to the behavior specified inbitvector.pyiand are exercised by a shared, parametrized test suite.
Bugfixes
- Fixed
BitVector.from01raisingAttributeErrorfor sequences of"0"/"1"characters rather than strings - Fixed slice and index-list assignment raising
TypeErrorforstr(and otherBitsConstructible) values - Fixed
BitVector.replacenever terminating whenoldis empty - Fixed construction from
BitsCastableobjects padding sub-byte__Bits__results up to whole bytes
Version 0.10.2
(1 June 2026)
Bugfixes
- Fixed aggregate (de)serialization raising
NameErrorfor dataclasses defined underfrom __future__ import annotations(PEP 563). Field type annotations are now resolved withtyping.get_type_hintsin the defining module's namespace instead of a bareevalin bytemaker's namespace, so stringized annotations such as"SInt16"resolve correctly incount_bits_in_aggregate_type,to_bits_aggregate,from_bits_aggregate,to_bytes_aggregate, andfrom_bytes_aggregate.
Version 0.10.1
(13 April 2026)
Breaking changes
- Replaced
reverse_endianness: boolparameter withendianness: Literal["big", "little"] = "big"across all conversion functions (to_bytes_individual,from_bytes_individual,to_bytes_aggregate,from_bytes_aggregate,bytes_to_bittype,bytes_to_pytype,ctype_to_bytes,bytes_to_ctype,ctype_to_bits,bits_to_ctype,pytype_to_bytes). The old boolean was relative and had inconsistent defaults. The new parameter is absolute, self-documenting, and matches Python conventions (int.from_bytesbyteorder). StructPackedBitTypenow stores bits in canonical big-endian order internally. Endianness is applied only at the bytes boundary byBitType.__bytes__(). This matches the stated design: "while the types have endianness, their underlying bit representations do not."- For ctypes, endianness reversal now checks
endianness != sys.byteorderinstead of a hardcoded boolean, making it correct on both little-endian and big-endian platforms.
Version 0.9.3
(12 April 2026)
Bugfixes
- Made the conversions subpackage exposed
- Fixed missing return statements in
String.codepoint_changesandString._reverse_codepoint_changesproperties (first call always returned None) - Fixed
to_bytes_individualcalling nonexistentBitType.to_bytes()method - Fixed
from_bytes_individualpassing unsupportedreverse_endiannessparameter tobytes_to_bittypeandbytes_to_pytype - Fixed double endianness reversal in
from_bytes_aggregate - Fixed
from_bytes_aggregateusing bit counts to slice byte objects (e.g. taking 32 bytes for a 32-bit field) - Fixed missing
field_typeassignment infrom_bytes_aggregatedataclass field loop - Fixed
count_bytes_in_unit_typeusing wrong ceiling division - Fixed
StructPackedBitType.valuegetter ignoring its own padding for non-multiple-of-8 bit types - Fixed
StructPackedBitType.__bytes__applying endianness reversal on top of struct packing, which already handles endianness - Fixed
to_bytes_aggregatecrashing on certain nested dataclasses
Other
- Replaced debug
print()statements inBitVector.from_chararraywithlogging.debug()
Version 0.9.2
(29 August 2024)
Bugfixes
pyproject.toml did not include subpackages for PyPi, so importing from PyPi was failing to include bitvector or bittypes
Other
Relaxed typechecking of inputs in bitvector.py from Literal[0, 1] to int when in sequences. This change allows users to use e.g. [0] * 5 without typecheckers having problems.
Removed some outdated references to BitArray in BitVector.pyi.
Version 0.9.1
Added magic methods to BitTypes classes.
Removed BitTypes' __hash__ functionality
Modified BitTypes' __repr__ to include endianness
Version 0.9.0
Bits is now BitVector. Its API has been changed to be much more similar to bytearray. To that end, inline methods and alternative syntaxes have been winnowed where possible.
ytypes are now BitTypes, and, rather than extending from Bits, now contain BitVectors. This change was made so that, in the long run, uint:UInt8 + sint:SInt8 wouldn't be the same as concatenation, and so that str24[1] would grab the second element.
BitTypes now have full support for endianness when casting to bytes. Note that while the types have endianness, their underlying bit representations do not (because that wouldn't make much sense!). Usage of As of v0.10.1, ctypes conversions use ctypes still assumes development is done on a little-endian machine.sys.byteorder to detect the platform endianness, so they work correctly on both little-endian and big-endian machines.
Upcoming deprecations:
(any BitType).to_bits() and (any BitType).from_bits(). This behavior should instead be replicated by (any BitType).bits and (any BitType)(bits)
Version 0.8.3
Metadata
Release files for bytemaker 0.12.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| bytemaker-0.12.0.tar.gz | 70.4 kB | With provenance | Details for bytemaker-0.12.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| bytemaker-0.12.0-py3-none-any.whl | Python 3 | none | any | Details for bytemaker-0.12.0-py3-none-any.whl |
Total release size: 146.0 kB
Release files / bytemaker-0.12.0.tar.gz
| Download URL | bytemaker-0.12.0.tar.gz |
|---|---|
| Size | 70.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
24a65bf6a5de384dc0abbbc26e931729119d8b2e50568c6b3ce2530373249b0b
|
|
BLAKE2b-256 checksum How to use checksums |
618326adf99413183d6f077cc96d754839f5a483ebc6b52753b87890f8213a6e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 21, 2026.
Transparency logRelease files / bytemaker-0.12.0-py3-none-any.whl
| Download URL | bytemaker-0.12.0-py3-none-any.whl |
|---|---|
| Size | 75.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
92ba06d2cf3250d5bd04223690b6701a96cfc5e84a882b203a1f0b4b1dea67aa
|
|
BLAKE2b-256 checksum How to use checksums |
1a0b2b4f17fdf3cd911cb2dba164d0cabbe7d550be7b7d55195f060e7ea72f1d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 21, 2026.
Transparency logSecurity for bytemaker 0.12.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for bytemaker-0.12.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.