11import typing
22import collections
3+ import dataclasses
34from typing import Annotated , NamedTuple , Any
45
56class Vector (NamedTuple ):
@@ -31,18 +32,38 @@ def _get_origin_type_and_metadata(t):
3132 return (t .__origin__ , t .__metadata__ )
3233 return (t , ())
3334
34- def _type_to_json_value (t , metadata ):
35+ def _dump_fields_schema (cls : type ) -> list [dict [str , Any ]]:
36+ return [
37+ {
38+ 'name' : field .name ,
39+ 'value_type' : _dump_enriched_type (field .type ),
40+ }
41+ for field in dataclasses .fields (cls )
42+ ]
43+
44+ def _dump_type (t , metadata ):
3545 origin_type = typing .get_origin (t )
3646 if origin_type is collections .abc .Sequence or origin_type is list :
37- dim = _find_annotation (metadata , Vector )
38- if dim is None :
39- raise ValueError (f"Vector dimension not found for { t } " )
4047 args = typing .get_args (t )
41- origin_type , metadata = _get_origin_type_and_metadata (args [0 ])
42- type_json = {
43- 'kind' : 'Vector' ,
44- 'element_type' : _type_to_json_value (origin_type , metadata ),
45- 'dimension' : dim .dim ,
48+ elem_type , elem_type_metadata = _get_origin_type_and_metadata (args [0 ])
49+ vector_annot = _find_annotation (metadata , Vector )
50+ if vector_annot is not None :
51+ encoded_type = {
52+ 'kind' : 'Vector' ,
53+ 'element_type' : _dump_type (elem_type , elem_type_metadata ),
54+ 'dimension' : vector_annot .dim ,
55+ }
56+ elif dataclasses .is_dataclass (elem_type ):
57+ encoded_type = {
58+ 'kind' : 'Table' ,
59+ 'row' : _dump_fields_schema (elem_type ),
60+ }
61+ else :
62+ raise ValueError (f"Unsupported type: { t } " )
63+ elif dataclasses .is_dataclass (t ):
64+ encoded_type = {
65+ 'kind' : 'Struct' ,
66+ 'fields' : _dump_fields_schema (t ),
4667 }
4768 else :
4869 type_kind = _find_annotation (metadata , TypeKind )
@@ -61,15 +82,15 @@ def _type_to_json_value(t, metadata):
6182 kind = 'Float64'
6283 else :
6384 raise ValueError (f"type unsupported yet: { t } " )
64- type_json = { 'kind' : kind }
85+ encoded_type = { 'kind' : kind }
6586
66- return type_json
87+ return encoded_type
6788
68- def _enriched_type_to_json_value (t ) -> dict [str , Any ] | None :
89+ def _dump_enriched_type (t ) -> dict [str , Any ] | None :
6990 if t is None :
7091 return None
7192 t , metadata = _get_origin_type_and_metadata (t )
72- enriched_type_json = {'type' : _type_to_json_value (t , metadata )}
93+ enriched_type_json = {'type' : _dump_type (t , metadata )}
7394 attrs = None
7495 for attr in metadata :
7596 if isinstance (attr , TypeAttr ):
@@ -85,4 +106,4 @@ def dump_type(t) -> dict[str, Any] | None:
85106 """
86107 Convert a Python type to a CocoIndex's type in JSON.
87108 """
88- return _enriched_type_to_json_value (t )
109+ return _dump_enriched_type (t )
0 commit comments