Struct Model#

TODO

Base classes#

class caterpillar.model.Sequence[source]#

Default implementation for a sequence of fields.

The native Python type mapped to this struct class is dict. To convert a dictionary into a sequence, you can either use the contructor directly or apply the type converter for this class:

>>> to_struct({'a': uint8})
Sequence(fields=['a'])
model: Any#

Specifies the target class/dictionary used as the base model.

arch: Arch | None#

Global architecture definition (will be inferred on all fields)

order: ByteOrder | None#

Optional configuration value for the byte order of a field.__annotations__

options: Set[Flag]#

Additional options specifying what to include in the final class.

field_options: Set[Flag]#

Global field flags that will be applied on all fields.

fields: List[Field | Tuple[_Action, None]]#

A list of all fields defined in this struct.

This attribute stores the fields in an ordered collection, whereby ordered means, relative to their initial class declaration position. These fields can be modified using add_field, del_field or the operators + and -.

has_option(option: Flag) bool[source]#

Check if the struct has a specific option.

Parameters:

option – The option to check.

Returns:

True if the struct has the specified option, else False.

add_field(name: str, field: Field, included: bool = False) None[source]#

Add a field to the struct.

Parameters:
  • name – The name of the field.

  • field – The field to add.

  • included – True if the field should be included, else False.

del_field(name: str, field: Field) None[source]#

Remomves a field from this struct.

Parameters:
  • name – The name of the field.

  • field – The field to remove.

class caterpillar.model.Struct[source]#

Represents a structured data model for serialization and deserialization.

Parameters:
  • model – The target class used as the base model.

  • order – Optional byte order for the fields in the structure.

  • arch – Global architecture definition (will be inferred on all fields).

  • options – Additional options specifying what to include in the final class.

class caterpillar.model.BitFieldGroup(size: int, pos: int, fields: Dict = None)[source]#
class caterpillar.model.BitField(model: type, order: ByteOrder | None = None, arch: Arch | None = None, options: Iterable[Flag] = None, field_options: Iterable[Flag] = None)[source]#
class caterpillar.model.UnionHook(struct_: Struct)[source]#

Implementation of a hook to simulate union types.

It will hook two methods of the target model type: __init__ and __setattr__. Because the constructor calls setattr for each attribute in the model, we have to intercept it before it gets called to set an internal status.

Internally, these two methods will be translated into __model_init__() and __model_setattr__(). Therefore, any class that implements these two methods can be used as a union hook.

struct: Struct#

The struct reference

max_size: int#

The static (cached) maximum size of the union

Standard functions#

caterpillar.model.struct(cls: Type[_T] | None = None, /, **kwds) Type[_T][source]#

Decorator to create a Struct class.

Parameters:
  • cls – The target class used as the base model.

  • options – Additional options specifying what to include in the final class.

  • order – Optional configuration value for the byte order of a field.

  • arch – Global architecture definition (will be inferred on all fields).

Returns:

The created Struct class or a wrapper function if cls is not provided.

caterpillar.model.union(cls: type = None, /, *, options: Iterable[Flag] = None, **kwds)[source]#

Decorator to create a Union class.

Parameters:
  • cls – The target class used as the base model.

  • options – Additional options specifying what to include in the final class.

  • order – Optional configuration value for the byte order of a field.

  • arch – Global architecture definition (will be inferred on all fields).

Returns:

The created Union class or a wrapper function if cls is not provided.

caterpillar.model.pack(obj: Any | _ContainsStruct, struct: _SupportsPack | None = None, **kwds) bytes[source]#

Pack an object into a bytes buffer using the specified struct.

Parameters:
  • obj – The object to pack.

  • struct – The struct to use for packing.

  • kwds – Additional keyword arguments to pass to the pack function.

Returns:

The packed bytes.

caterpillar.model.pack_into(obj: Any | _ContainsStruct, buffer: IOBase, struct: _StructLike | None = None, use_tempfile: bool = False, as_field: bool = False, **kwds) None[source]#

Pack an object into the specified buffer using the specified struct.

This function serializes an object (obj) into a given buffer, using a struct to define how the object should be packed. Optionally, the function can handle temporary files for packing, use a Field wrapper around the struct, and support additional keyword arguments. The packed data is written to the buffer.

Example 1: Packing an object into a bytes buffer >>> buffer = BytesIO() >>> my_obj = SomeObject() # Assume SomeObject is a valid object to be packed >>> pack_into(my_obj, buffer, struct=SomeStruct()) # Using a specific struct >>> buffer.getvalue() b”…”

Example 2: Packing into a file-like stream (e.g., file) >>> with open(‘packed_data.bin’, ‘wb’) as f: … pack_into(my_obj, f, struct=SomeStruct()) # Pack into a file

Example 3: Using as_field to wrap the struct in a Field before packing >>> buffer = BytesIO() >>> pack_into(42, buffer, struct=uint8, as_field=True) >>> buffer.getvalue() b”x2a”

Parameters:
  • obj – The object to pack (could be a plain object or a structure-like object).

  • buffer – The buffer to pack the object into (a writable stream such as BytesIO or a file).

  • struct – The struct to use for packing. If not specified, will infer from obj.

  • use_tempfile – Whether to use a temporary file for packing (experimental).

  • as_field – Whether to wrap the struct in a Field before packing.

  • kwds – Additional keyword arguments to pass to the pack function.

Raises:

TypeError – If no struct is specified and cannot be inferred from the object.

caterpillar.model.pack_file(obj: Any | _ContainsStruct, filename: str, struct: _StructLike | None = None, use_tempfile: bool = False, **kwds) None[source]#

Pack an object into a file using the specified struct.

Parameters:
  • obj – The object to pack.

  • filename – The name of the file to write to.

  • struct – The struct to use for packing.

  • kwds – Additional keyword arguments to pass to the pack function.

Returns:

None

caterpillar.model.unpack(struct: _SupportsUnpack | _ContainsStruct, buffer: bytes | IOBase, as_field: bool = False, **kwds) Any[source]#

Unpack an object from a bytes buffer or stream using the specified struct.

This function takes a struct that defines how data should be unpacked, a buffer (either bytes or a stream) containing the serialized data, and returns the unpacked object. If as_field is set to True, the struct is wrapped by a Field. Additional keyword arguments are passed to the root context as attributes.

Example: >>> buffer = b’x00x01x02x03’ >>> struct = SomeStruct() >>> unpack(struct, buffer) …

Parameters:
  • struct – The struct to use for unpacking (could be a SupportsUnpack or ContainsStruct object).

  • buffer – The bytes buffer or stream to unpack from.

  • as_field – Whether to wrap the struct in a Field transformer before unpacking.

  • kwds – Additional keyword arguments to pass to the unpack function.

Returns:

The unpacked object, which is the result of calling struct.__unpack__(context).

Raises:

TypeError – If the struct is not a valid struct instance.

caterpillar.model.unpack_file(struct: _StructLike | _ContainsStruct, filename: str, **kwds) Any[source]#

Unpack an object from a file using the specified struct.

Parameters:
  • struct – The struct to use for unpacking.

  • filename – The name of the file to read from.

  • kwds – Additional keyword arguments to pass to the unpack function.

Returns:

The unpacked object.

caterpillar.model.bitfield(cls: type = None, /, *, options: Iterable[Flag] = None, order: ByteOrder | None = None, arch: Arch | None = None, field_options: Iterable[Flag] = None)[source]#

Templates#

class caterpillar.model.TemplateTypeVar(name: str, **field_kwds)[source]#

Template type variable.

These specialised type variables are used within a template definition. They support most field operators. Therefore, they can be used in some situations where you need to adapt the field type at runtime.

>>> T = TemplateTypeVar("T")

Note that there is currently no support for inlined type variables, for example:

>>> @template(T)
... class Foo:
...     bar: Enum(Baz, T) # !!! throws an error

is not possible.

name: str#

The bound name of this type variable

field_kwds: Dict[str, Any]#

Arguments that will be passed to the created field instance.

caterpillar.model.istemplate(obj: Any) bool[source]#

Return true if the object is a template.

caterpillar.model.template(*args: str | TemplateTypeVar, **kwargs) Callable[[type], type][source]#

Defines required template type variables if necessary and prepares template class definition.

Returns:

a wrapper function that will be called with the class instance

Return type:

Callable[[type], type]

caterpillar.model.derive(template_ty: type, *tys_args, partial=False, name=None, union=False, **tys_kwargs) type[source]#

Creates a new struct class based on the given template class.

Parameters:
  • template_ty (type) – the template class

  • partial (bool, optional) – whether the resulting class is also a template, defaults to False

  • name (str | Ellipsis, optional) – the new class name, ... infers the outer variable name, defaults to None

Returns:

the derived type

Return type:

type