Types and specifications

Numeric annotations and specifications are imported from bytespec.types; datetime and UUID come from the standard library. Values remain ordinary Python objects. Practical examples: Numbers and other types.

Supported annotations

The table describes automatic representation selection. A custom type can be supported using an explicit codec or configure_codecs().

Python type / annotation

Representation

Settings

UInt8/16/32/64, Int8/16/32/64

Fixed-width integer, matching …Codec

The model’s byte order

int

VarIntCodec: ZigZag + varint in the Int64 range

Choose a numeric annotation for a different format

Float32, Float64

IEEE 754 binary32/binary64

The model’s byte order

VarUInt, VarInt

Unsigned varint / ZigZag + varint, 1–10 bytes

Independent of byte order

bool

BoolCodec: one byte, 0/1

None

str

StrCodec: byte length followed by text

encoding, prefix_length

bytes

BytesCodec: length followed by bytes

prefix_length

datetime.datetime

DatetimeCodec: an isoformat() string

encoding, prefix_length

uuid.UUID

UUIDCodec: exactly 16 bytes from UUID.bytes

No prefix; independent of byte order

A subclass of str and Enum

EnumCodec + StrCodec: the string .value

encoding, prefix_length

IntEnum / a subclass of int and Enum

EnumCodec + VarIntCodec: the numeric .value

Use an explicit EnumCodec for a different representation

list[T]

ListCodec: byte length followed by items

The list prefix; type T is configured separately

A subclass of ProtoModel

ModelCodec: its own header without Constructor

The nested class’s settings

T | None / Optional[T]

The value of T when the presence bit is set

field(flag=...) is required

Annotated[T, ...]

The representation of T with one supported specification

The specifications below

By default, text uses UTF-8 and length prefixes for variable-length data occupy 4 bytes. StrEnum works on Python versions where it is available. A plain Enum that does not inherit from str or int requires an explicit codec.

There is no built-in selection for bare float, list, datetime.date, datetime.time, or for dict, tuple, set, Any, Literal, and unions of multiple non-None types. list[T | None] is not supported.

Integers

bytespec.types.UInt8

alias of Annotated[int, IntegerSpec(bits=8, signed=False)]

bytespec.types.UInt16

alias of Annotated[int, IntegerSpec(bits=16, signed=False)]

bytespec.types.UInt32

alias of Annotated[int, IntegerSpec(bits=32, signed=False)]

bytespec.types.UInt64

alias of Annotated[int, IntegerSpec(bits=64, signed=False)]

bytespec.types.Int8

alias of Annotated[int, IntegerSpec(bits=8, signed=True)]

bytespec.types.Int16

alias of Annotated[int, IntegerSpec(bits=16, signed=True)]

bytespec.types.Int32

alias of Annotated[int, IntegerSpec(bits=32, signed=True)]

bytespec.types.Int64

alias of Annotated[int, IntegerSpec(bits=64, signed=True)]

Float and varint

bytespec.types.Float32

alias of Annotated[float, FloatSpec(bits=32)]

bytespec.types.Float64

alias of Annotated[float, FloatSpec(bits=64)]

bytespec.types.VarUInt

alias of Annotated[int, VarIntSpec(signed=False)]

bytespec.types.VarInt

alias of Annotated[int, VarIntSpec(signed=True)]

VarUInt is limited to 0 .. 2**64 - 1; VarInt is limited to -2**63 .. 2**63 - 1. The canonical representation is described in Binary / wire format. Float32 may round the value; there is no separate restriction on NaN or infinities. BoolCodec.encode() uses the value’s truthiness, while the decoder strictly accepts only bytes 0/1.

Annotated specifications

class bytespec.types.IntegerSpec(bits: Literal[8, 16, 32, 64], signed: bool)[source]

Select a fixed-width integer in Annotated[int, ...].

Parameters:
  • bits – The number of bits: 8, 16, 32, or 64.

  • signed – Allow negative values (signed representation).

A fixed-width integer: bits is 8, 16, 32, or 64; signed selects signedness.

class bytespec.types.FloatSpec(bits: Literal[32, 64])[source]

Select an IEEE 754 number in Annotated[float, ...].

Parameters:

bits – The number of bits: 32 or 64. Float32 rounds a Python float to its representation.

An IEEE 754 number: bits is 32 or 64.

class bytespec.types.VarIntSpec(signed: bool)[source]

Select a varint in Annotated[int, ...].

Parameters:

signed – If True, use ZigZag and the Int64 range; if False, use an unsigned varint and the UInt64 range.

A varint; with signed=True, ZigZag is applied first.

class bytespec.types.CodecSpec(prefix_length: bytespec.models.PrefixLength | None = None, encoding: str | None = None, codec: ICodec[Any] | None = None)[source]

Define reusable field settings using Annotated.

Parameters:
  • prefix_length – Prefix size: 1, 2, 4, or 8 bytes, or VarUInt. None leaves the field setting unchanged; VarInt is not supported.

  • encoding – The text encoding. A nonempty value replaces the field encoding.

  • codec – A ready-to-use codec instance instead of automatic selection.

Note

One supported specification is allowed per Annotated. An explicit field(codec=...) takes precedence over CodecSpec.

Settings for reuse through Annotated. codec accepts an ICodec instance. Setting precedence: Strings, lengths, and field settings.

bytespec.types.Spec = bytespec.types.spec.IntegerSpec | bytespec.types.spec.FloatSpec | bytespec.types.spec.VarIntSpec | bytespec.types.spec.CodecSpec

A union of the four supported specification types.

Combining settings

Only one recognized specification is allowed in a single Annotated; unrelated metadata is ignored. Numeric annotations already contain a spec: for example, UInt16 is Annotated[int, IntegerSpec(16, signed=False)]. A second spec cannot be added using an outer Annotated.

CodecSpec overwrites the field’s prefix_length if it is not None, and encoding if it is nonempty; a codec supplied in the spec is selected explicitly. field(codec=...) is applied before metadata and takes precedence. Other field() parameters do not reconfigure a ready-to-use codec instance.

Use a custom codec to specify an arbitrary struct format for a field; see Codecs: custom formats and types. Replacing the codec fully determines the decode result: the logical type annotation does not automatically convert it back.

Helper annotation

bytespec.types.UIntUnion

Union беззнаковых числовых аннотаций для типизации Python-кода. Сам по себе не является допустимой аннотацией сериализуемого поля: автоматический выбор между несколькими числовыми форматами не поддержан. alias of Annotated[int, IntegerSpec(bits=16, signed=False)] | Annotated[int, IntegerSpec(bits=32, signed=False)] | Annotated[int, IntegerSpec(bits=64, signed=False)] | Annotated[int, IntegerSpec(bits=8, signed=False)]