cocoindex 0.1.58__cp312-cp312-manylinux_2_28_x86_64.whl → 0.1.60__cp312-cp312-manylinux_2_28_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/__init__.py +11 -1
- cocoindex/_engine.cpython-312-x86_64-linux-gnu.so +0 -0
- cocoindex/convert.py +43 -20
- cocoindex/llm.py +1 -0
- cocoindex/tests/test_convert.py +81 -19
- cocoindex/typing.py +1 -0
- {cocoindex-0.1.58.dist-info → cocoindex-0.1.60.dist-info}/METADATA +1 -1
- {cocoindex-0.1.58.dist-info → cocoindex-0.1.60.dist-info}/RECORD +11 -11
- {cocoindex-0.1.58.dist-info → cocoindex-0.1.60.dist-info}/WHEEL +0 -0
- {cocoindex-0.1.58.dist-info → cocoindex-0.1.60.dist-info}/entry_points.txt +0 -0
- {cocoindex-0.1.58.dist-info → cocoindex-0.1.60.dist-info}/licenses/LICENSE +0 -0
cocoindex/__init__.py
CHANGED
@@ -17,7 +17,16 @@ from .llm import LlmSpec, LlmApiType
|
|
17
17
|
from .index import VectorSimilarityMetric, VectorIndexDef, IndexOptions
|
18
18
|
from .setting import DatabaseConnectionSpec, Settings, ServerSettings
|
19
19
|
from .setting import get_app_namespace
|
20
|
-
from .typing import
|
20
|
+
from .typing import (
|
21
|
+
Int64,
|
22
|
+
Float32,
|
23
|
+
Float64,
|
24
|
+
LocalDateTime,
|
25
|
+
OffsetDateTime,
|
26
|
+
Range,
|
27
|
+
Vector,
|
28
|
+
Json,
|
29
|
+
)
|
21
30
|
|
22
31
|
__all__ = [
|
23
32
|
# Submodules
|
@@ -64,6 +73,7 @@ __all__ = [
|
|
64
73
|
"ServerSettings",
|
65
74
|
"get_app_namespace",
|
66
75
|
# Typing
|
76
|
+
"Int64",
|
67
77
|
"Float32",
|
68
78
|
"Float64",
|
69
79
|
"LocalDateTime",
|
Binary file
|
cocoindex/convert.py
CHANGED
@@ -5,7 +5,6 @@ Utilities to convert between Python and engine values.
|
|
5
5
|
import dataclasses
|
6
6
|
import datetime
|
7
7
|
import inspect
|
8
|
-
import uuid
|
9
8
|
from enum import Enum
|
10
9
|
from typing import Any, Callable, Mapping, get_origin
|
11
10
|
|
@@ -14,7 +13,6 @@ import numpy as np
|
|
14
13
|
from .typing import (
|
15
14
|
KEY_FIELD_NAME,
|
16
15
|
TABLE_TYPES,
|
17
|
-
AnalyzedTypeInfo,
|
18
16
|
DtypeRegistry,
|
19
17
|
analyze_type_info,
|
20
18
|
encode_enriched_type,
|
@@ -74,23 +72,16 @@ def make_engine_value_decoder(
|
|
74
72
|
Returns:
|
75
73
|
A decoder from an engine value to a Python value.
|
76
74
|
"""
|
77
|
-
|
78
75
|
src_type_kind = src_type["kind"]
|
79
76
|
|
80
|
-
|
81
|
-
|
82
|
-
dst_annotation is
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
raise ValueError(
|
89
|
-
f"Type mismatch for `{''.join(field_path)}`: "
|
90
|
-
f"passed in {src_type_kind}, declared {dst_annotation} ({dst_type_info.kind})"
|
91
|
-
)
|
92
|
-
|
93
|
-
if dst_type_info is None:
|
77
|
+
dst_is_any = (
|
78
|
+
dst_annotation is None
|
79
|
+
or dst_annotation is inspect.Parameter.empty
|
80
|
+
or dst_annotation is Any
|
81
|
+
)
|
82
|
+
if dst_is_any:
|
83
|
+
if src_type_kind == "Union":
|
84
|
+
return lambda value: value[1]
|
94
85
|
if src_type_kind == "Struct" or src_type_kind in TABLE_TYPES:
|
95
86
|
raise ValueError(
|
96
87
|
f"Missing type annotation for `{''.join(field_path)}`."
|
@@ -98,6 +89,41 @@ def make_engine_value_decoder(
|
|
98
89
|
)
|
99
90
|
return lambda value: value
|
100
91
|
|
92
|
+
dst_type_info = analyze_type_info(dst_annotation)
|
93
|
+
|
94
|
+
if src_type_kind == "Union":
|
95
|
+
dst_type_variants = (
|
96
|
+
dst_type_info.union_variant_types
|
97
|
+
if dst_type_info.union_variant_types is not None
|
98
|
+
else [dst_annotation]
|
99
|
+
)
|
100
|
+
src_type_variants = src_type["types"]
|
101
|
+
decoders = []
|
102
|
+
for i, src_type_variant in enumerate(src_type_variants):
|
103
|
+
src_field_path = field_path + [f"[{i}]"]
|
104
|
+
decoder = None
|
105
|
+
for dst_type_variant in dst_type_variants:
|
106
|
+
try:
|
107
|
+
decoder = make_engine_value_decoder(
|
108
|
+
src_field_path, src_type_variant, dst_type_variant
|
109
|
+
)
|
110
|
+
break
|
111
|
+
except ValueError:
|
112
|
+
pass
|
113
|
+
if decoder is None:
|
114
|
+
raise ValueError(
|
115
|
+
f"Type mismatch for `{''.join(field_path)}`: "
|
116
|
+
f"cannot find matched target type for source type variant {src_type_variant}"
|
117
|
+
)
|
118
|
+
decoders.append(decoder)
|
119
|
+
return lambda value: decoders[value[0]](value[1])
|
120
|
+
|
121
|
+
if not _is_type_kind_convertible_to(src_type_kind, dst_type_info.kind):
|
122
|
+
raise ValueError(
|
123
|
+
f"Type mismatch for `{''.join(field_path)}`: "
|
124
|
+
f"passed in {src_type_kind}, declared {dst_annotation} ({dst_type_info.kind})"
|
125
|
+
)
|
126
|
+
|
101
127
|
if dst_type_info.kind in ("Float32", "Float64", "Int64"):
|
102
128
|
dst_core_type = dst_type_info.core_type
|
103
129
|
|
@@ -196,9 +222,6 @@ def make_engine_value_decoder(
|
|
196
222
|
field_path.pop()
|
197
223
|
return decode
|
198
224
|
|
199
|
-
if src_type_kind == "Union":
|
200
|
-
return lambda value: value[1]
|
201
|
-
|
202
225
|
return lambda value: value
|
203
226
|
|
204
227
|
|
cocoindex/llm.py
CHANGED
cocoindex/tests/test_convert.py
CHANGED
@@ -78,16 +78,15 @@ def build_engine_value_decoder(
|
|
78
78
|
return make_engine_value_decoder([], engine_type, python_type or engine_type_in_py)
|
79
79
|
|
80
80
|
|
81
|
-
def
|
81
|
+
def validate_full_roundtrip_to(
|
82
82
|
value: Any,
|
83
|
-
value_type: Any
|
84
|
-
*
|
83
|
+
value_type: Any,
|
84
|
+
*decoded_values: tuple[Any, Any],
|
85
85
|
) -> None:
|
86
86
|
"""
|
87
|
-
Validate the given value
|
87
|
+
Validate the given value becomes specific values after encoding, sending to engine (using output_type), receiving back and decoding (using input_type).
|
88
88
|
|
89
|
-
`
|
90
|
-
If provided, also validate the value can be decoded to the other types.
|
89
|
+
`decoded_values` is a tuple of (value, type) pairs.
|
91
90
|
"""
|
92
91
|
from cocoindex import _engine # type: ignore
|
93
92
|
|
@@ -102,15 +101,27 @@ def validate_full_roundtrip(
|
|
102
101
|
value_from_engine = _engine.testutil.seder_roundtrip(
|
103
102
|
encoded_value, encoded_output_type
|
104
103
|
)
|
105
|
-
decoder = make_engine_value_decoder([], encoded_output_type, value_type)
|
106
|
-
decoded_value = decoder(value_from_engine)
|
107
|
-
assert eq(decoded_value, value)
|
108
104
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
105
|
+
for other_value, other_type in decoded_values:
|
106
|
+
decoder = make_engine_value_decoder([], encoded_output_type, other_type)
|
107
|
+
other_decoded_value = decoder(value_from_engine)
|
108
|
+
assert eq(other_decoded_value, other_value)
|
109
|
+
|
110
|
+
|
111
|
+
def validate_full_roundtrip(
|
112
|
+
value: Any,
|
113
|
+
value_type: Any,
|
114
|
+
*other_decoded_values: tuple[Any, Any],
|
115
|
+
) -> None:
|
116
|
+
"""
|
117
|
+
Validate the given value doesn't change after encoding, sending to engine (using output_type), receiving back and decoding (using input_type).
|
118
|
+
|
119
|
+
`other_decoded_values` is a tuple of (value, type) pairs.
|
120
|
+
If provided, also validate the value can be decoded to the other types.
|
121
|
+
"""
|
122
|
+
validate_full_roundtrip_to(
|
123
|
+
value, value_type, (value, value_type), *other_decoded_values
|
124
|
+
)
|
114
125
|
|
115
126
|
|
116
127
|
def test_encode_engine_value_basic_types() -> None:
|
@@ -218,17 +229,33 @@ def test_encode_engine_value_none() -> None:
|
|
218
229
|
|
219
230
|
|
220
231
|
def test_roundtrip_basic_types() -> None:
|
221
|
-
validate_full_roundtrip(42, int, (42, None))
|
222
|
-
validate_full_roundtrip(3.25, float, (3.25, Float64))
|
223
232
|
validate_full_roundtrip(
|
224
|
-
|
233
|
+
42, cocoindex.Int64, (42, int), (np.int64(42), np.int64), (42, None)
|
234
|
+
)
|
235
|
+
validate_full_roundtrip(42, int, (42, cocoindex.Int64))
|
236
|
+
validate_full_roundtrip(np.int64(42), np.int64, (42, cocoindex.Int64))
|
237
|
+
|
238
|
+
validate_full_roundtrip(
|
239
|
+
3.25, Float64, (3.25, float), (np.float64(3.25), np.float64), (3.25, None)
|
225
240
|
)
|
241
|
+
validate_full_roundtrip(3.25, float, (3.25, Float64))
|
242
|
+
validate_full_roundtrip(np.float64(3.25), np.float64, (3.25, Float64))
|
243
|
+
|
226
244
|
validate_full_roundtrip(
|
227
|
-
3.25,
|
245
|
+
3.25,
|
246
|
+
Float32,
|
247
|
+
(3.25, float),
|
248
|
+
(np.float32(3.25), np.float32),
|
249
|
+
(np.float64(3.25), np.float64),
|
250
|
+
(3.25, Float64),
|
251
|
+
(3.25, None),
|
228
252
|
)
|
253
|
+
validate_full_roundtrip(np.float32(3.25), np.float32, (3.25, Float32))
|
254
|
+
|
229
255
|
validate_full_roundtrip("hello", str, ("hello", None))
|
230
256
|
validate_full_roundtrip(True, bool, (True, None))
|
231
257
|
validate_full_roundtrip(False, bool, (False, None))
|
258
|
+
validate_full_roundtrip((1, 2), cocoindex.Range, ((1, 2), None))
|
232
259
|
validate_full_roundtrip(
|
233
260
|
datetime.date(2025, 1, 1), datetime.date, (datetime.date(2025, 1, 1), None)
|
234
261
|
)
|
@@ -238,14 +265,37 @@ def test_roundtrip_basic_types() -> None:
|
|
238
265
|
cocoindex.LocalDateTime,
|
239
266
|
(datetime.datetime(2025, 1, 2, 3, 4, 5, 123456), datetime.datetime),
|
240
267
|
)
|
268
|
+
|
269
|
+
tz = datetime.timezone(datetime.timedelta(hours=5))
|
241
270
|
validate_full_roundtrip(
|
242
|
-
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456,
|
271
|
+
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456, tz),
|
272
|
+
cocoindex.OffsetDateTime,
|
273
|
+
(
|
274
|
+
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456, tz),
|
275
|
+
datetime.datetime,
|
276
|
+
),
|
277
|
+
)
|
278
|
+
validate_full_roundtrip(
|
279
|
+
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456, tz),
|
280
|
+
datetime.datetime,
|
281
|
+
(datetime.datetime(2025, 1, 2, 3, 4, 5, 123456, tz), cocoindex.OffsetDateTime),
|
282
|
+
)
|
283
|
+
validate_full_roundtrip_to(
|
284
|
+
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456),
|
243
285
|
cocoindex.OffsetDateTime,
|
244
286
|
(
|
245
287
|
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456, datetime.UTC),
|
246
288
|
datetime.datetime,
|
247
289
|
),
|
248
290
|
)
|
291
|
+
validate_full_roundtrip_to(
|
292
|
+
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456),
|
293
|
+
datetime.datetime,
|
294
|
+
(
|
295
|
+
datetime.datetime(2025, 1, 2, 3, 4, 5, 123456, datetime.UTC),
|
296
|
+
cocoindex.OffsetDateTime,
|
297
|
+
),
|
298
|
+
)
|
249
299
|
|
250
300
|
uuid_value = uuid.uuid4()
|
251
301
|
validate_full_roundtrip(uuid_value, uuid.UUID, (uuid_value, None))
|
@@ -613,6 +663,18 @@ def test_roundtrip_union_timedelta() -> None:
|
|
613
663
|
validate_full_roundtrip(value, t)
|
614
664
|
|
615
665
|
|
666
|
+
def test_roundtrip_vector_of_union() -> None:
|
667
|
+
t = list[str | int]
|
668
|
+
value = ["a", 1]
|
669
|
+
validate_full_roundtrip(value, t)
|
670
|
+
|
671
|
+
|
672
|
+
def test_roundtrip_union_with_vector() -> None:
|
673
|
+
t = NDArray[np.float32] | str
|
674
|
+
value = np.array([1.0, 2.0, 3.0], dtype=np.float32)
|
675
|
+
validate_full_roundtrip(value, t, ([1.0, 2.0, 3.0], list[float] | str))
|
676
|
+
|
677
|
+
|
616
678
|
def test_roundtrip_ltable() -> None:
|
617
679
|
t = list[Order]
|
618
680
|
value = [Order("O1", "item1", 10.0), Order("O2", "item2", 20.0)]
|
cocoindex/typing.py
CHANGED
@@ -40,6 +40,7 @@ class TypeAttr:
|
|
40
40
|
|
41
41
|
Annotation = TypeKind | TypeAttr | VectorInfo
|
42
42
|
|
43
|
+
Int64 = Annotated[int, TypeKind("Int64")]
|
43
44
|
Float32 = Annotated[float, TypeKind("Float32")]
|
44
45
|
Float64 = Annotated[float, TypeKind("Float64")]
|
45
46
|
Range = Annotated[tuple[int, int], TypeKind("Range")]
|
@@ -1,17 +1,17 @@
|
|
1
|
-
cocoindex-0.1.
|
2
|
-
cocoindex-0.1.
|
3
|
-
cocoindex-0.1.
|
4
|
-
cocoindex-0.1.
|
5
|
-
cocoindex/__init__.py,sha256=
|
6
|
-
cocoindex/_engine.cpython-312-x86_64-linux-gnu.so,sha256=
|
1
|
+
cocoindex-0.1.60.dist-info/METADATA,sha256=TLP5AmkWol7oAVwBcHJfzpQNbilcmrczI6MJX_oVBD0,10020
|
2
|
+
cocoindex-0.1.60.dist-info/WHEEL,sha256=_CzojsfcNnIHPHWM3rF2h1_Qa3VRJKIX8HSir-fDxGE,108
|
3
|
+
cocoindex-0.1.60.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
|
4
|
+
cocoindex-0.1.60.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
5
|
+
cocoindex/__init__.py,sha256=dSSqO5g2EPoPM3Yo7meIpIh8hWPDArsXFG8kXaQrCwk,1934
|
6
|
+
cocoindex/_engine.cpython-312-x86_64-linux-gnu.so,sha256=WS_4ebHkiGkGpTajRgOP1SOq6B7c-MgPQpouNYYg0Hk,63204856
|
7
7
|
cocoindex/auth_registry.py,sha256=1XqO7ibjmBBd8i11XSJTvTgdz8p1ptW-ZpuSgo_5zzk,716
|
8
8
|
cocoindex/cli.py,sha256=8bDL-Qmd9NYtn1DsDfvUMk45xfAqNf9YTyM7H9KRuNU,21345
|
9
|
-
cocoindex/convert.py,sha256=
|
9
|
+
cocoindex/convert.py,sha256=FsKb2Pfbm7e1VQDOs_AsoiW9PbIUuyHQuqUlrENXmUY,11199
|
10
10
|
cocoindex/flow.py,sha256=UQviW2O6nzCKt3jf7N1xAXULvK7YRCZDAj5hy5VLkjM,33041
|
11
11
|
cocoindex/functions.py,sha256=IBwvdPpGR-S5mk53HvHpT2GVs15MI9wQznxgOdxA0ac,3202
|
12
12
|
cocoindex/index.py,sha256=j93B9jEvvLXHtpzKWL88SY6wCGEoPgpsQhEGHlyYGFg,540
|
13
13
|
cocoindex/lib.py,sha256=BeRUn3RqE_wSsVtsgCzbFFKe1LXgRyRmMOcmwWBuEXo,2940
|
14
|
-
cocoindex/llm.py,sha256=
|
14
|
+
cocoindex/llm.py,sha256=0ri8ZRg9_Zf2gyC5xuQ1Kq6kdZUO8r-A5WLnxit5S_4,448
|
15
15
|
cocoindex/op.py,sha256=r_Usx7Jqh49Cck3tsYLx2vLRNUZArkQP_g7bIID6LPU,11809
|
16
16
|
cocoindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
cocoindex/runtime.py,sha256=bAdHYaXFWiiUWyAgzmKTeaAaRR0D_AmaqVCIdPO-v00,1056
|
@@ -20,9 +20,9 @@ cocoindex/setup.py,sha256=7uIHKN4FOCuoidPXcKyGTrkqpkl9luL49-6UcnMxYzw,3068
|
|
20
20
|
cocoindex/sources.py,sha256=JCnOhv1w4o28e03i7yvo4ESicWYAhckkBg5bQlxNH4U,1330
|
21
21
|
cocoindex/targets.py,sha256=Nfh_tpFd1goTnS_cxBjIs4j9zl3Z4Z1JomAQ1dl3Sic,2796
|
22
22
|
cocoindex/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
|
-
cocoindex/tests/test_convert.py,sha256=
|
23
|
+
cocoindex/tests/test_convert.py,sha256=WmgbaQTYPDnjBfMlIrZWBHipPW7SlrvHYsLLqb--KH0,38025
|
24
24
|
cocoindex/tests/test_optional_database.py,sha256=snAmkNa6wtOSaxoZE1HgjvL5v_ylitt3Jt_9df4Cgdc,8506
|
25
25
|
cocoindex/tests/test_typing.py,sha256=t6UCYShcfonTfjBlGRWPiFGMZ8DGFfABXo6idekPoJE,14757
|
26
|
-
cocoindex/typing.py,sha256=
|
26
|
+
cocoindex/typing.py,sha256=s_Hk4Npi8pxJUM2h_7Km0VFrojA8wJU9VDtRqVSL6C0,12622
|
27
27
|
cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
|
28
|
-
cocoindex-0.1.
|
28
|
+
cocoindex-0.1.60.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|