Package: dataclasses-struct
dataclasses-structA simple Python package that combinesdataclasseswithstructfor packing and
unpacking Python dataclasses to fixed-lengthbytesrepresentations.fromtypingimportAnnotated# use typing_extensions on Python <3.9importdataclasses_structasdcs@dcs.dataclass()classTest:x:int# or dcs.I64, i.e., a signed 64-bit integery:float# or dcs.F64, i.e., a double-precision (64-bit) floating pointz:dcs.U8# unsigned 8-bit integers:Annotated[bytes,10]# fixed-length byte array of length 10@dcs.dataclass()classContainer:test1:Testtest2:Test>>>dcs.is_dataclass_struct(Test)True>>>t1=Test(100,-0.25,0xff,b'12345')>>>dcs.is_dataclass_struct(t1)True>>>t1Test(x=100,y=-0.25,z=255,s=b'12345')>>>packed=t1.pack()>>>packedb'd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd0\xbf\xff12345\x00\x00\x00\x00\x00'>>>Test.from_packed(packed)Test(x=100,y=-0.25,z=255,s=b'12345\x00\x00\x00\x00\x00')>>>t2=Test(1,100,12,b'hello, world')>>>c=Container(t1,t2)>>>Container.from_packed(c.pack())Container(test1=Test(x=100,y=-0.25,z=255,s=b'12345\x00\x00\x00\x00\x00'),test2=Test(x=1,y=100.0,z=12,s=b'hello, wor'))InstallationThis package is available on pypi:pip install dataclasses-structTo work correctly withmypy, an extension is
required; add to yourmypy.ini:[mypy]plugins=dataclasses_struct.ext.mypy_pluginUsagefromtypingimportAnnotated# use typing_extensions on Python <3.9importdataclasses_structasdcsendians=(dcs.NATIVE_ENDIAN_ALIGNED,# uses system endianness and alignmentdcs.NATIVE_ENDIAN,# system endianness, packed representationdcs.LITTLE_ENDIAN,dcs.BIG_ENDIAN,dcs.NETWORK_ENDIAN,)@dcs.dataclass(endians[0])# if no endian provided, defaults to NATIVE_ENDIAN_ALIGNEDclassTest:# Single char type (must be bytes)single_char:dcs.Charsingle_char_alias:bytes# alias for Char# Booleanbool_1:dcs.Boolbool_2:bool# alias for Bool# Iegersint8:dcs.I8uint8:dcs.U8int16:dcs.I16uint16:dcs.U16int32:dcs.I32uint32:dcs.U32uint64:dcs.U64int64:dcs.I64int64_alias:int# alias for I64# Only supported with NATIVE_ENDIAN_ALIGNEDunsigned_size:dcs.Sizesigned_size:dcs.SSizepointer:dcs.Pointer# Floating point typessingle_precision:dcs.F32# equivalent to float in Cdouble_precision:dcs.F64# equivalent to double in Cdouble_precision_alias:float# alias for F64# Byte arrays: values shorter than size will be padded with b'\x00'array:Annotated[bytes,100]# an array of length 100# Pad bytes can be added before and after fields: a b'\x00' will be# inserted for each pad byte.pad_before:Annotated[int,dcs.PadBefore(4)]pad_after:Annotated[int,dcs.PadAfter(2)]pad_before_and_after:Annotated[int,dcs.PadBefore(3),dcs.PadAfter(2)]# Also supports nesting dataclass-structs@dcs.dataclass(endians[0])# endianness of contained classes must matchclassContainer:contained1:Test# supports PadBefore and PadAfter as well:contained2:Annotated[Test,dcs.PadBefore(10)]Decorated classes are transformed to a standard Pythondataclasswith boilerplate__init__,__repr__,__eq__etc. auto-generated. Additionally, two methods
are added to the class:pack, a method for packing an instance of the class tobytes, andfrom_packed, a class method that returns a new instance of the
class from its packedbytesrepresentation.A class or object can be check to see if it is a dataclass-struct using theis_dataclass_structfunction. Theget_struct_sizefunction will return
the size in bytes of the packed representation of a dataclass_struct class
or an instance of one.An additional class attribute,__dataclass_struct__. Thestructformat
string, packed
size, and endianness can be accessed like so:>>>Test.__dataclass_struct__.format'@cc??bBhHiIQqqNnPfdd100s4xqq2x3xq2x'>>>Test.__dataclass_struct__.size234>>>Test.__dataclass_struct__.endianness'@'Default attribute values will be validated against their expected type and
allowable value range. For example,importdataclasses_structasdcs@dcs.dataclass()classTest:x:dcs.U8=-1will raise aValueError. This can be disabled by passingvalidate=Falseto
thedataclasses_struct.dataclassdecorator.