cocoindex 0.1.80__cp311-cp311-manylinux_2_28_aarch64.whl → 0.1.82__cp311-cp311-manylinux_2_28_aarch64.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-aarch64-linux-gnu.so +0 -0
- cocoindex/cli.py +5 -46
- cocoindex/convert.py +120 -36
- cocoindex/flow.py +54 -63
- cocoindex/functions.py +3 -3
- cocoindex/op.py +80 -68
- cocoindex/subprocess_exec.py +241 -0
- cocoindex/tests/test_convert.py +63 -44
- cocoindex/tests/test_transform_flow.py +32 -0
- cocoindex/user_app_loader.py +51 -0
- {cocoindex-0.1.80.dist-info → cocoindex-0.1.82.dist-info}/METADATA +6 -6
- {cocoindex-0.1.80.dist-info → cocoindex-0.1.82.dist-info}/RECORD +15 -13
- {cocoindex-0.1.80.dist-info → cocoindex-0.1.82.dist-info}/WHEEL +0 -0
- {cocoindex-0.1.80.dist-info → cocoindex-0.1.82.dist-info}/entry_points.txt +0 -0
- {cocoindex-0.1.80.dist-info → cocoindex-0.1.82.dist-info}/licenses/LICENSE +0 -0
cocoindex/tests/test_convert.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import datetime
|
2
2
|
import inspect
|
3
3
|
import uuid
|
4
|
-
from dataclasses import dataclass, make_dataclass
|
5
|
-
from typing import Annotated, Any, Callable, Literal, NamedTuple
|
4
|
+
from dataclasses import dataclass, make_dataclass
|
5
|
+
from typing import Annotated, Any, Callable, Literal, NamedTuple, Type
|
6
6
|
|
7
7
|
import numpy as np
|
8
8
|
import pytest
|
@@ -11,7 +11,7 @@ from numpy.typing import NDArray
|
|
11
11
|
import cocoindex
|
12
12
|
from cocoindex.convert import (
|
13
13
|
dump_engine_object,
|
14
|
-
|
14
|
+
make_engine_value_encoder,
|
15
15
|
make_engine_value_decoder,
|
16
16
|
)
|
17
17
|
from cocoindex.typing import (
|
@@ -19,8 +19,8 @@ from cocoindex.typing import (
|
|
19
19
|
Float64,
|
20
20
|
TypeKind,
|
21
21
|
Vector,
|
22
|
-
encode_enriched_type,
|
23
22
|
analyze_type_info,
|
23
|
+
encode_enriched_type,
|
24
24
|
)
|
25
25
|
|
26
26
|
|
@@ -69,6 +69,14 @@ class CustomerNamedTuple(NamedTuple):
|
|
69
69
|
tags: list[Tag] | None = None
|
70
70
|
|
71
71
|
|
72
|
+
def encode_engine_value(value: Any, type_hint: Type[Any] | str) -> Any:
|
73
|
+
"""
|
74
|
+
Encode a Python value to an engine value.
|
75
|
+
"""
|
76
|
+
encoder = make_engine_value_encoder(analyze_type_info(type_hint))
|
77
|
+
return encoder(value)
|
78
|
+
|
79
|
+
|
72
80
|
def build_engine_value_decoder(
|
73
81
|
engine_type_in_py: Any, python_type: Any | None = None
|
74
82
|
) -> Callable[[Any], Any]:
|
@@ -99,7 +107,7 @@ def validate_full_roundtrip_to(
|
|
99
107
|
return np.array_equal(a, b)
|
100
108
|
return type(a) is type(b) and not not (a == b)
|
101
109
|
|
102
|
-
encoded_value = encode_engine_value(value)
|
110
|
+
encoded_value = encode_engine_value(value, value_type)
|
103
111
|
value_type = value_type or type(value)
|
104
112
|
encoded_output_type = encode_enriched_type(value_type)["type"]
|
105
113
|
value_from_engine = _engine.testutil.seder_roundtrip(
|
@@ -133,24 +141,24 @@ def validate_full_roundtrip(
|
|
133
141
|
|
134
142
|
|
135
143
|
def test_encode_engine_value_basic_types() -> None:
|
136
|
-
assert encode_engine_value(123) == 123
|
137
|
-
assert encode_engine_value(3.14) == 3.14
|
138
|
-
assert encode_engine_value("hello") == "hello"
|
139
|
-
assert encode_engine_value(True) is True
|
144
|
+
assert encode_engine_value(123, int) == 123
|
145
|
+
assert encode_engine_value(3.14, float) == 3.14
|
146
|
+
assert encode_engine_value("hello", str) == "hello"
|
147
|
+
assert encode_engine_value(True, bool) is True
|
140
148
|
|
141
149
|
|
142
150
|
def test_encode_engine_value_uuid() -> None:
|
143
151
|
u = uuid.uuid4()
|
144
|
-
assert encode_engine_value(u) == u
|
152
|
+
assert encode_engine_value(u, uuid.UUID) == u
|
145
153
|
|
146
154
|
|
147
155
|
def test_encode_engine_value_date_time_types() -> None:
|
148
156
|
d = datetime.date(2024, 1, 1)
|
149
|
-
assert encode_engine_value(d) == d
|
157
|
+
assert encode_engine_value(d, datetime.date) == d
|
150
158
|
t = datetime.time(12, 30)
|
151
|
-
assert encode_engine_value(t) == t
|
159
|
+
assert encode_engine_value(t, datetime.time) == t
|
152
160
|
dt = datetime.datetime(2024, 1, 1, 12, 30)
|
153
|
-
assert encode_engine_value(dt) == dt
|
161
|
+
assert encode_engine_value(dt, datetime.datetime) == dt
|
154
162
|
|
155
163
|
|
156
164
|
def test_encode_scalar_numpy_values() -> None:
|
@@ -161,17 +169,22 @@ def test_encode_scalar_numpy_values() -> None:
|
|
161
169
|
(np.float64(2.718), pytest.approx(2.718)),
|
162
170
|
]
|
163
171
|
for np_value, expected in test_cases:
|
164
|
-
encoded = encode_engine_value(np_value)
|
172
|
+
encoded = encode_engine_value(np_value, type(np_value))
|
165
173
|
assert encoded == expected
|
166
174
|
assert isinstance(encoded, (int, float))
|
167
175
|
|
168
176
|
|
169
177
|
def test_encode_engine_value_struct() -> None:
|
170
178
|
order = Order(order_id="O123", name="mixed nuts", price=25.0)
|
171
|
-
assert encode_engine_value(order) == [
|
179
|
+
assert encode_engine_value(order, Order) == [
|
180
|
+
"O123",
|
181
|
+
"mixed nuts",
|
182
|
+
25.0,
|
183
|
+
"default_extra",
|
184
|
+
]
|
172
185
|
|
173
186
|
order_nt = OrderNamedTuple(order_id="O123", name="mixed nuts", price=25.0)
|
174
|
-
assert encode_engine_value(order_nt) == [
|
187
|
+
assert encode_engine_value(order_nt, OrderNamedTuple) == [
|
175
188
|
"O123",
|
176
189
|
"mixed nuts",
|
177
190
|
25.0,
|
@@ -181,7 +194,7 @@ def test_encode_engine_value_struct() -> None:
|
|
181
194
|
|
182
195
|
def test_encode_engine_value_list_of_structs() -> None:
|
183
196
|
orders = [Order("O1", "item1", 10.0), Order("O2", "item2", 20.0)]
|
184
|
-
assert encode_engine_value(orders) == [
|
197
|
+
assert encode_engine_value(orders, list[Order]) == [
|
185
198
|
["O1", "item1", 10.0, "default_extra"],
|
186
199
|
["O2", "item2", 20.0, "default_extra"],
|
187
200
|
]
|
@@ -190,7 +203,7 @@ def test_encode_engine_value_list_of_structs() -> None:
|
|
190
203
|
OrderNamedTuple("O1", "item1", 10.0),
|
191
204
|
OrderNamedTuple("O2", "item2", 20.0),
|
192
205
|
]
|
193
|
-
assert encode_engine_value(orders_nt) == [
|
206
|
+
assert encode_engine_value(orders_nt, list[OrderNamedTuple]) == [
|
194
207
|
["O1", "item1", 10.0, "default_extra"],
|
195
208
|
["O2", "item2", 20.0, "default_extra"],
|
196
209
|
]
|
@@ -198,12 +211,12 @@ def test_encode_engine_value_list_of_structs() -> None:
|
|
198
211
|
|
199
212
|
def test_encode_engine_value_struct_with_list() -> None:
|
200
213
|
basket = Basket(items=["apple", "banana"])
|
201
|
-
assert encode_engine_value(basket) == [["apple", "banana"]]
|
214
|
+
assert encode_engine_value(basket, Basket) == [["apple", "banana"]]
|
202
215
|
|
203
216
|
|
204
217
|
def test_encode_engine_value_nested_struct() -> None:
|
205
218
|
customer = Customer(name="Alice", order=Order("O1", "item1", 10.0))
|
206
|
-
assert encode_engine_value(customer) == [
|
219
|
+
assert encode_engine_value(customer, Customer) == [
|
207
220
|
"Alice",
|
208
221
|
["O1", "item1", 10.0, "default_extra"],
|
209
222
|
None,
|
@@ -212,7 +225,7 @@ def test_encode_engine_value_nested_struct() -> None:
|
|
212
225
|
customer_nt = CustomerNamedTuple(
|
213
226
|
name="Alice", order=OrderNamedTuple("O1", "item1", 10.0)
|
214
227
|
)
|
215
|
-
assert encode_engine_value(customer_nt) == [
|
228
|
+
assert encode_engine_value(customer_nt, CustomerNamedTuple) == [
|
216
229
|
"Alice",
|
217
230
|
["O1", "item1", 10.0, "default_extra"],
|
218
231
|
None,
|
@@ -220,20 +233,20 @@ def test_encode_engine_value_nested_struct() -> None:
|
|
220
233
|
|
221
234
|
|
222
235
|
def test_encode_engine_value_empty_list() -> None:
|
223
|
-
assert encode_engine_value([]) == []
|
224
|
-
assert encode_engine_value([[]]) == [[]]
|
236
|
+
assert encode_engine_value([], list) == []
|
237
|
+
assert encode_engine_value([[]], list[list[Any]]) == [[]]
|
225
238
|
|
226
239
|
|
227
240
|
def test_encode_engine_value_tuple() -> None:
|
228
|
-
assert encode_engine_value(()) == []
|
229
|
-
assert encode_engine_value((1, 2, 3)) == [1, 2, 3]
|
230
|
-
assert encode_engine_value(((1, 2), (3, 4))) == [[1, 2], [3, 4]]
|
231
|
-
assert encode_engine_value(([],)) == [[]]
|
232
|
-
assert encode_engine_value(((),)) == [[]]
|
241
|
+
assert encode_engine_value((), Any) == []
|
242
|
+
assert encode_engine_value((1, 2, 3), Any) == [1, 2, 3]
|
243
|
+
assert encode_engine_value(((1, 2), (3, 4)), Any) == [[1, 2], [3, 4]]
|
244
|
+
assert encode_engine_value(([],), Any) == [[]]
|
245
|
+
assert encode_engine_value(((),), Any) == [[]]
|
233
246
|
|
234
247
|
|
235
248
|
def test_encode_engine_value_none() -> None:
|
236
|
-
assert encode_engine_value(None) is None
|
249
|
+
assert encode_engine_value(None, Any) is None
|
237
250
|
|
238
251
|
|
239
252
|
def test_roundtrip_basic_types() -> None:
|
@@ -743,7 +756,7 @@ IntVectorType = cocoindex.Vector[np.int64, Literal[5]]
|
|
743
756
|
|
744
757
|
def test_vector_as_vector() -> None:
|
745
758
|
value = np.array([1, 2, 3, 4, 5], dtype=np.int64)
|
746
|
-
encoded = encode_engine_value(value)
|
759
|
+
encoded = encode_engine_value(value, IntVectorType)
|
747
760
|
assert np.array_equal(encoded, value)
|
748
761
|
decoded = build_engine_value_decoder(IntVectorType)(encoded)
|
749
762
|
assert np.array_equal(decoded, value)
|
@@ -754,7 +767,7 @@ ListIntType = list[int]
|
|
754
767
|
|
755
768
|
def test_vector_as_list() -> None:
|
756
769
|
value: ListIntType = [1, 2, 3, 4, 5]
|
757
|
-
encoded = encode_engine_value(value)
|
770
|
+
encoded = encode_engine_value(value, ListIntType)
|
758
771
|
assert encoded == [1, 2, 3, 4, 5]
|
759
772
|
decoded = build_engine_value_decoder(ListIntType)(encoded)
|
760
773
|
assert np.array_equal(decoded, value)
|
@@ -772,13 +785,19 @@ NDArrayInt64Type = NDArray[np.int64]
|
|
772
785
|
def test_encode_engine_value_ndarray() -> None:
|
773
786
|
"""Test encoding NDArray vectors to lists for the Rust engine."""
|
774
787
|
vec_f32: Float32VectorType = np.array([1.0, 2.0, 3.0], dtype=np.float32)
|
775
|
-
assert np.array_equal(
|
788
|
+
assert np.array_equal(
|
789
|
+
encode_engine_value(vec_f32, Float32VectorType), [1.0, 2.0, 3.0]
|
790
|
+
)
|
776
791
|
vec_f64: Float64VectorType = np.array([1.0, 2.0, 3.0], dtype=np.float64)
|
777
|
-
assert np.array_equal(
|
792
|
+
assert np.array_equal(
|
793
|
+
encode_engine_value(vec_f64, Float64VectorType), [1.0, 2.0, 3.0]
|
794
|
+
)
|
778
795
|
vec_i64: Int64VectorType = np.array([1, 2, 3], dtype=np.int64)
|
779
|
-
assert np.array_equal(encode_engine_value(vec_i64), [1, 2, 3])
|
796
|
+
assert np.array_equal(encode_engine_value(vec_i64, Int64VectorType), [1, 2, 3])
|
780
797
|
vec_nd_f32: NDArrayFloat32Type = np.array([1.0, 2.0, 3.0], dtype=np.float32)
|
781
|
-
assert np.array_equal(
|
798
|
+
assert np.array_equal(
|
799
|
+
encode_engine_value(vec_nd_f32, NDArrayFloat32Type), [1.0, 2.0, 3.0]
|
800
|
+
)
|
782
801
|
|
783
802
|
|
784
803
|
def test_make_engine_value_decoder_ndarray() -> None:
|
@@ -808,21 +827,21 @@ def test_make_engine_value_decoder_ndarray() -> None:
|
|
808
827
|
def test_roundtrip_ndarray_vector() -> None:
|
809
828
|
"""Test roundtrip encoding and decoding of NDArray vectors."""
|
810
829
|
value_f32 = np.array([1.0, 2.0, 3.0], dtype=np.float32)
|
811
|
-
encoded_f32 = encode_engine_value(value_f32)
|
830
|
+
encoded_f32 = encode_engine_value(value_f32, Float32VectorType)
|
812
831
|
np.array_equal(encoded_f32, [1.0, 2.0, 3.0])
|
813
832
|
decoded_f32 = build_engine_value_decoder(Float32VectorType)(encoded_f32)
|
814
833
|
assert isinstance(decoded_f32, np.ndarray)
|
815
834
|
assert decoded_f32.dtype == np.float32
|
816
835
|
assert np.array_equal(decoded_f32, value_f32)
|
817
836
|
value_i64 = np.array([1, 2, 3], dtype=np.int64)
|
818
|
-
encoded_i64 = encode_engine_value(value_i64)
|
837
|
+
encoded_i64 = encode_engine_value(value_i64, Int64VectorType)
|
819
838
|
assert np.array_equal(encoded_i64, [1, 2, 3])
|
820
839
|
decoded_i64 = build_engine_value_decoder(Int64VectorType)(encoded_i64)
|
821
840
|
assert isinstance(decoded_i64, np.ndarray)
|
822
841
|
assert decoded_i64.dtype == np.int64
|
823
842
|
assert np.array_equal(decoded_i64, value_i64)
|
824
843
|
value_nd_f64: NDArrayFloat64Type = np.array([1.0, 2.0, 3.0], dtype=np.float64)
|
825
|
-
encoded_nd_f64 = encode_engine_value(value_nd_f64)
|
844
|
+
encoded_nd_f64 = encode_engine_value(value_nd_f64, NDArrayFloat64Type)
|
826
845
|
assert np.array_equal(encoded_nd_f64, [1.0, 2.0, 3.0])
|
827
846
|
decoded_nd_f64 = build_engine_value_decoder(NDArrayFloat64Type)(encoded_nd_f64)
|
828
847
|
assert isinstance(decoded_nd_f64, np.ndarray)
|
@@ -833,7 +852,7 @@ def test_roundtrip_ndarray_vector() -> None:
|
|
833
852
|
def test_ndarray_dimension_mismatch() -> None:
|
834
853
|
"""Test dimension enforcement for Vector with specified dimension."""
|
835
854
|
value = np.array([1.0, 2.0], dtype=np.float32)
|
836
|
-
encoded = encode_engine_value(value)
|
855
|
+
encoded = encode_engine_value(value, NDArray[np.float32])
|
837
856
|
assert np.array_equal(encoded, [1.0, 2.0])
|
838
857
|
with pytest.raises(ValueError, match="Vector dimension mismatch"):
|
839
858
|
build_engine_value_decoder(Float32VectorType)(encoded)
|
@@ -842,14 +861,14 @@ def test_ndarray_dimension_mismatch() -> None:
|
|
842
861
|
def test_list_vector_backward_compatibility() -> None:
|
843
862
|
"""Test that list-based vectors still work for backward compatibility."""
|
844
863
|
value = [1, 2, 3, 4, 5]
|
845
|
-
encoded = encode_engine_value(value)
|
864
|
+
encoded = encode_engine_value(value, list[int])
|
846
865
|
assert encoded == [1, 2, 3, 4, 5]
|
847
866
|
decoded = build_engine_value_decoder(IntVectorType)(encoded)
|
848
867
|
assert isinstance(decoded, np.ndarray)
|
849
868
|
assert decoded.dtype == np.int64
|
850
869
|
assert np.array_equal(decoded, np.array([1, 2, 3, 4, 5], dtype=np.int64))
|
851
870
|
value_list: ListIntType = [1, 2, 3, 4, 5]
|
852
|
-
encoded = encode_engine_value(value_list)
|
871
|
+
encoded = encode_engine_value(value_list, ListIntType)
|
853
872
|
assert np.array_equal(encoded, [1, 2, 3, 4, 5])
|
854
873
|
decoded = build_engine_value_decoder(ListIntType)(encoded)
|
855
874
|
assert np.array_equal(decoded, [1, 2, 3, 4, 5])
|
@@ -867,7 +886,7 @@ def test_encode_complex_structure_with_ndarray() -> None:
|
|
867
886
|
original = MyStructWithNDArray(
|
868
887
|
name="test_np", data=np.array([1.0, 0.5], dtype=np.float32), value=100
|
869
888
|
)
|
870
|
-
encoded = encode_engine_value(original)
|
889
|
+
encoded = encode_engine_value(original, MyStructWithNDArray)
|
871
890
|
|
872
891
|
assert encoded[0] == original.name
|
873
892
|
assert np.array_equal(encoded[1], original.data)
|
@@ -1026,7 +1045,7 @@ def test_full_roundtrip_vector_of_vector() -> None:
|
|
1026
1045
|
),
|
1027
1046
|
(
|
1028
1047
|
value_f32,
|
1029
|
-
np.typing.NDArray[np.
|
1048
|
+
np.typing.NDArray[np.float32],
|
1030
1049
|
),
|
1031
1050
|
)
|
1032
1051
|
|
@@ -1515,7 +1534,7 @@ def test_auto_default_for_supported_and_unsupported_types() -> None:
|
|
1515
1534
|
|
1516
1535
|
validate_full_roundtrip(LTableField(1, []), LTableField)
|
1517
1536
|
|
1518
|
-
|
1537
|
+
validate_full_roundtrip(KTableField(1, {}), KTableField)
|
1519
1538
|
|
1520
1539
|
with pytest.raises(
|
1521
1540
|
ValueError,
|
@@ -142,3 +142,35 @@ def test_none_arg_yield_none_result() -> None:
|
|
142
142
|
|
143
143
|
result = transform_flow.eval(1, 2, None, None)
|
144
144
|
assert result is None, f"Expected None, got {result}"
|
145
|
+
|
146
|
+
|
147
|
+
# Test GPU function behavior.
|
148
|
+
# They're not really executed on GPU, but we want to make sure they're scheduled on subprocesses correctly.
|
149
|
+
|
150
|
+
|
151
|
+
@cocoindex.op.function(gpu=True)
|
152
|
+
def gpu_append_world(text: str) -> str:
|
153
|
+
"""Append ' world' to the input text."""
|
154
|
+
return f"{text} world"
|
155
|
+
|
156
|
+
|
157
|
+
class GpuAppendSuffix(cocoindex.op.FunctionSpec):
|
158
|
+
suffix: str
|
159
|
+
|
160
|
+
|
161
|
+
@cocoindex.op.executor_class(gpu=True)
|
162
|
+
class GpuAppendSuffixExecutor:
|
163
|
+
spec: GpuAppendSuffix
|
164
|
+
|
165
|
+
def __call__(self, text: str) -> str:
|
166
|
+
return f"{text}{self.spec.suffix}"
|
167
|
+
|
168
|
+
|
169
|
+
def test_gpu_function() -> None:
|
170
|
+
@cocoindex.transform_flow()
|
171
|
+
def transform_flow(text: cocoindex.DataSlice[str]) -> cocoindex.DataSlice[str]:
|
172
|
+
return text.transform(gpu_append_world).transform(GpuAppendSuffix(suffix="!"))
|
173
|
+
|
174
|
+
result = transform_flow.eval("Hello")
|
175
|
+
expected = "Hello world!"
|
176
|
+
assert result == expected, f"Expected {expected}, got {result}"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
import importlib
|
4
|
+
import click
|
5
|
+
import types
|
6
|
+
|
7
|
+
|
8
|
+
def load_user_app(app_target: str) -> types.ModuleType:
|
9
|
+
"""
|
10
|
+
Loads the user's application, which can be a file path or an installed module name.
|
11
|
+
Exits on failure.
|
12
|
+
"""
|
13
|
+
if not app_target:
|
14
|
+
raise click.ClickException("Application target not provided.")
|
15
|
+
|
16
|
+
looks_like_path = os.sep in app_target or app_target.lower().endswith(".py")
|
17
|
+
|
18
|
+
if looks_like_path:
|
19
|
+
if not os.path.isfile(app_target):
|
20
|
+
raise click.ClickException(f"Application file path not found: {app_target}")
|
21
|
+
app_path = os.path.abspath(app_target)
|
22
|
+
app_dir = os.path.dirname(app_path)
|
23
|
+
module_name = os.path.splitext(os.path.basename(app_path))[0]
|
24
|
+
|
25
|
+
if app_dir not in sys.path:
|
26
|
+
sys.path.insert(0, app_dir)
|
27
|
+
try:
|
28
|
+
spec = importlib.util.spec_from_file_location(module_name, app_path)
|
29
|
+
if spec is None:
|
30
|
+
raise ImportError(f"Could not create spec for file: {app_path}")
|
31
|
+
module = importlib.util.module_from_spec(spec)
|
32
|
+
sys.modules[spec.name] = module
|
33
|
+
if spec.loader is None:
|
34
|
+
raise ImportError(f"Could not create loader for file: {app_path}")
|
35
|
+
spec.loader.exec_module(module)
|
36
|
+
return module
|
37
|
+
except (ImportError, FileNotFoundError, PermissionError) as e:
|
38
|
+
raise click.ClickException(f"Failed importing file '{app_path}': {e}")
|
39
|
+
finally:
|
40
|
+
if app_dir in sys.path and sys.path[0] == app_dir:
|
41
|
+
sys.path.pop(0)
|
42
|
+
|
43
|
+
# Try as module
|
44
|
+
try:
|
45
|
+
return importlib.import_module(app_target)
|
46
|
+
except ImportError as e:
|
47
|
+
raise click.ClickException(f"Failed to load module '{app_target}': {e}")
|
48
|
+
except Exception as e:
|
49
|
+
raise click.ClickException(
|
50
|
+
f"Unexpected error importing module '{app_target}': {e}"
|
51
|
+
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cocoindex
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.82
|
4
4
|
Requires-Dist: click>=8.1.8
|
5
5
|
Requires-Dist: rich>=14.0.0
|
6
6
|
Requires-Dist: python-dotenv>=1.1.0
|
@@ -79,17 +79,17 @@ Ultra performant data transformation framework for AI, with core engine written
|
|
79
79
|
|
80
80
|
</br>
|
81
81
|
|
82
|
-
CocoIndex makes it
|
82
|
+
CocoIndex makes it effortless to transform data with AI, and keep source data and target in sync. Whether you’re building a vector index for RAG, creating knowledge graphs, or performing any custom data transformations — goes beyond SQL.
|
83
83
|
|
84
84
|
</br>
|
85
85
|
|
86
86
|
<p align="center">
|
87
|
-
|
87
|
+
<img width="4187" height="1883" alt="CocoIndex Features" src="https://github.com/user-attachments/assets/6147673f-0daf-4313-a0c7-7c4205ba2e31" />
|
88
88
|
</p>
|
89
89
|
|
90
90
|
</br>
|
91
91
|
|
92
|
-
|
92
|
+
|
93
93
|
|
94
94
|
## Exceptional velocity
|
95
95
|
Just declare transformation in dataflow with ~100 lines of python
|
@@ -114,8 +114,8 @@ CocoIndex follows the idea of [Dataflow](https://en.wikipedia.org/wiki/Dataflow_
|
|
114
114
|
|
115
115
|
**Particularly**, developers don't explicitly mutate data by creating, updating and deleting. They just need to define transformation/formula for a set of source data.
|
116
116
|
|
117
|
-
##
|
118
|
-
Native builtins for different source, targets and transformations. Standardize interface, make it 1-line code switch between different components.
|
117
|
+
## Plug-and-Play Building Blocks
|
118
|
+
Native builtins for different source, targets and transformations. Standardize interface, make it 1-line code switch between different components - as easy as assembling building blocks.
|
119
119
|
|
120
120
|
<p align="center">
|
121
121
|
<img src="https://cocoindex.io/images/components.svg" alt="CocoIndex Features">
|
@@ -1,31 +1,33 @@
|
|
1
|
-
cocoindex-0.1.
|
2
|
-
cocoindex-0.1.
|
3
|
-
cocoindex-0.1.
|
4
|
-
cocoindex-0.1.
|
1
|
+
cocoindex-0.1.82.dist-info/METADATA,sha256=totDI7Pxf_1q8U_5YRvAq0npG0A0loaeUpM7PeKvfkU,12188
|
2
|
+
cocoindex-0.1.82.dist-info/WHEEL,sha256=vxXvNW_GtY-xnGbsbca-Hwhz3FaRbDUi_vh_ORpt-Xc,109
|
3
|
+
cocoindex-0.1.82.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
|
4
|
+
cocoindex-0.1.82.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
5
5
|
cocoindex/__init__.py,sha256=sLpSVO5Cotgn_82lawxvXnaqfa-qj33rytWBAe2MTtU,2201
|
6
|
-
cocoindex/_engine.cpython-311-aarch64-linux-gnu.so,sha256=
|
6
|
+
cocoindex/_engine.cpython-311-aarch64-linux-gnu.so,sha256=7bNexbj8KzMBL8lbzkLTapRJEyeXoZjUMm-DwRouk5U,69705600
|
7
7
|
cocoindex/auth_registry.py,sha256=PE1-kVkcyC1G2C_V7b1kvYzeq73OFQehWKQP7ln7fJ8,1478
|
8
|
-
cocoindex/cli.py,sha256
|
9
|
-
cocoindex/convert.py,sha256=
|
10
|
-
cocoindex/flow.py,sha256=
|
11
|
-
cocoindex/functions.py,sha256
|
8
|
+
cocoindex/cli.py,sha256=8Q2D0gI_yHorxfFC7tzV96oJAR7PtTn_T4qWLorPPoM,20675
|
9
|
+
cocoindex/convert.py,sha256=bf61K1gEYhZx05LQtV_-E7SDOUYpiYaHZtH8iZ1W_VE,21473
|
10
|
+
cocoindex/flow.py,sha256=W0PjZ0vLQFEW6tvbblje85jnkz4Mn9B1_Z4_slUffYM,35981
|
11
|
+
cocoindex/functions.py,sha256=09erNt3WbzY9l1KER-akBF2O5-6xEahV2ORBECaL6yk,12260
|
12
12
|
cocoindex/index.py,sha256=j93B9jEvvLXHtpzKWL88SY6wCGEoPgpsQhEGHlyYGFg,540
|
13
13
|
cocoindex/lib.py,sha256=f--9dAYd84CZosbDZqNW0oGbBLsY3dXiUTR1VrfQ_QY,817
|
14
14
|
cocoindex/llm.py,sha256=Pv_cdnRngTLtuLU9AUmS8izIHhcKVnuBNolC33f9BDI,851
|
15
|
-
cocoindex/op.py,sha256=
|
15
|
+
cocoindex/op.py,sha256=kdcWAOvvMxTVTinOZK6cVi8tY59G6VOdVuTV8fUJy0A,22714
|
16
16
|
cocoindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
cocoindex/runtime.py,sha256=povilB3HH3y1JF-yxKwU-pD8n2WnAqyQxIgvXXHNc60,1080
|
18
18
|
cocoindex/setting.py,sha256=n5ipJ_uMFZBh5-Ib_gyjOqS_XPXsQwTFVYEuSAnoscg,5283
|
19
19
|
cocoindex/setup.py,sha256=7uIHKN4FOCuoidPXcKyGTrkqpkl9luL49-6UcnMxYzw,3068
|
20
20
|
cocoindex/sources.py,sha256=69COA4qbZDipzGYfXv-WJSmicFkA509xIShRGDh6A0A,2083
|
21
|
+
cocoindex/subprocess_exec.py,sha256=davnBvbw119NBaFX6s9IyHW9MTZyrYYuKYex0HManHY,7902
|
21
22
|
cocoindex/targets.py,sha256=Nfh_tpFd1goTnS_cxBjIs4j9zl3Z4Z1JomAQ1dl3Sic,2796
|
22
23
|
cocoindex/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
|
-
cocoindex/tests/test_convert.py,sha256=
|
24
|
+
cocoindex/tests/test_convert.py,sha256=UsQDuz7qukT9UAU5LBv3atNTqdUVc6uW8lrmLA7ys_w,50207
|
24
25
|
cocoindex/tests/test_optional_database.py,sha256=snAmkNa6wtOSaxoZE1HgjvL5v_ylitt3Jt_9df4Cgdc,8506
|
25
|
-
cocoindex/tests/test_transform_flow.py,sha256=
|
26
|
+
cocoindex/tests/test_transform_flow.py,sha256=MdIzLdIMBPlIfKRFAB7n8gIZixqChL6xb4vScvcyiNU,5148
|
26
27
|
cocoindex/tests/test_typing.py,sha256=9OF3lO2uSpZBefkEJx7WRbnkXjwQtvlQIeeARYQID68,12391
|
27
28
|
cocoindex/tests/test_validation.py,sha256=X6AQzVs-hVKIXcrHMEMQnhfUE8at7iXQnPq8nHNhZ2Q,4543
|
28
29
|
cocoindex/typing.py,sha256=qQ0ANF3iuQDeSqipHgL2SDiiXL2reTMUN0aj4ve_T0w,13359
|
30
|
+
cocoindex/user_app_loader.py,sha256=o2n25y7CGw9Qrb-RN6tiNlv2YJ9YLM8NSMhJZjLhhKQ,1914
|
29
31
|
cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
|
30
32
|
cocoindex/validation.py,sha256=PZnJoby4sLbsmPv9fOjOQXuefjfZ7gmtsiTGU8SH-tc,3090
|
31
|
-
cocoindex-0.1.
|
33
|
+
cocoindex-0.1.82.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|