PEP 593 introduced typing.Annotated
. I’ve been trying to wrap my head around how it’s supposed to be used, and I can’t make sense of it. Having read PEP 593, the discussions that preceded it [1][2], and the documentation on Annotated
, I still do not understand how Annotated
is meant to be used.
The first example in the PEP is
UnsignedShort = Annotated[int, struct2.ctype('H')]
SignedChar = Annotated[int, struct2.ctype('b')]
class Student(struct2.Packed):
# mypy typechecks 'name' field as 'str'
name: Annotated[str, struct2.ctype("<10s")]
serialnum: UnsignedShort
school: SignedChar
# 'unpack' only uses the metadata within the type annotations
Student.unpack(record)
# Student(name=b'raymond ', serialnum=4658, school=264)
The semantics of struct2
are not made clear, which prevents me from understanding the example [1].
I have tried to recreate something that behaves kind of like this example, and this is what I came up with:
import struct
from dataclasses import dataclass
from typing import Annotated
UnsignedShort = Annotated[int, struct.Struct("H")]
SignedChar = Annotated[int, struct.Struct("b")]
@dataclass
class Student:
name: Annotated[str, struct.Struct("<10s")]
serialnum: UnsignedShort
school: SignedChar
@classmethod
def unpack(cls, record: bytes) -> "Student":
unpacker = struct.Struct(
"".join(a.__metadata__[0].format for a in cls.__annotations__.values())
)
return cls(*unpacker.unpack(record))
record = b"raymond 2\x12@"
Student.unpack(record)
# Student(name=b'raymond ', serialnum=4658, school=64)
which works, but this line
"".join(a.__metadata__[0].format for a in cls.__annotations__.values())
is all kinds of awful. Is this really how I’m supposed to use Annotated
at runtime?
Like, is
Student
some kind of dataclass?name
,serialnumber
, andschool
do not seem to be class vars, despite syntactically appearing to be.struct2.Packed
apparently provides anunpack
method which, per the example, “only uses the metadata within the type annotations”. How? Also,school=264
does not fit in aSignedChar
. ↩︎