enhancement for the python package 'construct' that adds support for dataclasses.
Project description
construct-dataclasses
This small repository is an enhancement of the python package construct, which is a powerful tool to declare symmetrical parsers and builders for binary data. This project combines construct with python's dataclasses with support for nested structs.
Installation
You can install the package via pip or just copy the python file (__init__.py) as it is only one.
pip install construct-dataclasses
Usage
More usage examples are placed in the examples/ directory.
Define dataclasses
Before we can start declaring fields on a dataclass, the class itself has to be created. Currently, there are two ways on how to create a dataclass usable by this package.
-
Use the standard
@dataclassdecorator and create the parser instance afterwards (recommended for type checking):from construct_dataclasses import DataclassStruct @dataclasses.dataclass class Foo: ... # Create the parser manually parser = DataclassStruct(Foo) instance = parser.parse(...)
-
Use the
@dataclass_structdecorator to define a new dataclass and automatically create a parser instance that will be assigned as a class attribute:from construct_dataclasses import dataclass_struct @dataclass_struct class Foo: ... # Use the class-parser to parse instance = Foo.parser.parse(...) # or to build data = Foo.parser.build(instance)
Hint: Use
@containerto mimic a construct container instance if needed. That may be the case if you have to access an already parsed object of a custom type:@container @dataclasses.dataclass class ImageHeader: length: int = csfield(Int32ub) @dataclasses.dataclass class Image: header: ImageHeader = csfield(ImageHeader) data: bytes = csfield(Bytes(this.header.length))The access to
header.lengthwould throw an exception without the container annotation.
Define fields
This module defines a new way how to declare fields of a dataclass. In order to combine the python package construct with python's dataclasses module, this project introduces the following four methods:
-
csfield: Default definition of a field using a subcon or other dataclass@dataclass_struct class ImageHeader: signature: bytes = csfield(cs.Const(b"BMP")) num_entries: int = csfield(cs.Int32ul)
-
subcsfield: Definition of nested constructs that are contained in list-like structures.@dataclass_struct class Image: header: ImageHeader = csfield(ImageHeader) # dataclass reference width: int = csfield(cs.Int8ub) height: int = csfield(cs.Int8ub) # Note that we have to convert our dataclass into a struct using # the method "to_struct(...)" pixels: list[Pixel] = subcsfield(Pixel, cs.Array(this.width * this.height, to_struct(Pixel)))
-
tfield: a simple typed field that tries to return an instance of the given model class. Usesubcsfieldfor dataclass models,csenumfor simple enum fields andtfieldfor enum types in list fields.@dataclass_struct class ImageHeader: orientations: list[Orientation] = tfield(Orientation, cs.Enum(cs.Int8ul, Orientation))
-
csenum: shortcut for simple enum fields@dataclass_struct class ImageHeader: orientations: Orientation = csenum(Orientation, cs.Int8ul)
Convert dataclasses
By default, all conversion is done automatically if you don't use instances of SubContruct classes in your field definitions. If you have to define a subcon that needs a nested subcon, like Array or RepeatUntil and you would like to parse a dataclass struct, it is required to convert the defined dataclass into a struct.
-
to_struct: This method converts all fields defined in a dataclass into a singleStructorAlignedStructinstance.@dataclass_struct class Pixel: data: int = csfield(cs.Int8ub) pixel_struct: construct.Struct = to_struct(Pixel)
-
to_object: In order to use data returned byStruct.parse, this method can be used to apply this data and create a dataclass object from it.data = pixel_struct.parse(b"...") pixel = to_object(data, Pixel)
The complete example is shown below:
# Example modifed from here: https://github.com/timrid/construct-typing/
import dataclasses
import enum
import construct as cs
from construct_dataclasses import dataclass_struct, csfield, to_struct, subcsfield, csenum
class Orientation(enum.IntEnum):
NONE = 0
HORIZONTAL = 1
VERTICAL = 2
@dataclass_struct
class ImageHeader:
signature: bytes = csfield(cs.Const(b"BMP"))
orientation: Orientation = csenum(Orientation, cs.Int8ub)
@dataclass_struct
class Pixel:
data: int = csfield(cs.Int8ub)
@dataclass_struct
class Image:
header: ImageHeader = csfield(ImageHeader)
width: int = csfield(cs.Int8ub)
height: int = csfield(cs.Int8ub)
pixels: list[Pixel] = subcsfield(Pixel, cs.Array(this.width * this.height, to_struct(Pixel)))
obj = Image(
header=ImageHeader(
orientation=Orientation.VERTICAL
),
width=3,
height=2,
pixels=[Pixel(1), Pixel(2), Pixel(3), Pixel(4), Pixel(5), Pixel(6)]
)
print(Image.parser.build(obj))
print(Image.parser.parse(b"BMP\x02\x03\x02\x01\x02\x03\x04\x05\06"))
The expected output would be:
b'BMP\x02\x03\x02\x01\x02\x03\x04\x05\x06'
Image(
header=ImageHeader(signature=b'BMP', orientation=<Orientation.VERTICAL: 2>),
width=3, height=2,
pixels=[Pixel(data=1), Pixel(data=2), Pixel(data=3), Pixel(data=4), Pixel(data=5), Pixel(data=6)]
)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file construct_dataclasses-1.1.12.tar.gz.
File metadata
- Download URL: construct_dataclasses-1.1.12.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99cebee1d44cd9dbf51be9f401b47cbc1090af9d051f1c3bb4d3d641a6a3ab7b
|
|
| MD5 |
387191cb2cae7e2483ac7365e261c754
|
|
| BLAKE2b-256 |
65757c7deb10c092b637dc83ce86907c0f069c9d12092cd60ffd49e25b90c859
|
Provenance
The following attestation bundles were made for construct_dataclasses-1.1.12.tar.gz:
Publisher:
python-publish.yml on MatrixEditor/construct-dataclasses
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
construct_dataclasses-1.1.12.tar.gz -
Subject digest:
99cebee1d44cd9dbf51be9f401b47cbc1090af9d051f1c3bb4d3d641a6a3ab7b - Sigstore transparency entry: 747682730
- Sigstore integration time:
-
Permalink:
MatrixEditor/construct-dataclasses@328970d058ad1b831543e8883abbd228d2b3cffe -
Branch / Tag:
refs/tags/v1.1.12 - Owner: https://github.com/MatrixEditor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@328970d058ad1b831543e8883abbd228d2b3cffe -
Trigger Event:
release
-
Statement type:
File details
Details for the file construct_dataclasses-1.1.12-py3-none-any.whl.
File metadata
- Download URL: construct_dataclasses-1.1.12-py3-none-any.whl
- Upload date:
- Size: 22.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd221ddc18c72b9320254dc31d77b6bd505994ba6090b0cd3c2974778a51d7d8
|
|
| MD5 |
ede49112e3b94ba25c1386892a42ff89
|
|
| BLAKE2b-256 |
4160915e0c9796d8df1836958b7f4ccc1c6f92d92df36d9cbed966eb1dc73c28
|
Provenance
The following attestation bundles were made for construct_dataclasses-1.1.12-py3-none-any.whl:
Publisher:
python-publish.yml on MatrixEditor/construct-dataclasses
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
construct_dataclasses-1.1.12-py3-none-any.whl -
Subject digest:
dd221ddc18c72b9320254dc31d77b6bd505994ba6090b0cd3c2974778a51d7d8 - Sigstore transparency entry: 747682732
- Sigstore integration time:
-
Permalink:
MatrixEditor/construct-dataclasses@328970d058ad1b831543e8883abbd228d2b3cffe -
Branch / Tag:
refs/tags/v1.1.12 - Owner: https://github.com/MatrixEditor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@328970d058ad1b831543e8883abbd228d2b3cffe -
Trigger Event:
release
-
Statement type: