cocoindex 0.1.83__cp312-cp312-macosx_10_12_x86_64.whl → 0.2.0__cp312-cp312-macosx_10_12_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cocoindex/_engine.cpython-312-darwin.so +0 -0
- cocoindex/convert.py +63 -46
- cocoindex/typing.py +37 -22
- {cocoindex-0.1.83.dist-info → cocoindex-0.2.0.dist-info}/METADATA +1 -1
- {cocoindex-0.1.83.dist-info → cocoindex-0.2.0.dist-info}/RECORD +8 -8
- {cocoindex-0.1.83.dist-info → cocoindex-0.2.0.dist-info}/WHEEL +1 -1
- {cocoindex-0.1.83.dist-info → cocoindex-0.2.0.dist-info}/entry_points.txt +0 -0
- {cocoindex-0.1.83.dist-info → cocoindex-0.2.0.dist-info}/licenses/LICENSE +0 -0
Binary file
|
cocoindex/convert.py
CHANGED
@@ -14,7 +14,6 @@ from typing import Any, Callable, Mapping, Type, get_origin
|
|
14
14
|
import numpy as np
|
15
15
|
|
16
16
|
from .typing import (
|
17
|
-
KEY_FIELD_NAME,
|
18
17
|
TABLE_TYPES,
|
19
18
|
AnalyzedAnyType,
|
20
19
|
AnalyzedBasicType,
|
@@ -28,7 +27,6 @@ from .typing import (
|
|
28
27
|
encode_enriched_type,
|
29
28
|
is_namedtuple_type,
|
30
29
|
is_numpy_number_type,
|
31
|
-
is_struct_type,
|
32
30
|
)
|
33
31
|
|
34
32
|
|
@@ -88,38 +86,35 @@ def make_engine_value_encoder(type_info: AnalyzedTypeInfo) -> Callable[[Any], An
|
|
88
86
|
|
89
87
|
return encode_struct_list
|
90
88
|
|
91
|
-
|
92
|
-
if not variant.value_type:
|
93
|
-
return lambda value: value
|
89
|
+
# Otherwise it's a vector, falling into basic type in the engine.
|
94
90
|
|
91
|
+
if isinstance(variant, AnalyzedDictType):
|
95
92
|
value_type_info = analyze_type_info(variant.value_type)
|
96
|
-
if isinstance(value_type_info.variant, AnalyzedStructType):
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
# Handle KTable case
|
108
|
-
if value and is_struct_type(val_type):
|
109
|
-
key_encoder = (
|
110
|
-
make_engine_value_encoder(analyze_type_info(key_type))
|
111
|
-
if is_struct_type(key_type)
|
112
|
-
else make_engine_value_encoder(ANY_TYPE_INFO)
|
113
|
-
)
|
114
|
-
value_encoder = make_engine_value_encoder(
|
115
|
-
analyze_type_info(val_type)
|
116
|
-
)
|
117
|
-
return [
|
118
|
-
[key_encoder(k)] + value_encoder(v) for k, v in value.items()
|
119
|
-
]
|
120
|
-
return {key_encoder(k): value_encoder(v) for k, v in value.items()}
|
93
|
+
if not isinstance(value_type_info.variant, AnalyzedStructType):
|
94
|
+
raise ValueError(
|
95
|
+
f"Value type for dict is required to be a struct (e.g. dataclass or NamedTuple), got {variant.value_type}. "
|
96
|
+
f"If you want a free-formed dict, use `cocoindex.Json` instead."
|
97
|
+
)
|
98
|
+
value_encoder = make_engine_value_encoder(value_type_info)
|
99
|
+
|
100
|
+
key_type_info = analyze_type_info(variant.key_type)
|
101
|
+
key_encoder = make_engine_value_encoder(key_type_info)
|
102
|
+
if isinstance(key_type_info.variant, AnalyzedBasicType):
|
121
103
|
|
122
|
-
|
104
|
+
def encode_row(k: Any, v: Any) -> Any:
|
105
|
+
return [key_encoder(k)] + value_encoder(v)
|
106
|
+
|
107
|
+
else:
|
108
|
+
|
109
|
+
def encode_row(k: Any, v: Any) -> Any:
|
110
|
+
return key_encoder(k) + value_encoder(v)
|
111
|
+
|
112
|
+
def encode_struct_dict(value: Any) -> Any:
|
113
|
+
if not value:
|
114
|
+
return []
|
115
|
+
return [encode_row(k, v) for k, v in value.items()]
|
116
|
+
|
117
|
+
return encode_struct_dict
|
123
118
|
|
124
119
|
if isinstance(variant, AnalyzedStructType):
|
125
120
|
struct_type = variant.struct_type
|
@@ -132,8 +127,8 @@ def make_engine_value_encoder(type_info: AnalyzedTypeInfo) -> Callable[[Any], An
|
|
132
127
|
field_names = [f.name for f in fields]
|
133
128
|
|
134
129
|
def encode_dataclass(value: Any) -> Any:
|
135
|
-
if
|
136
|
-
return
|
130
|
+
if value is None:
|
131
|
+
return None
|
137
132
|
return [
|
138
133
|
encoder(getattr(value, name))
|
139
134
|
for encoder, name in zip(field_encoders, field_names)
|
@@ -154,8 +149,8 @@ def make_engine_value_encoder(type_info: AnalyzedTypeInfo) -> Callable[[Any], An
|
|
154
149
|
]
|
155
150
|
|
156
151
|
def encode_namedtuple(value: Any) -> Any:
|
157
|
-
if
|
158
|
-
return
|
152
|
+
if value is None:
|
153
|
+
return None
|
159
154
|
return [
|
160
155
|
encoder(getattr(value, name))
|
161
156
|
for encoder, name in zip(field_encoders, field_names)
|
@@ -248,25 +243,47 @@ def make_engine_value_decoder(
|
|
248
243
|
f"declared `{dst_type_info.core_type}`, a dict type expected"
|
249
244
|
)
|
250
245
|
|
251
|
-
|
252
|
-
|
253
|
-
key_decoder =
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
246
|
+
num_key_parts = src_type.get("num_key_parts", 1)
|
247
|
+
key_type_info = analyze_type_info(key_type)
|
248
|
+
key_decoder: Callable[..., Any] | None = None
|
249
|
+
if (
|
250
|
+
isinstance(
|
251
|
+
key_type_info.variant, (AnalyzedBasicType, AnalyzedAnyType)
|
252
|
+
)
|
253
|
+
and num_key_parts == 1
|
254
|
+
):
|
255
|
+
single_key_decoder = make_engine_value_decoder(
|
256
|
+
field_path,
|
257
|
+
engine_fields_schema[0]["type"],
|
258
|
+
key_type_info,
|
259
|
+
for_key=True,
|
260
|
+
)
|
261
|
+
|
262
|
+
def key_decoder(value: list[Any]) -> Any:
|
263
|
+
return single_key_decoder(value[0])
|
264
|
+
|
265
|
+
else:
|
266
|
+
key_decoder = make_engine_struct_decoder(
|
267
|
+
field_path,
|
268
|
+
engine_fields_schema[0:num_key_parts],
|
269
|
+
key_type_info,
|
270
|
+
for_key=True,
|
271
|
+
)
|
260
272
|
value_decoder = make_engine_struct_decoder(
|
261
273
|
field_path,
|
262
|
-
engine_fields_schema[
|
274
|
+
engine_fields_schema[num_key_parts:],
|
263
275
|
analyze_type_info(value_type),
|
264
276
|
)
|
265
277
|
|
266
278
|
def decode(value: Any) -> Any | None:
|
267
279
|
if value is None:
|
268
280
|
return None
|
269
|
-
return {
|
281
|
+
return {
|
282
|
+
key_decoder(v[0:num_key_parts]): value_decoder(
|
283
|
+
v[num_key_parts:]
|
284
|
+
)
|
285
|
+
for v in value
|
286
|
+
}
|
270
287
|
|
271
288
|
return decode
|
272
289
|
|
cocoindex/typing.py
CHANGED
@@ -330,35 +330,50 @@ def analyze_type_info(t: Any) -> AnalyzedTypeInfo:
|
|
330
330
|
|
331
331
|
def _encode_struct_schema(
|
332
332
|
struct_type: type, key_type: type | None = None
|
333
|
-
) -> dict[str, Any]:
|
333
|
+
) -> tuple[dict[str, Any], int | None]:
|
334
334
|
fields = []
|
335
335
|
|
336
|
-
def add_field(name: str,
|
336
|
+
def add_field(name: str, analyzed_type: AnalyzedTypeInfo) -> None:
|
337
337
|
try:
|
338
|
-
type_info = encode_enriched_type_info(
|
338
|
+
type_info = encode_enriched_type_info(analyzed_type)
|
339
339
|
except ValueError as e:
|
340
340
|
e.add_note(
|
341
341
|
f"Failed to encode annotation for field - "
|
342
|
-
f"{struct_type.__name__}.{name}: {
|
342
|
+
f"{struct_type.__name__}.{name}: {analyzed_type.core_type}"
|
343
343
|
)
|
344
344
|
raise
|
345
345
|
type_info["name"] = name
|
346
346
|
fields.append(type_info)
|
347
347
|
|
348
|
+
def add_fields_from_struct(struct_type: type) -> None:
|
349
|
+
if dataclasses.is_dataclass(struct_type):
|
350
|
+
for field in dataclasses.fields(struct_type):
|
351
|
+
add_field(field.name, analyze_type_info(field.type))
|
352
|
+
elif is_namedtuple_type(struct_type):
|
353
|
+
for name, field_type in struct_type.__annotations__.items():
|
354
|
+
add_field(name, analyze_type_info(field_type))
|
355
|
+
else:
|
356
|
+
raise ValueError(f"Unsupported struct type: {struct_type}")
|
357
|
+
|
358
|
+
result: dict[str, Any] = {}
|
359
|
+
num_key_parts = None
|
348
360
|
if key_type is not None:
|
349
|
-
|
361
|
+
key_type_info = analyze_type_info(key_type)
|
362
|
+
if isinstance(key_type_info.variant, AnalyzedBasicType):
|
363
|
+
add_field(KEY_FIELD_NAME, key_type_info)
|
364
|
+
num_key_parts = 1
|
365
|
+
elif isinstance(key_type_info.variant, AnalyzedStructType):
|
366
|
+
add_fields_from_struct(key_type_info.variant.struct_type)
|
367
|
+
num_key_parts = len(fields)
|
368
|
+
else:
|
369
|
+
raise ValueError(f"Unsupported key type: {key_type}")
|
350
370
|
|
351
|
-
|
352
|
-
for field in dataclasses.fields(struct_type):
|
353
|
-
add_field(field.name, field.type)
|
354
|
-
elif is_namedtuple_type(struct_type):
|
355
|
-
for name, field_type in struct_type.__annotations__.items():
|
356
|
-
add_field(name, field_type)
|
371
|
+
add_fields_from_struct(struct_type)
|
357
372
|
|
358
|
-
result
|
373
|
+
result["fields"] = fields
|
359
374
|
if doc := inspect.getdoc(struct_type):
|
360
375
|
result["description"] = doc
|
361
|
-
return result
|
376
|
+
return result, num_key_parts
|
362
377
|
|
363
378
|
|
364
379
|
def _encode_type(type_info: AnalyzedTypeInfo) -> dict[str, Any]:
|
@@ -374,7 +389,7 @@ def _encode_type(type_info: AnalyzedTypeInfo) -> dict[str, Any]:
|
|
374
389
|
return {"kind": variant.kind}
|
375
390
|
|
376
391
|
if isinstance(variant, AnalyzedStructType):
|
377
|
-
encoded_type = _encode_struct_schema(variant.struct_type)
|
392
|
+
encoded_type, _ = _encode_struct_schema(variant.struct_type)
|
378
393
|
encoded_type["kind"] = "Struct"
|
379
394
|
return encoded_type
|
380
395
|
|
@@ -384,10 +399,8 @@ def _encode_type(type_info: AnalyzedTypeInfo) -> dict[str, Any]:
|
|
384
399
|
if isinstance(elem_type_info.variant, AnalyzedStructType):
|
385
400
|
if variant.vector_info is not None:
|
386
401
|
raise ValueError("LTable type must not have a vector info")
|
387
|
-
|
388
|
-
|
389
|
-
"row": _encode_struct_schema(elem_type_info.variant.struct_type),
|
390
|
-
}
|
402
|
+
row_type, _ = _encode_struct_schema(elem_type_info.variant.struct_type)
|
403
|
+
return {"kind": "LTable", "row": row_type}
|
391
404
|
else:
|
392
405
|
vector_info = variant.vector_info
|
393
406
|
return {
|
@@ -402,12 +415,14 @@ def _encode_type(type_info: AnalyzedTypeInfo) -> dict[str, Any]:
|
|
402
415
|
raise ValueError(
|
403
416
|
f"KTable value must have a Struct type, got {value_type_info.core_type}"
|
404
417
|
)
|
418
|
+
row_type, num_key_parts = _encode_struct_schema(
|
419
|
+
value_type_info.variant.struct_type,
|
420
|
+
variant.key_type,
|
421
|
+
)
|
405
422
|
return {
|
406
423
|
"kind": "KTable",
|
407
|
-
"row":
|
408
|
-
|
409
|
-
variant.key_type,
|
410
|
-
),
|
424
|
+
"row": row_type,
|
425
|
+
"num_key_parts": num_key_parts,
|
411
426
|
}
|
412
427
|
|
413
428
|
if isinstance(variant, AnalyzedUnionType):
|
@@ -1,12 +1,12 @@
|
|
1
|
-
cocoindex-0.
|
2
|
-
cocoindex-0.
|
3
|
-
cocoindex-0.
|
4
|
-
cocoindex-0.
|
1
|
+
cocoindex-0.2.0.dist-info/METADATA,sha256=UqU2UILgJFn7J42_8ohdY0MOewTw4X5l_rmmclMP6kM,12187
|
2
|
+
cocoindex-0.2.0.dist-info/WHEEL,sha256=IL3YV51tpydQP7kj9OmuredpauMtSrvXdJ-izRXxqss,106
|
3
|
+
cocoindex-0.2.0.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
|
4
|
+
cocoindex-0.2.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
5
5
|
cocoindex/__init__.py,sha256=sLpSVO5Cotgn_82lawxvXnaqfa-qj33rytWBAe2MTtU,2201
|
6
|
-
cocoindex/_engine.cpython-312-darwin.so,sha256=
|
6
|
+
cocoindex/_engine.cpython-312-darwin.so,sha256=iWAk25MOj_B4_Nve9E8EjkXeE8CUnShL_E_mVutpNE0,68876372
|
7
7
|
cocoindex/auth_registry.py,sha256=PE1-kVkcyC1G2C_V7b1kvYzeq73OFQehWKQP7ln7fJ8,1478
|
8
8
|
cocoindex/cli.py,sha256=8Q2D0gI_yHorxfFC7tzV96oJAR7PtTn_T4qWLorPPoM,20675
|
9
|
-
cocoindex/convert.py,sha256=
|
9
|
+
cocoindex/convert.py,sha256=x3eYx-NQD-z9h-jmpVgUMiSTqll6Baa_SfZJF3mZSUc,22071
|
10
10
|
cocoindex/flow.py,sha256=7133Z6QU4LF_GMV81AmkO_aGhfAQCStwOnMW7BABymU,36258
|
11
11
|
cocoindex/functions.py,sha256=09erNt3WbzY9l1KER-akBF2O5-6xEahV2ORBECaL6yk,12260
|
12
12
|
cocoindex/index.py,sha256=j93B9jEvvLXHtpzKWL88SY6wCGEoPgpsQhEGHlyYGFg,540
|
@@ -26,8 +26,8 @@ cocoindex/tests/test_optional_database.py,sha256=snAmkNa6wtOSaxoZE1HgjvL5v_ylitt
|
|
26
26
|
cocoindex/tests/test_transform_flow.py,sha256=MdIzLdIMBPlIfKRFAB7n8gIZixqChL6xb4vScvcyiNU,5148
|
27
27
|
cocoindex/tests/test_typing.py,sha256=9OF3lO2uSpZBefkEJx7WRbnkXjwQtvlQIeeARYQID68,12391
|
28
28
|
cocoindex/tests/test_validation.py,sha256=X6AQzVs-hVKIXcrHMEMQnhfUE8at7iXQnPq8nHNhZ2Q,4543
|
29
|
-
cocoindex/typing.py,sha256=
|
29
|
+
cocoindex/typing.py,sha256=lEQYIzAGVKQp6RnhyeopY9Q7xEED7yQj3ZMxvTPblV8,14200
|
30
30
|
cocoindex/user_app_loader.py,sha256=o2n25y7CGw9Qrb-RN6tiNlv2YJ9YLM8NSMhJZjLhhKQ,1914
|
31
31
|
cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
|
32
32
|
cocoindex/validation.py,sha256=PZnJoby4sLbsmPv9fOjOQXuefjfZ7gmtsiTGU8SH-tc,3090
|
33
|
-
cocoindex-0.
|
33
|
+
cocoindex-0.2.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|