API¶
This documentation assumes that you’re somewhat familiar with WTForms, since Minform is intentionally similar to (and substantively derived from) that project.
Minform provides a BinaryForm class, which subclasses from
wtforms.form.Form. Instead of subclassing
Form with wtforms.fields.Field instances
as class variables, you need to subclass BinaryForm, and give it
BinaryItem instances as class variables. The result will be a
Form with additional pack() and
unpack() methods.
Note
This documentation will often refer to bytes objects. This mostly
applies to Python 3; if you’re using Python 2, you can read bytes
as str.
| Python version | raw bytes type | unicode string type |
|---|---|---|
| Python 2 | str |
unicode |
| Python 3 | bytes |
str |
Base Classes¶
- class
minform.BinaryForm(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs)[source]¶Form with the power to serialize to and deserialize from packed bytes!
A
BinaryFormis used much like awtforms.form.Form. Instead ofwtforms.fields.Fieldinstances, however, the class members should be instances ofBinaryItem.When the class is created, the
BinaryItemclass members will be used, in order, to generate a binary protocol for serializing and deserializing instances of the form. Using theBinaryFormsubclass’sunpack()method will bind a form to the data represented by a buffer.
size¶int
The number of bytes in a packed buffer of data for this class.
order¶Byte ordering of numbers, etc. in corresponding buffers of packed data. See Byte Order for more.
pack(order=None)[source]¶Serialize this form’s bound data into packed bytes.
Parameters: order – byte order constant dictating the endianness of packed integers. If self.orderis set, this parameter will be ignored.Returns: bytes object with length self.sizeReturn type: bytes
pack_into(buffer, offset, order=None)[source]¶Pack data from this item into an existing buffer.
Parameters:
- classmethod
unpack(buffer, order=None)[source]¶
Parameters:
- buffer (bytes) – bytes object of length
size- order – byte order constant for integer endianness. If
orderis set, this parameter will be ignored.Returns: form bound to the data stored in the buffer
Return type: Raises:
ValueError– ifbufferhas the wrong size.
- classmethod
unpack_from(buffer, offset=0, order=None)[source]¶Unpack data from a specific portion of a buffer.
Parameters:
- buffer – a byte buffer (e.g. a
bytesobject) that contains the serialized data at some offset- offset (int) – the index in buffer where the serialized data starts
- order – see
unpack()
- class
minform.BinaryItem[source]¶Item that occupies a block of bytes in a
BinaryFormA number of
BinaryItemsubclasses have already been provided; see items for more.
size¶The number of bytes that will be used to store the item when the parent form is packed in a buffer.
Note
If you subclass
BinaryItem, you need to ensure that the object will have an appropriatesizeproperty, since it is used by the form to split up buffer data for unpacking, and to assembled packed data.
form_field¶This property is optional; for example,
BlankBytesinstances do not have aform_field. If present, it should be an instance ofwtforms.Field. This field will then become a member of the form, just like a field in awtforms.form.Form.
order¶byte order constant that will override the order of the containing form or field. This will only be necessary if you need to serialize/deserialize with mixed byte ordering.
pack(data, order=None)[source]¶Serialize a chunk of data into packed bytes.
Parameters:
- data – data to serialize, e.g. stored by a corresponding form field
- order – byte order constant dictating the endianness of packed integers. If
self.orderis set, this parameter will be ignored.Returns: bytes object with length
sizeReturn type: bytes
pack_into(buffer, offset, data, order=None)[source]¶Pack data from this item into an existing buffer.
Parameters:
unpack(buffer, order=None)[source]¶Deserialize packed bytes into data.
Parameters:
- buffer – bytes object of length
size- order – byte order constant for integer endianness. If
self.orderis set, this parameter will be ignored.Returns: data stored in the buffer
Raises:
ValueError– if buffer has the wrong size.
Binary Items¶
Blank Bytes¶
- class
minform.BlankBytes(size)[source]¶Add padding to a form when serialized.
The size argument will set the
size.A
BlankBytesinstance can be placed anywhere in the list of fields in aBinaryFormdefinition. It doesn’t matter what name you give it; when the form’s fields are processed, theBlankBytesobject itself will be removed from the class’s namespace.The corresponding bytes will be null when the form is packed, and ignored when a data buffer is unpacked. Likewise, the bytes in a packed buffer will be ignored, and unpacking blank bytes will always return
None.Because
BlankBytesobjects lack aform_fieldattribute, there will be no corresponding attribute in a parentBinaryForm‘s data.
Basic Binary Fields¶
- class
minform.BinaryField[source]¶
BinaryItemthat corresponds to a form field.Note
This class should not be instantiated directly. Instead, use one of its subclasses, described below.
The following classes all have
form_fieldattributes, and their constructors accept a superset of the construction parameters for awtforms.fields.Field. In general, constructor arguments whose names correspond toBinaryItemconstruction parameters will be passed in to the constructor for the correspondingwtforms.fields.Field. So, for example, you can set alabelfor HTML rendering, or add extravalidators.The only notable exceptions are the order and length parameters, which are used to set the byte order and length policy, and will not be passed through to the
Field.
- class
minform.BinaryBooleanField(label='', validators=None, order=None, **kwargs)[source]¶Store either
TrueorFalseasb'\x01'orb'\x00'(respectively).
size¶always
1
form_field¶A
wtforms.fields.BooleanFieldinstance.
- class
minform.CharField(label='', validators=None, order=None, **kwargs)[source]¶Store a single byte as a one-character
str(in Python 2) orbytesobject (in Python 3).
size¶always
1
form_field¶A
wtforms.fields.StringFieldinstance.
- class
minform.BinaryIntegerField(label='', validators=None, order=None, **kwargs)[source]¶This class should not be instantiated directly; instead, you should use one of its subclasses, which determine what kind of int is stored, and how. Those subclasses are:
Name size Min Max Int8Field1 -128 127 UInt8Field1 0 255 Int16Field2 -32768 32767 UInt16Field2 0 65535 Int32Field4 -231 231 - 1 UInt32Field4 0 232 - 1 Int64Field8 -263 263 - 1 UInt64Field8 0 264 - 1
form_field¶A
wtforms.fields.Integerfieldinstance.
- class
minform.Float32Field(label='', validators=None, order=None, **kwargs)[source]¶Store a
floatin four bytes.
size¶Always
4.
form_field¶A
wtforms.fields.FloatFieldinstance.
- class
minform.Float64Field(label='', validators=None, order=None, **kwargs)[source]¶Store a
floatin eight bytes.
size¶Always
8.
form_field¶A
wtforms.fields.FloatFieldinstance.
- class
minform.BytesField(label='', validators=None, max_length=None, length='automatic', order=None, **kwargs)[source]¶Store N bytes.
size¶The
sizeof aBytesFieldwithmax_lengthN varies based on the length argument used to construct it.If length is
FIXEDorAUTOMATIC,sizewill be N.If length is
EXPLICIT, there will be one or more extra bytes at the beginning of the packed data, which store the number of bytes used by the string. This will be the smallest number of bytes needed to store a number up tomax_length. So,sizecan be N+1, N+2, N+4, or N+8. (For more information, see the documentation forEXPLICIT.)
form_field¶A
wtforms.fields.StringFieldinstance.
Compound Binary Fields¶
These fields allow data to be nested. If your data may include several items with the same type, you can use a
BinaryFieldListto manage them. If you want to re-use a set of items (or nest a more complicated data type in aBinaryFieldList), you can use aBinaryFormFieldto do so.
- class
minform.BinaryFieldList(inner_field, label='', validators=None, max_entries=None, length='explicit', order=None, **kwargs)[source]¶Store a homogeneous list of information.
inner_field¶A
BinaryFieldinstance.
max_entries¶The maximum number of items that can be stored in the list.
size¶If
lengthisminform.FIXED, size will be equal tomax_size * inner_field.length.If
lengthisminform.EXPLICIT, size will beprefix_length + (max_size * inner_field.length). The value ofprefix_lengthfollows the documentation for Length.
form_field¶A
wtforms.fields.FieldListinstance.
- class
minform.BinaryFormField(form_class, label='', validators=None, order=None, **kwargs)[source]¶Nest one
BinaryForminside another.
form_class¶The
BinaryFormsubclass that describes the contents of this field. ABinaryFormFieldinstance will have the samesizeas itsform_class, and will pack and unpack data in the same ways.
form_field¶A
wtforms.fields.FormFieldinstance.
Custom BinaryItems¶
When creating a custom
BinaryItem, you need to be sure to include:
- A
sizeattribute. This is used to determine how many bytes will be required by theunpack()method, and how many will be expected to be returned by thepack()method. This attribute is required even if you write custompack()andBinaryItem.unpack()methods that don’t refer to it!- A
pack()method. The type ofdatashould be compatible with the type returned by theunpack()method (below).- An
unpack()method. You can expectbufto haveself.sizebytes when the method is invoked in the course of using aBinaryForm.
Length¶
The following constants are used as the length argument when
constructing a BytesField or a
BinaryFieldList; they control whether and how the packed
buffer signals the length of the data.
-
minform.FIXED¶ If the length is
FIXED, all of the packed information, including terminal null bytes, will be considered part of the data.fixed_bytes = BytesField(max_length=6, length=FIXED) fixed_bytes.unpack(b'foobar\0\0\0\0') == b'foobar\0\0\0\0' fixed_list = BinaryFieldList(UInt16Field(), max_entries=4, length=FIXED) fixed_list.unpack(b'\x12\x34\x56\x78\x9a\x00\x00\x00') == \ [0x1234, 0x5678, 0x9a00, 0x0000]
-
minform.EXPLICIT¶ If length is
EXPLICIT, the packed buffer will start with an unsigned int that gives the length of the data (the number of bytes in aBytesField, or the number of entries in aBinaryFieldList). This prefix will be sized according to necessity; it will always be big enough to store themax_lengthormax_entriesof the field:maximum prefix type prefix size up to 255 UInt8 1 byte 256 - 65535 UInt16 2 bytes 65535 - 4294967296 UInt32 4 bytes larger UInt64 8 bytes If the max is larger than 264, a
ValueErrorwill be thrown. Here are some examples of the use ofEXPLICITlength fields:explicit_bytes = BytesField(max_length=9, length=EXPLICIT) # The first byte is the length of the string. explicit_bytes.pack(b'foobar') == b'\x06foobar\0\0\0' # If you manually include the null bytes, they'll be preserved. explicit_bytes.pack(b'foo\0\0\0') == b'\x06foo\0\0\0\0\0\0' # The unpacking process respects the explicit size given. explicit_bytes.unpack(b'\x05hey\0\0\0\0\0\0') == b'hey\0\0' explicit_bytes.unpack(b'\x02hey\0\0\0\0\0\0') == b'he' explicit_list = BinaryFieldList(UInt16Field, max_entries=4, length=EXPLICIT) explicit_list.pack([0x1234, 0x5678, 0x9abc, 0xdef0]) == \ b'\x04\x12\x34\x56\x78\x9a\xbc\xde\xf0' explicit_list.pack([0x1234, 0x5678]) == b'\x02\x12\x34\x56\x78\0\0\0\0'
-
minform.AUTOMATIC¶ The
AUTOMATICoption is only available forBytesField, and has very simple semantics: strings shorter than max_length will be padded with null bytes when packed, and null bytes will be trimmed from the end when unpacking a buffer.auto_bytes = BytesField(max_length=10, length=AUTOMATIC) auto_bytes.pack(b'1234554321') == b'1234554321' auto_bytes.pack(b'foobar') == b'foobar\0\0\0\0' auto_bytes.unpack(b'abc\0def\0\0\0') == b'abc\0def'
Byte order¶
minform.NATIVE¶
minform.LITTLE_ENDIAN¶
minform.BIG_ENDIAN¶
minform.NETWORK¶These constants operate according to the byte order constants from the struct module. The
minform.NATIVEconstant corresponds to the'='prefix, rather than'@'.Note
Setting the
orderproperty on aBinaryFormorBinaryItemwill override the order argument ofpack()andunpack()methods. For clarity, we recommend that you use either the attribute or thepack()/unpack()argument.Likewise, the
orderof aBinaryItemwill override theorderof the form or field that contains it.You can think of it as the order cascading down from the
BinaryForm.unpackorder argument, through the class, to each of that form’s items, and easy nested item, until it is overridden by anorderattribute.