cocoindex 0.1.57__cp311-cp311-manylinux_2_28_x86_64.whl → 0.1.59__cp311-cp311-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/_engine.cpython-311-x86_64-linux-gnu.so +0 -0
- cocoindex/convert.py +43 -20
- cocoindex/flow.py +60 -27
- cocoindex/llm.py +1 -0
- cocoindex/op.py +3 -4
- cocoindex/tests/test_convert.py +13 -1
- {cocoindex-0.1.57.dist-info → cocoindex-0.1.59.dist-info}/METADATA +1 -1
- {cocoindex-0.1.57.dist-info → cocoindex-0.1.59.dist-info}/RECORD +11 -11
- {cocoindex-0.1.57.dist-info → cocoindex-0.1.59.dist-info}/WHEEL +0 -0
- {cocoindex-0.1.57.dist-info → cocoindex-0.1.59.dist-info}/entry_points.txt +0 -0
- {cocoindex-0.1.57.dist-info → cocoindex-0.1.59.dist-info}/licenses/LICENSE +0 -0
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/flow.py
CHANGED
@@ -5,25 +5,27 @@ Flow is the main interface for building and running flows.
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
7
|
import asyncio
|
8
|
-
import re
|
9
|
-
import inspect
|
10
8
|
import datetime
|
11
9
|
import functools
|
10
|
+
import inspect
|
11
|
+
import re
|
12
|
+
|
13
|
+
from dataclasses import dataclass
|
14
|
+
from enum import Enum
|
15
|
+
from threading import Lock
|
12
16
|
from typing import (
|
13
17
|
Any,
|
14
18
|
Callable,
|
19
|
+
Generic,
|
20
|
+
NamedTuple,
|
15
21
|
Sequence,
|
16
22
|
TypeVar,
|
17
|
-
|
23
|
+
cast,
|
18
24
|
get_args,
|
19
25
|
get_origin,
|
20
|
-
NamedTuple,
|
21
|
-
cast,
|
22
26
|
Iterable,
|
23
27
|
)
|
24
|
-
|
25
|
-
from enum import Enum
|
26
|
-
from dataclasses import dataclass
|
28
|
+
|
27
29
|
from rich.text import Text
|
28
30
|
from rich.tree import Tree
|
29
31
|
|
@@ -32,9 +34,10 @@ from . import index
|
|
32
34
|
from . import op
|
33
35
|
from . import setting
|
34
36
|
from .convert import dump_engine_object, encode_engine_value, make_engine_value_decoder
|
35
|
-
from .
|
37
|
+
from .op import FunctionSpec
|
36
38
|
from .runtime import execution_context
|
37
39
|
from .setup import SetupChangeBundle
|
40
|
+
from .typing import encode_enriched_type
|
38
41
|
|
39
42
|
|
40
43
|
class _NameBuilder:
|
@@ -92,6 +95,30 @@ def _spec_kind(spec: Any) -> str:
|
|
92
95
|
return cast(str, spec.__class__.__name__)
|
93
96
|
|
94
97
|
|
98
|
+
def _transform_helper(
|
99
|
+
flow_builder_state: _FlowBuilderState,
|
100
|
+
fn_spec: FunctionSpec,
|
101
|
+
transform_args: list[tuple[Any, str | None]],
|
102
|
+
name: str | None = None,
|
103
|
+
) -> DataSlice[Any]:
|
104
|
+
if not isinstance(fn_spec, FunctionSpec):
|
105
|
+
raise ValueError("transform() can only be called on a CocoIndex function")
|
106
|
+
|
107
|
+
return _create_data_slice(
|
108
|
+
flow_builder_state,
|
109
|
+
lambda target_scope, name: flow_builder_state.engine_flow_builder.transform(
|
110
|
+
_spec_kind(fn_spec),
|
111
|
+
dump_engine_object(fn_spec),
|
112
|
+
transform_args,
|
113
|
+
target_scope,
|
114
|
+
flow_builder_state.field_name_builder.build_name(
|
115
|
+
name, prefix=_to_snake_case(_spec_kind(fn_spec)) + "_"
|
116
|
+
),
|
117
|
+
),
|
118
|
+
name,
|
119
|
+
)
|
120
|
+
|
121
|
+
|
95
122
|
T = TypeVar("T")
|
96
123
|
S = TypeVar("S")
|
97
124
|
|
@@ -191,31 +218,19 @@ class DataSlice(Generic[T]):
|
|
191
218
|
"""
|
192
219
|
Apply a function to the data slice.
|
193
220
|
"""
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
transform_args: list[tuple[Any, str | None]]
|
198
|
-
transform_args = [(self._state.engine_data_slice, None)]
|
221
|
+
transform_args: list[tuple[Any, str | None]] = [
|
222
|
+
(self._state.engine_data_slice, None)
|
223
|
+
]
|
199
224
|
transform_args += [
|
200
225
|
(self._state.flow_builder_state.get_data_slice(v), None) for v in args
|
201
226
|
]
|
202
227
|
transform_args += [
|
203
228
|
(self._state.flow_builder_state.get_data_slice(v), k)
|
204
|
-
for
|
229
|
+
for k, v in kwargs.items()
|
205
230
|
]
|
206
231
|
|
207
|
-
|
208
|
-
|
209
|
-
flow_builder_state,
|
210
|
-
lambda target_scope, name: flow_builder_state.engine_flow_builder.transform(
|
211
|
-
_spec_kind(fn_spec),
|
212
|
-
dump_engine_object(fn_spec),
|
213
|
-
transform_args,
|
214
|
-
target_scope,
|
215
|
-
flow_builder_state.field_name_builder.build_name(
|
216
|
-
name, prefix=_to_snake_case(_spec_kind(fn_spec)) + "_"
|
217
|
-
),
|
218
|
-
),
|
232
|
+
return _transform_helper(
|
233
|
+
self._state.flow_builder_state, fn_spec, transform_args
|
219
234
|
)
|
220
235
|
|
221
236
|
def call(self, func: Callable[..., S], *args: Any, **kwargs: Any) -> S:
|
@@ -446,6 +461,24 @@ class FlowBuilder:
|
|
446
461
|
name,
|
447
462
|
)
|
448
463
|
|
464
|
+
def transform(
|
465
|
+
self, fn_spec: FunctionSpec, *args: Any, **kwargs: Any
|
466
|
+
) -> DataSlice[Any]:
|
467
|
+
"""
|
468
|
+
Apply a function to inputs, returning a DataSlice.
|
469
|
+
"""
|
470
|
+
transform_args: list[tuple[Any, str | None]] = [
|
471
|
+
(self._state.get_data_slice(v), None) for v in args
|
472
|
+
]
|
473
|
+
transform_args += [
|
474
|
+
(self._state.get_data_slice(v), k) for k, v in kwargs.items()
|
475
|
+
]
|
476
|
+
|
477
|
+
if not transform_args:
|
478
|
+
raise ValueError("At least one input is required for transformation")
|
479
|
+
|
480
|
+
return _transform_helper(self._state, fn_spec, transform_args)
|
481
|
+
|
449
482
|
def declare(self, spec: op.DeclarationSpec) -> None:
|
450
483
|
"""
|
451
484
|
Add a declaration to the flow.
|
cocoindex/llm.py
CHANGED
cocoindex/op.py
CHANGED
@@ -5,13 +5,12 @@ Facilities for defining cocoindex operations.
|
|
5
5
|
import asyncio
|
6
6
|
import dataclasses
|
7
7
|
import inspect
|
8
|
-
|
9
|
-
from typing import Protocol, Any, Callable, Awaitable, dataclass_transform
|
10
8
|
from enum import Enum
|
9
|
+
from typing import Any, Awaitable, Callable, Protocol, dataclass_transform
|
11
10
|
|
12
|
-
from .typing import encode_enriched_type, resolve_forward_ref
|
13
|
-
from .convert import encode_engine_value, make_engine_value_decoder
|
14
11
|
from . import _engine # type: ignore
|
12
|
+
from .convert import encode_engine_value, make_engine_value_decoder
|
13
|
+
from .typing import encode_enriched_type, resolve_forward_ref
|
15
14
|
|
16
15
|
|
17
16
|
class OpCategory(Enum):
|
cocoindex/tests/test_convert.py
CHANGED
@@ -104,7 +104,7 @@ def validate_full_roundtrip(
|
|
104
104
|
)
|
105
105
|
decoder = make_engine_value_decoder([], encoded_output_type, value_type)
|
106
106
|
decoded_value = decoder(value_from_engine)
|
107
|
-
assert eq(decoded_value, value)
|
107
|
+
assert eq(decoded_value, value), f"{decoded_value} != {value}"
|
108
108
|
|
109
109
|
if other_decoded_values is not None:
|
110
110
|
for other_value, other_type in other_decoded_values:
|
@@ -613,6 +613,18 @@ def test_roundtrip_union_timedelta() -> None:
|
|
613
613
|
validate_full_roundtrip(value, t)
|
614
614
|
|
615
615
|
|
616
|
+
def test_roundtrip_vector_of_union() -> None:
|
617
|
+
t = list[str | int]
|
618
|
+
value = ["a", 1]
|
619
|
+
validate_full_roundtrip(value, t)
|
620
|
+
|
621
|
+
|
622
|
+
def test_roundtrip_union_with_vector() -> None:
|
623
|
+
t = NDArray[np.float32] | str
|
624
|
+
value = np.array([1.0, 2.0, 3.0], dtype=np.float32)
|
625
|
+
validate_full_roundtrip(value, t, ([1.0, 2.0, 3.0], list[float] | str))
|
626
|
+
|
627
|
+
|
616
628
|
def test_roundtrip_ltable() -> None:
|
617
629
|
t = list[Order]
|
618
630
|
value = [Order("O1", "item1", 10.0), Order("O2", "item2", 20.0)]
|
@@ -1,18 +1,18 @@
|
|
1
|
-
cocoindex-0.1.
|
2
|
-
cocoindex-0.1.
|
3
|
-
cocoindex-0.1.
|
4
|
-
cocoindex-0.1.
|
1
|
+
cocoindex-0.1.59.dist-info/METADATA,sha256=XyuEgs1E6LhwzhvSwCwjcRmzFZkEHaw-GFEgpp5qVn8,10020
|
2
|
+
cocoindex-0.1.59.dist-info/WHEEL,sha256=1ugA4CjcVVPH4LDWfawu_6l5KZf3P6xl5-C8vT5fNPY,108
|
3
|
+
cocoindex-0.1.59.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
|
4
|
+
cocoindex-0.1.59.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
5
5
|
cocoindex/__init__.py,sha256=MFm-QJzrr0ODJCsAAsPUzJXh8KH1WdZod8F60B1iUYw,1877
|
6
|
-
cocoindex/_engine.cpython-311-x86_64-linux-gnu.so,sha256=
|
6
|
+
cocoindex/_engine.cpython-311-x86_64-linux-gnu.so,sha256=Z584GErs4MYSUSRtODhQ7dFHZqDTBn-GFKipJyZwce0,63206328
|
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=
|
10
|
-
cocoindex/flow.py,sha256=
|
9
|
+
cocoindex/convert.py,sha256=FsKb2Pfbm7e1VQDOs_AsoiW9PbIUuyHQuqUlrENXmUY,11199
|
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=
|
15
|
-
cocoindex/op.py,sha256=
|
14
|
+
cocoindex/llm.py,sha256=0ri8ZRg9_Zf2gyC5xuQ1Kq6kdZUO8r-A5WLnxit5S_4,448
|
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
|
18
18
|
cocoindex/setting.py,sha256=Zl8K86r8RVvG9c3pCsH0Ot8BHhDAQAQCjoBp7TnXMLQ,3590
|
@@ -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=fY3p1gRHZpuWUgk5v28UGPYzyaMI4Qakv4I4qHSNGu8,36528
|
24
24
|
cocoindex/tests/test_optional_database.py,sha256=snAmkNa6wtOSaxoZE1HgjvL5v_ylitt3Jt_9df4Cgdc,8506
|
25
25
|
cocoindex/tests/test_typing.py,sha256=t6UCYShcfonTfjBlGRWPiFGMZ8DGFfABXo6idekPoJE,14757
|
26
26
|
cocoindex/typing.py,sha256=kPMFVKs2i4SCLzW1Tn5NP_Ev9DAc-2qW6eJ68gpLexU,12580
|
27
27
|
cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
|
28
|
-
cocoindex-0.1.
|
28
|
+
cocoindex-0.1.59.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|