Construct Typing
Construct Typing is an extension for the `construct` Python package, which provides a powerful declarative and symmetrical parser and builder for binary data. It enhances `construct` by adding comprehensive typing features, including `.pyi` stub files for the entire `construct` library (via `construct-stubs`) and additional strongly-typed classes (via `construct_typed`) for improved autocompletion and type hints, particularly for complex structures like `Struct` and `Enum`. The library is actively maintained, with regular releases, and the latest version is 0.7.0.
Warnings
- breaking The `construct-stubs` package underwent a significant rework in version `v0.6.0` to improve compatibility with `pyright>=v1.1.310`. This involved changes to the `__new__` and `__init__` methods of various constructs, which could cause type checking errors or unexpected runtime behavior for users relying on older `pyright` versions or specific type inference patterns.
- gotcha When using `DataclassStruct` or similar strongly typed constructs for building binary data, you must provide an instance of the corresponding `dataclass` (e.g., `Image(...)` in the quickstart) instead of a generic Python dictionary. `construct-typing` enforces the correct container type to leverage static type checking, departing from the dictionary-based building often used with standard `construct`.
- gotcha The `construct_typed` package, which provides the core enhanced typing features (like `DataclassStruct` and `TEnum`), is explicitly marked as an "EXPERIMENTAL VERSION" in the official documentation. While actively developed, this implies that its API or behavior might be subject to non-backward compatible changes in future minor or patch releases.
- gotcha While `construct-typing` aims for compatibility with both `mypy` and `pyright`, these static type checkers can exhibit semantic differences, especially with complex type annotations, overloads, or in scenarios with partially untyped code. Users might encounter discrepancies in reported errors or warnings between the two tools.
Install
-
pip install construct-typing
Imports
- DataclassStruct
from construct_typed import DataclassStruct
- TEnum
from construct_typed import TEnum
- csfield
from construct_typed import csfield
- DataclassMixin
from construct_typed import DataclassMixin
- construct
import construct as cs
Quickstart
import dataclasses
import typing as t
from construct import Array, Byte, Const, Int8ub, this
from construct_typed import DataclassMixin, DataclassStruct, TEnum, csfield
# Define a typed Enum
class Orientation(TEnum, Int8ub):
HORIZONTAL: t.ClassVar[int] = 0
VERTICAL: t.ClassVar[int] = 1
# Define a typed Struct using dataclasses
@dataclasses.dataclass
class Image(DataclassMixin):
signature: bytes = csfield(Const(b"BMP"))
orientation: Orientation = csfield(TEnum(Int8ub, Orientation))
width: int = csfield(Int8ub)
height: int = csfield(Int8ub)
pixels: t.List[int] = csfield(Array(this.width * this.height, Byte))
# Example usage: Parse binary data
img_bytes = b"BMP\x00\x03\x02\x07\x08\t\x0b\x0c\r"
parsed_image = Image.parse(img_bytes)
print(f"Parsed Image: {parsed_image}")
# Expected: Parsed Image: Image(signature=b'BMP', orientation=<Orientation.HORIZONTAL: 0>, width=3, height=2, pixels=[7, 8, 9, 11, 12, 13])
# Example usage: Build binary data from a typed object
built_bytes = Image.build(
Image(
orientation=Orientation.HORIZONTAL,
width=3,
height=2,
pixels=[7, 8, 9, 11, 12, 13]
)
)
print(f"Built Bytes: {built_bytes}")
# Expected: Built Bytes: b'BMP\x00\x03\x02\x07\x08\t\x0b\x0c\r'