Skip to content

Commit e3b570e

Browse files
committed
refactor(convert): remove caching for type info and streamline encoder logic
1 parent d684fba commit e3b570e

File tree

1 file changed

+20
-85
lines changed

1 file changed

+20
-85
lines changed

python/cocoindex/convert.py

Lines changed: 20 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import dataclasses
88
import datetime
9-
import functools
109
import inspect
1110
import warnings
1211
from 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

8570
def _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

Comments
 (0)