cocoindex 0.1.21__cp312-cp312-manylinux_2_28_aarch64.whl → 0.1.23__cp312-cp312-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/convert.py CHANGED
@@ -117,7 +117,10 @@ def dump_engine_object(v: Any) -> Any:
117
117
  nanos = int((total_secs - secs) * 1e9)
118
118
  return {'secs': secs, 'nanos': nanos}
119
119
  elif hasattr(v, '__dict__'):
120
- return {k: dump_engine_object(v) for k, v in v.__dict__.items()}
120
+ s = {k: dump_engine_object(v) for k, v in v.__dict__.items()}
121
+ if hasattr(v, 'kind') and 'kind' not in s:
122
+ s['kind'] = v.kind
123
+ return s
121
124
  elif isinstance(v, (list, tuple)):
122
125
  return [dump_engine_object(item) for item in v]
123
126
  elif isinstance(v, dict):
cocoindex/functions.py CHANGED
@@ -5,6 +5,9 @@ import sentence_transformers
5
5
  from .typing import Float32, Vector, TypeAttr
6
6
  from . import op, llm
7
7
 
8
+ class ParseJson(op.FunctionSpec):
9
+ """Parse a text into a JSON object."""
10
+
8
11
  class SplitRecursively(op.FunctionSpec):
9
12
  """Split a document (in string) recursively."""
10
13
 
cocoindex/storages.py CHANGED
@@ -21,7 +21,7 @@ class Qdrant(op.StorageSpec):
21
21
  api_key: str | None = None
22
22
 
23
23
  @dataclass
24
- class Neo4jConnectionSpec:
24
+ class Neo4jConnection:
25
25
  """Connection spec for Neo4j."""
26
26
  uri: str
27
27
  user: str
@@ -29,7 +29,7 @@ class Neo4jConnectionSpec:
29
29
  db: str | None = None
30
30
 
31
31
  @dataclass
32
- class Neo4jFieldMapping:
32
+ class GraphFieldMapping:
33
33
  """Mapping for a Neo4j field."""
34
34
  field_name: str
35
35
  # Field name for the node in the Knowledge Graph.
@@ -37,22 +37,36 @@ class Neo4jFieldMapping:
37
37
  node_field_name: str | None = None
38
38
 
39
39
  @dataclass
40
- class Neo4jRelationshipEndSpec:
40
+ class GraphRelationshipEnd:
41
41
  """Spec for a Neo4j node type."""
42
42
  label: str
43
- fields: list[Neo4jFieldMapping]
43
+ fields: list[GraphFieldMapping]
44
44
 
45
45
  @dataclass
46
- class Neo4jRelationshipNodeSpec:
46
+ class GraphRelationshipNode:
47
47
  """Spec for a Neo4j node type."""
48
48
  primary_key_fields: Sequence[str]
49
49
  vector_indexes: Sequence[index.VectorIndexDef] = ()
50
50
 
51
- class Neo4jRelationship(op.StorageSpec):
51
+ @dataclass
52
+ class GraphNode:
53
+ """Spec for a Neo4j node type."""
54
+ kind = "Node"
55
+
56
+ label: str
57
+
58
+ @dataclass
59
+ class GraphRelationship:
60
+ """Spec for a Neo4j relationship."""
61
+ kind = "Relationship"
62
+
63
+ rel_type: str
64
+ source: GraphRelationshipEnd
65
+ target: GraphRelationshipEnd
66
+ nodes: dict[str, GraphRelationshipNode] | None = None
67
+
68
+ class Neo4j(op.StorageSpec):
52
69
  """Graph storage powered by Neo4j."""
53
70
 
54
71
  connection: AuthEntryReference
55
- rel_type: str
56
- source: Neo4jRelationshipEndSpec
57
- target: Neo4jRelationshipEndSpec
58
- nodes: dict[str, Neo4jRelationshipNodeSpec]
72
+ mapping: GraphNode | GraphRelationship
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,69 @@
1
+ import dataclasses
2
+ import uuid
3
+ import datetime
4
+ from dataclasses import dataclass
5
+ import pytest
6
+ from cocoindex.convert import to_engine_value
7
+
8
+ @dataclass
9
+ class Order:
10
+ order_id: str
11
+ name: str
12
+ price: float
13
+
14
+ @dataclass
15
+ class Basket:
16
+ items: list
17
+
18
+ @dataclass
19
+ class Customer:
20
+ name: str
21
+ order: Order
22
+
23
+ def test_to_engine_value_basic_types():
24
+ assert to_engine_value(123) == 123
25
+ assert to_engine_value(3.14) == 3.14
26
+ assert to_engine_value("hello") == "hello"
27
+ assert to_engine_value(True) is True
28
+
29
+ def test_to_engine_value_uuid():
30
+ u = uuid.uuid4()
31
+ assert to_engine_value(u) == u.bytes
32
+
33
+ def test_to_engine_value_date_time_types():
34
+ d = datetime.date(2024, 1, 1)
35
+ assert to_engine_value(d) == d
36
+ t = datetime.time(12, 30)
37
+ assert to_engine_value(t) == t
38
+ dt = datetime.datetime(2024, 1, 1, 12, 30)
39
+ assert to_engine_value(dt) == dt
40
+
41
+ def test_to_engine_value_struct():
42
+ order = Order(order_id="O123", name="mixed nuts", price=25.0)
43
+ assert to_engine_value(order) == ["O123", "mixed nuts", 25.0]
44
+
45
+ def test_to_engine_value_list_of_structs():
46
+ orders = [Order("O1", "item1", 10.0), Order("O2", "item2", 20.0)]
47
+ assert to_engine_value(orders) == [["O1", "item1", 10.0], ["O2", "item2", 20.0]]
48
+
49
+ def test_to_engine_value_struct_with_list():
50
+ basket = Basket(items=["apple", "banana"])
51
+ assert to_engine_value(basket) == [["apple", "banana"]]
52
+
53
+ def test_to_engine_value_nested_struct():
54
+ customer = Customer(name="Alice", order=Order("O1", "item1", 10.0))
55
+ assert to_engine_value(customer) == ["Alice", ["O1", "item1", 10.0]]
56
+
57
+ def test_to_engine_value_empty_list():
58
+ assert to_engine_value([]) == []
59
+ assert to_engine_value([[]]) == [[]]
60
+
61
+ def test_to_engine_value_tuple():
62
+ assert to_engine_value(()) == []
63
+ assert to_engine_value((1, 2, 3)) == [1, 2, 3]
64
+ assert to_engine_value(((1, 2), (3, 4))) == [[1, 2], [3, 4]]
65
+ assert to_engine_value(([],)) == [[]]
66
+ assert to_engine_value(((),)) == [[]]
67
+
68
+ def test_to_engine_value_none():
69
+ assert to_engine_value(None) is None
cocoindex/typing.py CHANGED
@@ -183,11 +183,7 @@ def _encode_type(type_info: AnalyzedTypeInfo) -> dict[str, Any]:
183
183
  if type_info.elem_type is None:
184
184
  raise ValueError(f"{type_info.kind} type must have an element type")
185
185
  row_type_info = analyze_type_info(type_info.elem_type)
186
- if row_type_info.dataclass_type is None:
187
- raise ValueError(f"{type_info.kind} type must have a dataclass type")
188
- encoded_type['row'] = {
189
- 'fields': _encode_fields_schema(row_type_info.dataclass_type),
190
- }
186
+ encoded_type['row'] = _encode_type(row_type_info)
191
187
 
192
188
  return encoded_type
193
189
 
@@ -1,8 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cocoindex
3
- Version: 0.1.21
3
+ Version: 0.1.23
4
4
  Requires-Dist: sentence-transformers>=3.3.1
5
5
  Requires-Dist: click>=8.1.8
6
+ Requires-Dist: pytest ; extra == 'test'
7
+ Provides-Extra: test
6
8
  License-File: LICENSE
7
9
  Summary: With CocoIndex, users declare the transformation, CocoIndex creates & maintains an index, and keeps the derived index up to date based on source update, with minimal computation and changes.
8
10
  Author-email: CocoIndex <cocoindex.io@gmail.com>
@@ -1,21 +1,23 @@
1
- cocoindex-0.1.21.dist-info/METADATA,sha256=6e2Mq54aZuC_yMX2fWkvSjmp_XfmbuRc_Oe0m3XnORc,8005
2
- cocoindex-0.1.21.dist-info/WHEEL,sha256=xOZEB-WIKOrrrITqsx8xpY2EDgJkCu53Yhd8N6qLrYE,109
3
- cocoindex-0.1.21.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1
+ cocoindex-0.1.23.dist-info/METADATA,sha256=IcyNWcJi0ycAqXknL1KbV-tsNRQqNf3a097Xrpbe4g8,8066
2
+ cocoindex-0.1.23.dist-info/WHEEL,sha256=xOZEB-WIKOrrrITqsx8xpY2EDgJkCu53Yhd8N6qLrYE,109
3
+ cocoindex-0.1.23.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
4
4
  cocoindex/llm.py,sha256=uHXub9AWTOtxNyTaefHY-VuY_yzo6ikM1kUxHsQn-zw,298
5
+ cocoindex/tests/test_convert.py,sha256=wSAiskmBgBM5UZussbNXmCxt47hHGlSEEQVgDZaY4TE,2058
6
+ cocoindex/tests/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
5
7
  cocoindex/sources.py,sha256=wZFU8lwSXjyofJR-syySH9fTyPnBlAPJ6-1hQNX8fGA,936
6
- cocoindex/typing.py,sha256=EZstkCKOFTRST23ia8R8PV7rZbQiNWFblzzRIQ3vVcQ,7472
7
- cocoindex/storages.py,sha256=Tqrk9ROgHTjtfjgxYZqLwNU_2bQmYjbST6zOqq0ksS4,1491
8
+ cocoindex/typing.py,sha256=4mP9VXS75s3VMfF1LDc1LXsBng7uGdR5aD73N8iaeSM,7282
9
+ cocoindex/storages.py,sha256=ZWpQABuUWTs6BdPcTBWDOiRXVGxS87Uh2i_C1wtkXYQ,1718
8
10
  cocoindex/flow.py,sha256=HwngOKZyF60pUE_LGjt02yVNWh-haoMWH1Si0w5rYqY,19856
9
11
  cocoindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
12
  cocoindex/setup.py,sha256=W1HshwYk_K2aeLOVn_e62ZOXBO9yWsoUboRiH4SjF48,496
11
- cocoindex/convert.py,sha256=Nc_gFC64MkpGxkJHy9sSr9d-R916uqYyvUW7qwxS0-0,4921
13
+ cocoindex/convert.py,sha256=tzlHadc-SaZCRBWxZEp08T4clJQPab_eXt6mUub0iQQ,5017
12
14
  cocoindex/query.py,sha256=XsVY5cBJJ3a70qazkcCHjWZLE1zBqzMQ4HVSulicGMA,3273
13
15
  cocoindex/op.py,sha256=UaBgkWN8KEKqD-3UEYW_v-99OwNQZfIB4PdpAd4jd74,9984
14
16
  cocoindex/__init__.py,sha256=f4LTPg4db7Wm3QO9HirvhsT11OVykiFxGbt1JK6taFA,572
15
17
  cocoindex/cli.py,sha256=jRwGCPuqkBz_cIp7LKARCRAiDsPm91bsduKzfYJohJ4,6931
16
18
  cocoindex/lib.py,sha256=kyfzkaanrMHVwWjd2UWgLr8ArS_vjlK64qb4TbNTbbs,3464
17
- cocoindex/functions.py,sha256=uukmig7qtOIda3lrM7tNSfGqx22e0EANfWWZjuhE_5E,1579
19
+ cocoindex/functions.py,sha256=xcAeRQTy9JObfxpjyMn-dPY2y7XhVWjB7759xVyup6o,1657
18
20
  cocoindex/auth_registry.py,sha256=lZ2rD5_9aC_UpGk7t4TmSYal_rjN7eHgO4_sU7FR0Zw,620
19
21
  cocoindex/index.py,sha256=LssEOuZi6AqhwKtZM3QFeQpa9T-0ELi8G5DsrYKECvc,534
20
- cocoindex/_engine.cpython-312-aarch64-linux-gnu.so,sha256=SW0zPWuc7U8qcPAMKOF7hOyRwC9cbzZgx56tg0ok9qc,63367352
21
- cocoindex-0.1.21.dist-info/RECORD,,
22
+ cocoindex/_engine.cpython-312-aarch64-linux-gnu.so,sha256=VfLg3LJ2C_ARY8XmYKW7LXN_4YDI-gGolWNFf6ZQ5Ok,63385472
23
+ cocoindex-0.1.23.dist-info/RECORD,,