3.2.1.5. Templates#
A specialized form of structs are templates, which are basically generic Python classes. Think of them
as blueprints for your final classes/structs that contain placeholders for actual types. As in C++, a
template needs type arguments, in this case we will name them TemplateTypeVar.
Actually, there are two different types of type variables:
- Required:
These variables are required when creating a new struct based on the template and they can be used as positional arguments within the type derivation.
- Positional:
These arguments are usable only as keyword arguments and are may be optional if a default value is supplied.
These template type variables can be created using simple variable definitions:
>>> A = TemplateTypeVar("A")
Important
A template class is not a struct definition. It specifies a blueprint for the final class.
A template class is defined like a struct, union or bitfield class, but without being a dataclass nor storing a struct instance.
>>> @template(A, "B")
... class FormatTemplate:
... foo: A
... bar: B
... baz: uint32
...
The defined class then can be used to create new classes based on the provided class structure. For instance,
>>> Format = derive(FormatTemplate, A=uint32, B=uint8)
>>> Format
<class '__main__.__4BE4F2562B65393CFormatTemplate'>
will return an anonymous class (in this case). Normally, caterpillar tries to infer the
variable name from the current module (if name=...). In summary, every time
derive() is called, a new class will be created if not already
defined.
The current implementation will place template information about the current class using
a special class attribute: __template__.
To support sub-classes of templates, we can declare a derived class as partial:
>>> Format32 = derive(FormatTemplate, A=uint32, partial=True)
Again, the resulting class is not a struct, but another template class.
Developer’s note
By now, a template won’t copy existing field documentation comments. Therefore, you can’t display inherited members using sphinx.