11import typing
22import collections
33import dataclasses
4- from typing import Annotated , NamedTuple , Any
4+ from typing import Annotated , NamedTuple , Any , TypeVar , TYPE_CHECKING
55
66class Vector (NamedTuple ):
77 dim : int | None
@@ -21,6 +21,28 @@ def __init__(self, key: str, value: Any):
2121Range = Annotated [tuple [int , int ], TypeKind ('Range' )]
2222Json = Annotated [Any , TypeKind ('Json' )]
2323
24+ R = TypeVar ("R" )
25+
26+ if TYPE_CHECKING :
27+ Table = Annotated [list [R ], TypeKind ('Table' )]
28+ List = Annotated [list [R ], TypeKind ('List' )]
29+ else :
30+ # pylint: disable=too-few-public-methods
31+ class Table : # type: ignore[unreachable]
32+ """
33+ A Table type, which has a list of rows. The first field of each row is the key.
34+ """
35+ def __class_getitem__ (cls , item : type [R ]):
36+ return Annotated [list [item ], TypeKind ('Table' )]
37+
38+ # pylint: disable=too-few-public-methods
39+ class List : # type: ignore[unreachable]
40+ """
41+ A List type, which has a list of ordered rows.
42+ """
43+ def __class_getitem__ (cls , item : type [R ]):
44+ return Annotated [list [item ], TypeKind ('List' )]
45+
2446def _find_annotation (metadata , cls ):
2547 for m in iter (metadata ):
2648 if isinstance (m , cls ):
@@ -43,6 +65,7 @@ def _dump_fields_schema(cls: type) -> list[dict[str, Any]]:
4365
4466def _dump_type (t , metadata ):
4567 origin_type = typing .get_origin (t )
68+ type_kind = _find_annotation (metadata , TypeKind )
4669 if origin_type is collections .abc .Sequence or origin_type is list :
4770 args = typing .get_args (t )
4871 elem_type , elem_type_metadata = _get_origin_type_and_metadata (args [0 ])
@@ -54,10 +77,16 @@ def _dump_type(t, metadata):
5477 'dimension' : vector_annot .dim ,
5578 }
5679 elif dataclasses .is_dataclass (elem_type ):
57- encoded_type = {
58- 'kind' : 'List' ,
59- 'row' : { 'fields' : _dump_fields_schema (elem_type ) },
60- }
80+ if type_kind is not None and type_kind .kind == 'Table' :
81+ encoded_type = {
82+ 'kind' : 'Table' ,
83+ 'row' : { 'fields' : _dump_fields_schema (elem_type ) },
84+ }
85+ else :
86+ encoded_type = {
87+ 'kind' : 'List' ,
88+ 'row' : { 'fields' : _dump_fields_schema (elem_type ) },
89+ }
6190 else :
6291 raise ValueError (f"Unsupported type: { t } " )
6392 elif dataclasses .is_dataclass (t ):
@@ -66,7 +95,6 @@ def _dump_type(t, metadata):
6695 'fields' : _dump_fields_schema (t ),
6796 }
6897 else :
69- type_kind = _find_annotation (metadata , TypeKind )
7098 if type_kind is not None :
7199 kind = type_kind .kind
72100 else :
0 commit comments