In implementation of an interop layer with several other languages I have run into the question of how to represent fixed and max-length sequences. While for Python it doesn't matter much the full type info needs to be available for the other languages. The user-facing API should look as follows:
@dataclass
class MyStruct:
name: bounded_str[12] # here 12 is a max length
data: sequence[int8, 20] # here 20 is the max length
other_data: array[float32, 10] # here 10 is a fixed length
Now I have no problem getting this to work with normal python. I let sequence
and array
generate Annotated
types as follows:
class ArrayMeta(type):
def __getitem__(cls, tup):
if type(tup) != tuple or len(tup) != 2 or type(tup[1]) != int:
return TypeError("An array takes two arguments: a subtype and a constant length.")
return Annotated[Sequence[tup[0]], array(*tup)]
class array(metaclass=ArrayMeta):
def __init__(self, subtype, length):
self.subtype = subtype
self.length = length
This leaves the dataclass with a perfectly acceptable Annotated[Sequence[subtype], ...]
and I can inspect the annotation with get_type_hints
and determine the 'true' type needed for interop, generating validators/serializers etc.
Now the problem comes in when we bring Mypy into the mix. Mypy doesn't recognize the array
type as valid and that is fair enough. However, any of my attempts at making a valid version have been stumped so far, as Generic
will not take a value types:
T = TypeVar('T')
V = TypeVar('V')
class MyArray(Protocol, Generic[T, V]):
def __getitem__(self, key: int) -> T: ...
def __len__(self):
return V
a: MyArray[int, 5] = [0, 1, 2, 3, 4]
>>> TypeError: Parameters to generic types must be types. Got 5.
Is there a way to make Mypy happy about these sequence
and array
types?