66
77import dataclasses
88import datetime
9- import functools
109import inspect
1110import warnings
1211from enum import Enum
@@ -64,22 +63,8 @@ def _is_type_kind_convertible_to(src_type_kind: str, dst_type_kind: str) -> bool
6463 )
6564
6665
67- def _get_type_info (type_to_analyze : Any ) -> AnalyzedTypeInfo :
68- """Safely get type info, bypassing cache if type is not hashable."""
69-
70- @functools .cache
71- def _get_cached_type_info (t : Any ) -> AnalyzedTypeInfo :
72- """cache the computed type information for a given type."""
73- return analyze_type_info (t )
74-
75- try :
76- return _get_cached_type_info (type_to_analyze )
77- except TypeError : # The type is not hashable
78- return analyze_type_info (type_to_analyze )
79-
80-
8166# Pre-computed type info for missing/Any type annotations
82- ANY_TYPE_INFO = _get_type_info (inspect .Parameter .empty )
67+ ANY_TYPE_INFO = analyze_type_info (inspect .Parameter .empty )
8368
8469
8570def _make_encoder_closure (type_info : AnalyzedTypeInfo ) -> Callable [[Any ], Any ]:
@@ -90,7 +75,7 @@ def _make_encoder_closure(type_info: AnalyzedTypeInfo) -> Callable[[Any], Any]:
9075
9176 if isinstance (variant , AnalyzedListType ):
9277 elem_type_info = (
93- _get_type_info (variant .elem_type ) if variant .elem_type else ANY_TYPE_INFO
78+ analyze_type_info (variant .elem_type ) if variant .elem_type else ANY_TYPE_INFO
9479 )
9580 if isinstance (elem_type_info .variant , AnalyzedStructType ):
9681 elem_encoder = _make_encoder_closure (elem_type_info )
@@ -104,26 +89,28 @@ def encode_struct_list(value: Any) -> Any:
10489 if not variant .value_type :
10590 return lambda value : value
10691
107- value_type_info = _get_type_info (variant .value_type )
92+ value_type_info = analyze_type_info (variant .value_type )
10893 if isinstance (value_type_info .variant , AnalyzedStructType ):
109- key_encoder = (
110- _make_encoder_closure (ANY_TYPE_INFO )
111- if not variant .key_type
112- else _make_encoder_closure (_get_type_info (variant .key_type ))
113- )
114- value_encoder = _make_encoder_closure (value_type_info )
11594
11695 def encode_struct_dict (value : Any ) -> Any :
11796 if not isinstance (value , dict ):
11897 return value
11998 if not value :
12099 return []
100+
101+ sample_key , sample_val = next (iter (value .items ()))
102+ key_type , val_type = type (sample_key ), type (sample_val )
103+
121104 # Handle KTable case
122- if value and is_struct_type (type (next (iter (value .values ())))):
123- default_encoder = _make_encoder_closure (ANY_TYPE_INFO )
105+ if value and is_struct_type (val_type ):
106+ key_encoder = (
107+ _make_encoder_closure (analyze_type_info (key_type ))
108+ if is_struct_type (key_type )
109+ else _make_encoder_closure (ANY_TYPE_INFO )
110+ )
111+ value_encoder = _make_encoder_closure (analyze_type_info (val_type ))
124112 return [
125- [default_encoder (k )] + default_encoder (v )
126- for k , v in value .items ()
113+ [key_encoder (k )] + value_encoder (v ) for k , v in value .items ()
127114 ]
128115 return {key_encoder (k ): value_encoder (v ) for k , v in value .items ()}
129116
@@ -135,7 +122,7 @@ def encode_struct_dict(value: Any) -> Any:
135122 if dataclasses .is_dataclass (struct_type ):
136123 fields = dataclasses .fields (struct_type )
137124 field_encoders = [
138- _make_encoder_closure (_get_type_info (f .type )) for f in fields
125+ _make_encoder_closure (analyze_type_info (f .type )) for f in fields
139126 ]
140127 field_names = [f .name for f in fields ]
141128
@@ -154,7 +141,7 @@ def encode_dataclass(value: Any) -> Any:
154141 field_names = list (getattr (struct_type , "_fields" , ()))
155142 field_encoders = [
156143 _make_encoder_closure (
157- _get_type_info (annotations [name ])
144+ analyze_type_info (annotations [name ])
158145 if name in annotations
159146 else ANY_TYPE_INFO
160147 )
@@ -171,65 +158,13 @@ def encode_namedtuple(value: Any) -> Any:
171158
172159 return encode_namedtuple
173160
174- if isinstance (variant , AnalyzedAnyType ):
175-
176- def encode_any_type (value : Any ) -> Any :
177- # Handle numpy types
178- if isinstance (value , np .number ):
179- return value .item ()
180- if isinstance (value , np .ndarray ):
181- return value
182-
183- # Handle tuples
184- if isinstance (value , tuple ):
185- default_encoder = _make_encoder_closure (ANY_TYPE_INFO )
186- return [default_encoder (v ) for v in value ]
187-
188- # Handle structured types
189- if dataclasses .is_dataclass (value ):
190- return [
191- _make_encoder_closure (_get_type_info (f .type ))(
192- getattr (value , f .name )
193- )
194- for f in dataclasses .fields (value )
195- ]
196- if is_namedtuple_type (type (value )):
197- annotations = type (value ).__annotations__
198- default_encoder = _make_encoder_closure (ANY_TYPE_INFO )
199- return [
200- _make_encoder_closure (
201- _get_type_info (annotations [name ])
202- if name in annotations
203- else ANY_TYPE_INFO
204- )(getattr (value , name ))
205- for name in value ._fields
206- ]
207-
208- # Handle collections
209- if isinstance (value , list ):
210- default_encoder = _make_encoder_closure (ANY_TYPE_INFO )
211- return [default_encoder (v ) for v in value ]
212- if isinstance (value , dict ):
213- if value and is_struct_type (type (next (iter (value .values ())))):
214- default_encoder = _make_encoder_closure (ANY_TYPE_INFO )
215- return [
216- [default_encoder (k )] + default_encoder (v )
217- for k , v in value .items ()
218- ]
219- default_encoder = _make_encoder_closure (ANY_TYPE_INFO )
220- return {
221- default_encoder (k ): default_encoder (v ) for k , v in value .items ()
222- }
223-
224- return value
225-
226- return encode_any_type
227-
228161 def encode_basic_value (value : Any ) -> Any :
229162 if isinstance (value , np .number ):
230163 return value .item ()
231164 if isinstance (value , np .ndarray ):
232165 return value
166+ if isinstance (value , (list , tuple )):
167+ return [encode_basic_value (v ) for v in value ]
233168 return value
234169
235170 return encode_basic_value
@@ -245,7 +180,7 @@ def make_engine_value_encoder(type_hint: Type[Any] | str) -> Callable[[Any], Any
245180 Returns:
246181 A closure that encodes Python values to engine values
247182 """
248- type_info = _get_type_info (type_hint )
183+ type_info = analyze_type_info (type_hint )
249184 if isinstance (type_info .variant , AnalyzedUnknownType ):
250185 raise ValueError (f"Type annotation `{ type_info .core_type } ` is unsupported" )
251186
0 commit comments