Structure of uniquely named and typed members data store and transform.
[plum.structure] Module Reference¶
This module provides classes for defining a custom data store type that also
acts as a bytes transform to convert data within a data store instance into
bytes and to convert bytes back into a data store instance. Similar to
Python’s dataclasses
, member properties added to a class definition
control the generation of special methods (e.g. __init__()
, __repr__
,
etc.) to avoid the need to write that code by hand.
The examples shown on this page require the following setup:
>>> from plum.bigendian import uint8
>>> from plum.structure import Structure, member
>>> from plum.structure import dimmed_member, sized_member
>>> from plum.utilities import pack, unpack
Basic Usage¶
To create a data store type, subclass the Structure
class and add
structure data members as class attributes in the class definition
with the Member
class to define each member’s format. The fmt
parameter accepts anything that supports the plum
bytes
transformation API (e.g. transform instances or even a data store
class such as another structure). For example:
>>> class MyStruct(Structure):
... m1: int = member(fmt=uint8)
... m2: int = member(fmt=uint8)
...
You may include other class attributes or methods in the class
definition. The Structure
metaclass which generates the
initializer pays attention only to the class attributes that are a
Member
(or a subclass of it). The generated initializer accepts
keyword only argument values for each structure member. Access
structure member values as an attribute or by indexing.
>>> struct = MyStruct(m1=1, m2=2)
>>> struct
MyStruct(m1=1, m2=2)
>>> struct.m1
1
>>> struct[0]
1
Then use the structure class to specify a format when using pack()
and unpack()
utility functions or other applications where a
format is needed:
>>> fmt = [uint8, MyStruct]
>>>
>>> pack([0, MyStruct(m1=1, m2=2)], fmt)
b'\x00\x01\x02'
>>>
>>> unpack(fmt, b'\x00\x01\x02')
[0, MyStruct(m1=1, m2=2)]
Since structure data store types support the plum
bytes transformation
API, packing a structure instance does not require a format to be specified:
>>> pack(MyStruct(m1=1, m2=2))
b'\x01\x02'
The structure data store type accepts any iterable of member values during packing. The following example packs a simple list:
>>> pack([1, 2], fmt=MyStruct)
b'\x01\x02'
Member Default¶
Use the default
argument in the member definition to specify a default
value for the member. Instantiations use the default value for the member
when one was not provided:
>>> class MyStruct(Structure):
... m1: int = member(fmt=uint8)
... m2: int = member(fmt=uint8, default=2)
...
>>> struct = MyStruct(m1=1)
>>> struct
MyStruct(m1=1, m2=2)
>>>
>>> pack(struct)
b'\x01\x02'
Ignore Member¶
To ignore certain members when comparing structure instances, use
the ignore
argument in the member definition:
>>> class MyStruct(Structure):
... m1: int = member(fmt=uint8)
... m2: int = member(fmt=uint8, ignore=True)
...
>>> struct_a = MyStruct(m1=1, m2=0)
>>> struct_b = MyStruct(m1=1, m2=99)
>>>
>>> struct_a == struct_b
True
To guarantee an exact comparison, compare against a list or use the
asdict()
method:
>>> struct_a == list(struct_b)
False
>>>
>>> struct_a.asdict() == struct_b.asdict()
False
Read Only Member¶
To block against changing the value of a structure member when setting
the structure member attribute, pass readonly=True
when defining
the member property:
>>> class MyStruct(Structure):
... m1: int = member(fmt=uint8)
... m2: int = member(fmt=uint8, readonly=True)
...
>>> struct = MyStruct(m1=1, m2=2)
>>> try:
... struct.m2 = 99
... except AttributeError:
... print("AttributeError: can't set attribute 'm2'")
...
AttributeError: can't set attribute 'm2'
Advanced Features¶
The following tutorials detail additional structure features:
Tutorial Description Bit Field Structure Member comprises partial bytes Dimensioned Array Structure Member array member dims controlled by separate dims member Dynamically Typed Structure Member member type controlled by separate type member Sized Structure Member member size controlled by separate size member
API Reference¶
-
class
plum.structure.
Structure
¶ Structured data store type.
-
byteorder
= 'little'¶
-
dump
¶ Summary containing details of bytes and layout.
-
nbytes
= 0¶
-
asdict
() → Dict[str, Any]¶ Return structure members in dictionary form.
Returns: structure members
-
classmethod
pack
(value: Any) → bytes¶ Pack value as formatted bytes.
Raises: PackError
if type error, value error, etc.
-
classmethod
pack_and_dump
(value: Any) → Tuple[bytes, plum.dump.Dump]¶ Pack value as formatted bytes and produce bytes summary.
Raises: PackError
if type error, value error, etc.
-
classmethod
unpack
(buffer: bytes) → Any¶ Unpack value from formatted bytes.
Raises: UnpackError
if insufficient bytes, excess bytes, or value error
-
classmethod
unpack_and_dump
(buffer: bytes) → Tuple[Any, plum.dump.Dump]¶ Unpack value from bytes and produce packed bytes summary.
Raises: UnpackError
if insufficient bytes, excess bytes, or value error
-
-
plum.structure.
bitfield_member
(doc: str = '', *, size: int, lsb: Optional[int] = None, typ: type = <class 'int'>, signed: bool = False, default: Any = NO_DEFAULT, ignore: bool = False, readonly: bool = False, compute: bool = False, nbytes: int = 0, argrepr: Optional[str] = None) → Any¶ Bit field structure member definition.
Parameters: - doc – accessor documentation string
- size – bit field width (in bits)
- lsb – least significant bit position
- signed – interpret as signed integer
- typ – field type (e.g.
IntEnum
subclass) - default – initializer default value
- ignore – ignore member during comparisons
- readonly – block setting member attribute
- compute – initializer defaults to compute based on another member
- nbytes – bytes occupied by this bit field and ones that follow (0 => calculate)
- argrepr – format to represent member argument in structure repr
-
plum.structure.
dimmed_member
(doc: str = '', *, fmt: plum.array.ArrayX, dims: plum.structure.member.Member, default: Any = NO_DEFAULT, ignore: bool = False, readonly: bool = False, argrepr: Optional[str] = None) → Any¶ Define variably dimensioned array structure member.
Parameters: - doc – accessor documentation string
- fmt – array transform (or factory function)
- dims – array dimensions member definition
- default – initializer default value
- ignore – ignore member during comparisons
- readonly – block setting member attribute
- argrepr – format to represent member argument in structure repr
-
plum.structure.
member
(doc: str = '', *, default: Any = NO_DEFAULT, ignore: bool = False, readonly: bool = False, compute: bool = False, argrepr: Optional[str] = None, fmt: Union[Callable[[Type[Any]], Union[plum.transform.Transform, Type[plum.data.Data]]], plum.transform.Transform, Type[plum.data.Data]], fmt_arg: Optional[Member] = None) → Any¶ Define structure member properties.
Parameters: - doc – accessor documentation string
- default – initializer default value
- ignore – ignore member during comparisons
- readonly – block setting member attribute
- compute – initializer defaults to compute based on another member
- argrepr – format to represent member argument in structure repr
- fmt – member format
- fmt_arg – member property to use as format factory argument
-
plum.structure.
sized_member
(doc: str = '', *, fmt: Union[plum.transform.Transform, Type[plum.data.Data]], size: Any, ratio: float = 1, offset: int = 0, default: Any = NO_DEFAULT, ignore: bool = False, readonly: bool = False, argrepr: Optional[str] = None) → Any¶ Sized structure member definition.
Parameters: - doc – accessor documentation string
- fmt – member format, default uses type annotation
- size – member property which controls size
- ratio (int) – number of bytes per increment of size member
- offset (int) – difference in size (in bytes)
- default – initializer default value
- ignore – ignore member during comparisons
- readonly – block setting member attribute
- argrepr – format to represent member argument in structure repr