cocoindex 0.1.62__cp311-cp311-manylinux_2_28_aarch64.whl → 0.1.64__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/cli.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import atexit
2
+ import asyncio
2
3
  import datetime
3
4
  import importlib.util
4
5
  import os
@@ -18,6 +19,7 @@ from rich.table import Table
18
19
 
19
20
  from . import flow, lib, setting
20
21
  from .setup import flow_names_with_setup
22
+ from .runtime import execution_context
21
23
 
22
24
  # Create ServerSettings lazily upon first call, as environment variables may be loaded from files, etc.
23
25
  COCOINDEX_HOST = "https://cocoindex.io"
@@ -267,6 +269,21 @@ def _setup_flows(
267
269
  setup_bundle.apply(report_to_stdout=not quiet)
268
270
 
269
271
 
272
+ def _show_no_live_update_hint() -> None:
273
+ click.secho(
274
+ "NOTE: No change capture mechanism exists. See https://cocoindex.io/docs/core/flow_methods#live-update for more details.\n",
275
+ fg="yellow",
276
+ )
277
+
278
+
279
+ async def _update_all_flows_with_hint_async(
280
+ options: flow.FlowLiveUpdaterOptions,
281
+ ) -> None:
282
+ await flow.update_all_flows_async(options)
283
+ if options.live_mode:
284
+ _show_no_live_update_hint()
285
+
286
+
270
287
  @cli.command()
271
288
  @click.argument("app_target", type=str)
272
289
  @click.option(
@@ -398,7 +415,7 @@ def update(
398
415
  setup: bool, # pylint: disable=redefined-outer-name
399
416
  force: bool,
400
417
  quiet: bool,
401
- ) -> Any:
418
+ ) -> None:
402
419
  """
403
420
  Update the index to reflect the latest data from data sources.
404
421
 
@@ -410,8 +427,8 @@ def update(
410
427
 
411
428
  if live:
412
429
  click.secho(
413
- "NOTE: Flow code changes will NOT be reflected in the server until you restart it.",
414
- fg="red",
430
+ "NOTE: Flow code changes will NOT be reflected until you restart to load the new code.\n",
431
+ fg="yellow",
415
432
  )
416
433
 
417
434
  options = flow.FlowLiveUpdaterOptions(live_mode=live, print_stats=not quiet)
@@ -422,14 +439,15 @@ def update(
422
439
  force=force,
423
440
  quiet=quiet,
424
441
  )
425
- return flow.update_all_flows(options)
442
+ execution_context.run(_update_all_flows_with_hint_async(options))
426
443
  else:
427
444
  fl = flow.flow_by_name(flow_name)
428
445
  if setup:
429
446
  _setup_flows((fl,), force=force, quiet=quiet)
430
447
  with flow.FlowLiveUpdater(fl, options) as updater:
431
448
  updater.wait()
432
- return updater.update_stats()
449
+ if options.live_mode:
450
+ _show_no_live_update_hint()
433
451
 
434
452
 
435
453
  @cli.command()
@@ -604,8 +622,8 @@ def server(
604
622
  )
605
623
  else:
606
624
  click.secho(
607
- "NOTE: Flow code changes will NOT be reflected in the server until you restart it. Use --reload to enable auto-reload.",
608
- fg="red",
625
+ "NOTE: Flow code changes will NOT be reflected until you restart to load the new code. Use --reload to enable auto-reload.\n",
626
+ fg="yellow",
609
627
  )
610
628
  _run_server(*args)
611
629
 
@@ -650,10 +668,6 @@ def _run_server(
650
668
  quiet=quiet,
651
669
  )
652
670
 
653
- if live_update:
654
- options = flow.FlowLiveUpdaterOptions(live_mode=True, print_stats=not quiet)
655
- flow.update_all_flows(options)
656
-
657
671
  lib.start_server(server_settings)
658
672
 
659
673
  if COCOINDEX_HOST in cors_origins:
@@ -661,6 +675,12 @@ def _run_server(
661
675
 
662
676
  click.secho("Press Ctrl+C to stop the server.", fg="yellow")
663
677
 
678
+ if live_update:
679
+ options = flow.FlowLiveUpdaterOptions(live_mode=True, print_stats=not quiet)
680
+ asyncio.run_coroutine_threadsafe(
681
+ _update_all_flows_with_hint_async(options), execution_context.event_loop
682
+ )
683
+
664
684
  shutdown_event = threading.Event()
665
685
 
666
686
  def handle_signal(signum: int, frame: FrameType | None) -> None:
cocoindex/convert.py CHANGED
@@ -18,6 +18,7 @@ from .typing import (
18
18
  encode_enriched_type,
19
19
  extract_ndarray_scalar_dtype,
20
20
  is_namedtuple_type,
21
+ is_struct_type,
21
22
  )
22
23
 
23
24
 
@@ -37,9 +38,15 @@ def encode_engine_value(value: Any) -> Any:
37
38
  if isinstance(value, (list, tuple)):
38
39
  return [encode_engine_value(v) for v in value]
39
40
  if isinstance(value, dict):
40
- return [
41
- [encode_engine_value(k)] + encode_engine_value(v) for k, v in value.items()
42
- ]
41
+ if not value:
42
+ return {}
43
+
44
+ first_val = next(iter(value.values()))
45
+ if is_struct_type(type(first_val)): # KTable
46
+ return [
47
+ [encode_engine_value(k)] + encode_engine_value(v)
48
+ for k, v in value.items()
49
+ ]
43
50
  return value
44
51
 
45
52
 
cocoindex/flow.py CHANGED
@@ -198,18 +198,42 @@ class DataSlice(Generic[T]):
198
198
  raise KeyError(field_name)
199
199
  return DataSlice(_DataSliceState(self._state.flow_builder_state, field_slice))
200
200
 
201
- def row(self) -> DataScope:
201
+ def row(
202
+ self,
203
+ /,
204
+ *,
205
+ max_inflight_rows: int | None = None,
206
+ max_inflight_bytes: int | None = None,
207
+ ) -> DataScope:
202
208
  """
203
209
  Return a scope representing each row of the table.
204
210
  """
205
- row_scope = self._state.engine_data_slice.table_row_scope()
211
+ row_scope = self._state.flow_builder_state.engine_flow_builder.for_each(
212
+ self._state.engine_data_slice,
213
+ execution_options=dump_engine_object(
214
+ _ExecutionOptions(
215
+ max_inflight_rows=max_inflight_rows,
216
+ max_inflight_bytes=max_inflight_bytes,
217
+ ),
218
+ ),
219
+ )
206
220
  return DataScope(self._state.flow_builder_state, row_scope)
207
221
 
208
- def for_each(self, f: Callable[[DataScope], None]) -> None:
222
+ def for_each(
223
+ self,
224
+ f: Callable[[DataScope], None],
225
+ /,
226
+ *,
227
+ max_inflight_rows: int | None = None,
228
+ max_inflight_bytes: int | None = None,
229
+ ) -> None:
209
230
  """
210
231
  Apply a function to each row of the collection.
211
232
  """
212
- with self.row() as scope:
233
+ with self.row(
234
+ max_inflight_rows=max_inflight_rows,
235
+ max_inflight_bytes=max_inflight_bytes,
236
+ ) as scope:
213
237
  f(scope)
214
238
 
215
239
  def transform(
@@ -418,7 +442,8 @@ class _SourceRefreshOptions:
418
442
 
419
443
  @dataclass
420
444
  class _ExecutionOptions:
421
- max_inflight_count: int | None = None
445
+ max_inflight_rows: int | None = None
446
+ max_inflight_bytes: int | None = None
422
447
 
423
448
 
424
449
  class FlowBuilder:
@@ -444,7 +469,8 @@ class FlowBuilder:
444
469
  *,
445
470
  name: str | None = None,
446
471
  refresh_interval: datetime.timedelta | None = None,
447
- max_inflight_count: int | None = None,
472
+ max_inflight_rows: int | None = None,
473
+ max_inflight_bytes: int | None = None,
448
474
  ) -> DataSlice[T]:
449
475
  """
450
476
  Import a source to the flow.
@@ -464,7 +490,10 @@ class FlowBuilder:
464
490
  _SourceRefreshOptions(refresh_interval=refresh_interval)
465
491
  ),
466
492
  execution_options=dump_engine_object(
467
- _ExecutionOptions(max_inflight_count=max_inflight_count)
493
+ _ExecutionOptions(
494
+ max_inflight_rows=max_inflight_rows,
495
+ max_inflight_bytes=max_inflight_bytes,
496
+ )
468
497
  ),
469
498
  ),
470
499
  name,
cocoindex/setting.py CHANGED
@@ -43,6 +43,15 @@ class DatabaseConnectionSpec:
43
43
  password: str | None = None
44
44
 
45
45
 
46
+ @dataclass
47
+ class DefaultExecutionOptions:
48
+ """Default execution options."""
49
+
50
+ # The maximum number of concurrent inflight requests.
51
+ source_max_inflight_rows: int | None = 256
52
+ source_max_inflight_bytes: int | None = 1024 * 1024 * 1024
53
+
54
+
46
55
  def _load_field(
47
56
  target: dict[str, Any],
48
57
  name: str,
@@ -55,7 +64,15 @@ def _load_field(
55
64
  if required:
56
65
  raise ValueError(f"{env_name} is not set")
57
66
  else:
58
- target[name] = value if parse is None else parse(value)
67
+ if parse is None:
68
+ target[name] = value
69
+ else:
70
+ try:
71
+ target[name] = parse(value)
72
+ except Exception as e:
73
+ raise ValueError(
74
+ f"failed to parse environment variable {env_name}: {value}"
75
+ ) from e
59
76
 
60
77
 
61
78
  @dataclass
@@ -64,6 +81,7 @@ class Settings:
64
81
 
65
82
  database: DatabaseConnectionSpec | None = None
66
83
  app_namespace: str = ""
84
+ default_execution_options: DefaultExecutionOptions | None = None
67
85
 
68
86
  @classmethod
69
87
  def from_env(cls) -> Self:
@@ -79,9 +97,28 @@ class Settings:
79
97
  else:
80
98
  database = None
81
99
 
100
+ exec_kwargs: dict[str, Any] = dict()
101
+ _load_field(
102
+ exec_kwargs,
103
+ "source_max_inflight_rows",
104
+ "COCOINDEX_SOURCE_MAX_INFLIGHT_ROWS",
105
+ parse=int,
106
+ )
107
+ _load_field(
108
+ exec_kwargs,
109
+ "source_max_inflight_bytes",
110
+ "COCOINDEX_SOURCE_MAX_INFLIGHT_BYTES",
111
+ parse=int,
112
+ )
113
+ default_execution_options = DefaultExecutionOptions(**exec_kwargs)
114
+
82
115
  app_namespace = os.getenv("COCOINDEX_APP_NAMESPACE", "")
83
116
 
84
- return cls(database=database, app_namespace=app_namespace)
117
+ return cls(
118
+ database=database,
119
+ app_namespace=app_namespace,
120
+ default_execution_options=default_execution_options,
121
+ )
85
122
 
86
123
 
87
124
  @dataclass
@@ -93,7 +93,7 @@ def validate_full_roundtrip_to(
93
93
  def eq(a: Any, b: Any) -> bool:
94
94
  if isinstance(a, np.ndarray) and isinstance(b, np.ndarray):
95
95
  return np.array_equal(a, b)
96
- return type(a) == type(b) and not not (a == b)
96
+ return type(a) is type(b) and not not (a == b)
97
97
 
98
98
  encoded_value = encode_engine_value(value)
99
99
  value_type = value_type or type(value)
@@ -229,6 +229,11 @@ def test_encode_engine_value_none() -> None:
229
229
 
230
230
 
231
231
  def test_roundtrip_basic_types() -> None:
232
+ validate_full_roundtrip(b"hello world", bytes, (b"hello world", None))
233
+ validate_full_roundtrip(b"\x00\x01\x02\xff\xfe", bytes)
234
+ validate_full_roundtrip("hello", str, ("hello", None))
235
+ validate_full_roundtrip(True, bool, (True, None))
236
+ validate_full_roundtrip(False, bool, (False, None))
232
237
  validate_full_roundtrip(
233
238
  42, cocoindex.Int64, (42, int), (np.int64(42), np.int64), (42, None)
234
239
  )
@@ -252,10 +257,29 @@ def test_roundtrip_basic_types() -> None:
252
257
  )
253
258
  validate_full_roundtrip(np.float32(3.25), np.float32, (3.25, Float32))
254
259
 
255
- validate_full_roundtrip("hello", str, ("hello", None))
256
- validate_full_roundtrip(True, bool, (True, None))
257
- validate_full_roundtrip(False, bool, (False, None))
258
- validate_full_roundtrip((1, 2), cocoindex.Range, ((1, 2), None))
260
+
261
+ def test_roundtrip_uuid() -> None:
262
+ uuid_value = uuid.uuid4()
263
+ validate_full_roundtrip(uuid_value, uuid.UUID, (uuid_value, None))
264
+
265
+
266
+ def test_roundtrip_range() -> None:
267
+ r1 = (0, 100)
268
+ validate_full_roundtrip(r1, cocoindex.Range, (r1, None))
269
+ r2 = (50, 50)
270
+ validate_full_roundtrip(r2, cocoindex.Range, (r2, None))
271
+ r3 = (0, 1_000_000_000)
272
+ validate_full_roundtrip(r3, cocoindex.Range, (r3, None))
273
+
274
+
275
+ def test_roundtrip_time() -> None:
276
+ t1 = datetime.time(10, 30, 50, 123456)
277
+ validate_full_roundtrip(t1, datetime.time, (t1, None))
278
+ t2 = datetime.time(23, 59, 59)
279
+ validate_full_roundtrip(t2, datetime.time, (t2, None))
280
+ t3 = datetime.time(0, 0, 0)
281
+ validate_full_roundtrip(t3, datetime.time, (t3, None))
282
+
259
283
  validate_full_roundtrip(
260
284
  datetime.date(2025, 1, 1), datetime.date, (datetime.date(2025, 1, 1), None)
261
285
  )
@@ -297,8 +321,38 @@ def test_roundtrip_basic_types() -> None:
297
321
  ),
298
322
  )
299
323
 
300
- uuid_value = uuid.uuid4()
301
- validate_full_roundtrip(uuid_value, uuid.UUID, (uuid_value, None))
324
+
325
+ def test_roundtrip_timedelta() -> None:
326
+ td1 = datetime.timedelta(
327
+ days=5, seconds=10, microseconds=123, milliseconds=456, minutes=30, hours=2
328
+ )
329
+ validate_full_roundtrip(td1, datetime.timedelta, (td1, None))
330
+ td2 = datetime.timedelta(days=-5, hours=-2)
331
+ validate_full_roundtrip(td2, datetime.timedelta, (td2, None))
332
+ td3 = datetime.timedelta(0)
333
+ validate_full_roundtrip(td3, datetime.timedelta, (td3, None))
334
+
335
+
336
+ def test_roundtrip_json() -> None:
337
+ simple_dict = {"key": "value", "number": 123, "bool": True, "float": 1.23}
338
+ validate_full_roundtrip(simple_dict, cocoindex.Json)
339
+
340
+ simple_list = [1, "string", False, None, 4.56]
341
+ validate_full_roundtrip(simple_list, cocoindex.Json)
342
+
343
+ nested_structure = {
344
+ "name": "Test Json",
345
+ "version": 1.0,
346
+ "items": [
347
+ {"id": 1, "value": "item1"},
348
+ {"id": 2, "value": None, "props": {"active": True}},
349
+ ],
350
+ "metadata": None,
351
+ }
352
+ validate_full_roundtrip(nested_structure, cocoindex.Json)
353
+
354
+ validate_full_roundtrip({}, cocoindex.Json)
355
+ validate_full_roundtrip([], cocoindex.Json)
302
356
 
303
357
 
304
358
  def test_decode_scalar_numpy_values() -> None:
@@ -675,6 +729,21 @@ def test_roundtrip_union_with_vector() -> None:
675
729
  validate_full_roundtrip(value, t, ([1.0, 2.0, 3.0], list[float] | str))
676
730
 
677
731
 
732
+ def test_roundtrip_union_with_misc_types() -> None:
733
+ t_bytes_union = int | bytes | str
734
+ validate_full_roundtrip(b"test_bytes", t_bytes_union)
735
+ validate_full_roundtrip(123, t_bytes_union)
736
+
737
+ t_range_union = cocoindex.Range | str | bool
738
+ validate_full_roundtrip((100, 200), t_range_union)
739
+ validate_full_roundtrip("test_string", t_range_union)
740
+
741
+ t_json_union = cocoindex.Json | int | bytes
742
+ json_dict = {"a": 1, "b": [2, 3]}
743
+ validate_full_roundtrip(json_dict, t_json_union)
744
+ validate_full_roundtrip(b"another_byte_string", t_json_union)
745
+
746
+
678
747
  def test_roundtrip_ltable() -> None:
679
748
  t = list[Order]
680
749
  value = [Order("O1", "item1", 10.0), Order("O2", "item2", 20.0)]
@@ -688,10 +757,26 @@ def test_roundtrip_ltable() -> None:
688
757
  validate_full_roundtrip(value_nt, t_nt)
689
758
 
690
759
 
691
- def test_roundtrip_ktable_str_key() -> None:
692
- t = dict[str, Order]
693
- value = {"K1": Order("O1", "item1", 10.0), "K2": Order("O2", "item2", 20.0)}
694
- validate_full_roundtrip(value, t)
760
+ def test_roundtrip_ktable_various_key_types() -> None:
761
+ @dataclass
762
+ class SimpleValue:
763
+ data: str
764
+
765
+ t_bytes_key = dict[bytes, SimpleValue]
766
+ value_bytes_key = {b"key1": SimpleValue("val1"), b"key2": SimpleValue("val2")}
767
+ validate_full_roundtrip(value_bytes_key, t_bytes_key)
768
+
769
+ t_int_key = dict[int, SimpleValue]
770
+ value_int_key = {1: SimpleValue("val1"), 2: SimpleValue("val2")}
771
+ validate_full_roundtrip(value_int_key, t_int_key)
772
+
773
+ t_bool_key = dict[bool, SimpleValue]
774
+ value_bool_key = {True: SimpleValue("val_true"), False: SimpleValue("val_false")}
775
+ validate_full_roundtrip(value_bool_key, t_bool_key)
776
+
777
+ t_str_key = dict[str, Order]
778
+ value_str_key = {"K1": Order("O1", "item1", 10.0), "K2": Order("O2", "item2", 20.0)}
779
+ validate_full_roundtrip(value_str_key, t_str_key)
695
780
 
696
781
  t_nt = dict[str, OrderNamedTuple]
697
782
  value_nt = {
@@ -700,6 +785,27 @@ def test_roundtrip_ktable_str_key() -> None:
700
785
  }
701
786
  validate_full_roundtrip(value_nt, t_nt)
702
787
 
788
+ t_range_key = dict[cocoindex.Range, SimpleValue]
789
+ value_range_key = {
790
+ (1, 10): SimpleValue("val_range1"),
791
+ (20, 30): SimpleValue("val_range2"),
792
+ }
793
+ validate_full_roundtrip(value_range_key, t_range_key)
794
+
795
+ t_date_key = dict[datetime.date, SimpleValue]
796
+ value_date_key = {
797
+ datetime.date(2023, 1, 1): SimpleValue("val_date1"),
798
+ datetime.date(2024, 2, 2): SimpleValue("val_date2"),
799
+ }
800
+ validate_full_roundtrip(value_date_key, t_date_key)
801
+
802
+ t_uuid_key = dict[uuid.UUID, SimpleValue]
803
+ value_uuid_key = {
804
+ uuid.uuid4(): SimpleValue("val_uuid1"),
805
+ uuid.uuid4(): SimpleValue("val_uuid2"),
806
+ }
807
+ validate_full_roundtrip(value_uuid_key, t_uuid_key)
808
+
703
809
 
704
810
  def test_roundtrip_ktable_struct_key() -> None:
705
811
  @dataclass(frozen=True)
@@ -990,6 +1096,24 @@ def test_full_roundtrip_vector_numeric_types() -> None:
990
1096
  validate_full_roundtrip(value_u64, Vector[np.uint64, Literal[3]])
991
1097
 
992
1098
 
1099
+ def test_full_roundtrip_vector_other_types() -> None:
1100
+ """Test full roundtrip for Vector with non-numeric basic types."""
1101
+ uuid_list = [uuid.uuid4(), uuid.uuid4()]
1102
+ validate_full_roundtrip(uuid_list, Vector[uuid.UUID], (uuid_list, list[uuid.UUID]))
1103
+
1104
+ date_list = [datetime.date(2023, 1, 1), datetime.date(2024, 10, 5)]
1105
+ validate_full_roundtrip(
1106
+ date_list, Vector[datetime.date], (date_list, list[datetime.date])
1107
+ )
1108
+
1109
+ bool_list = [True, False, True, False]
1110
+ validate_full_roundtrip(bool_list, Vector[bool], (bool_list, list[bool]))
1111
+
1112
+ validate_full_roundtrip([], Vector[uuid.UUID], ([], list[uuid.UUID]))
1113
+ validate_full_roundtrip([], Vector[datetime.date], ([], list[datetime.date]))
1114
+ validate_full_roundtrip([], Vector[bool], ([], list[bool]))
1115
+
1116
+
993
1117
  def test_roundtrip_vector_no_dimension() -> None:
994
1118
  """Test full roundtrip for vector types without dimension annotation."""
995
1119
  value_f64 = np.array([1.0, 2.0, 3.0], dtype=np.float64)
cocoindex/typing.py CHANGED
@@ -108,7 +108,7 @@ def is_namedtuple_type(t: type) -> bool:
108
108
  return isinstance(t, type) and issubclass(t, tuple) and hasattr(t, "_fields")
109
109
 
110
110
 
111
- def _is_struct_type(t: ElementType | None) -> bool:
111
+ def is_struct_type(t: ElementType | None) -> bool:
112
112
  return isinstance(t, type) and (
113
113
  dataclasses.is_dataclass(t) or is_namedtuple_type(t)
114
114
  )
@@ -205,7 +205,7 @@ def analyze_type_info(t: Any) -> AnalyzedTypeInfo:
205
205
  union_variant_types: typing.List[ElementType] | None = None
206
206
  key_type: type | None = None
207
207
  np_number_type: type | None = None
208
- if _is_struct_type(t):
208
+ if is_struct_type(t):
209
209
  struct_type = t
210
210
 
211
211
  if kind is None:
@@ -220,7 +220,7 @@ def analyze_type_info(t: Any) -> AnalyzedTypeInfo:
220
220
  elem_type = args[0]
221
221
 
222
222
  if kind is None:
223
- if _is_struct_type(elem_type):
223
+ if is_struct_type(elem_type):
224
224
  kind = "LTable"
225
225
  if vector_info is not None:
226
226
  raise ValueError(
@@ -243,7 +243,7 @@ def analyze_type_info(t: Any) -> AnalyzedTypeInfo:
243
243
  args = typing.get_args(t)
244
244
  elem_type = (args[0], args[1])
245
245
  kind = "KTable"
246
- elif base_type is types.UnionType:
246
+ elif base_type in (types.UnionType, typing.Union):
247
247
  possible_types = typing.get_args(t)
248
248
  non_none_types = [
249
249
  arg for arg in possible_types if arg not in (None, types.NoneType)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cocoindex
3
- Version: 0.1.62
3
+ Version: 0.1.64
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
@@ -162,6 +162,7 @@ It defines an index flow like this:
162
162
  | [FastAPI Server with Docker](examples/fastapi_server_docker) | Run the semantic search server in a Dockerized FastAPI setup |
163
163
  | [Product Recommendation](examples/product_recommendation) | Build real-time product recommendations with LLM and graph database|
164
164
  | [Image Search with Vision API](examples/image_search) | Generates detailed captions for images using a vision model, embeds them, enables live-updating semantic search via FastAPI and served on a React frontend|
165
+ | [Paper Metadata](examples/paper_metadata) | Index papers in PDF files, and build metadata tables for each paper |
165
166
 
166
167
  More coming and stay tuned 👀!
167
168
 
@@ -1,13 +1,13 @@
1
- cocoindex-0.1.62.dist-info/METADATA,sha256=zLkmmjLMos6lgZF4pDNIJzlhx4WCr3lhwWHBrBWtEzA,10020
2
- cocoindex-0.1.62.dist-info/WHEEL,sha256=sV4rA9gfzC7j5ItBe_WAiMMgsSnxbuMxVbhOxuTV0TE,109
3
- cocoindex-0.1.62.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
- cocoindex-0.1.62.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1
+ cocoindex-0.1.64.dist-info/METADATA,sha256=ByEFBlXrGkbESv0twsq2eLycjhTdkQKnE_EzQVIpWgQ,10136
2
+ cocoindex-0.1.64.dist-info/WHEEL,sha256=tYU0YwShGV5a1IBa9K6b40tOXRGPW5TH008p3c7dncU,109
3
+ cocoindex-0.1.64.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
+ cocoindex-0.1.64.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
5
5
  cocoindex/__init__.py,sha256=hDjehCjxRabFCW0RTt00JxnSAJIn9HeVoK4OjFbETsk,1910
6
- cocoindex/_engine.cpython-311-aarch64-linux-gnu.so,sha256=OOUet4oqGjo9xeH_XgZ3UFgfd858M3K0aAy22e3mA84,60998736
6
+ cocoindex/_engine.cpython-311-aarch64-linux-gnu.so,sha256=a6r52tacUnzRqxo_W26iQ7fbR3qdCMb8umOaJ6-TLUs,61287640
7
7
  cocoindex/auth_registry.py,sha256=1XqO7ibjmBBd8i11XSJTvTgdz8p1ptW-ZpuSgo_5zzk,716
8
- cocoindex/cli.py,sha256=YpAn6awBlPHtTvDcHQk3xXS1PDlF4HDs5ak6t2da_WE,21695
9
- cocoindex/convert.py,sha256=FsKb2Pfbm7e1VQDOs_AsoiW9PbIUuyHQuqUlrENXmUY,11199
10
- cocoindex/flow.py,sha256=x13SDZvFZ-MR-gGF1HPp14DMSn0vp37cfz0YFK9Pmy8,33334
8
+ cocoindex/cli.py,sha256=-gp639JSyQN6YjnhGqCakIzYoSSqXxQMbxbkcYGP0QY,22359
9
+ cocoindex/convert.py,sha256=qE1Ut_tAwX4wA4WqaWxpyj80-1t6WZ8Oi5_L9Mw5g4k,11393
10
+ cocoindex/flow.py,sha256=Rb3ImrFa-TKYZXZnfcTj4ePUZXqKgJCzZR4OYHP6rlk,34207
11
11
  cocoindex/functions.py,sha256=IBwvdPpGR-S5mk53HvHpT2GVs15MI9wQznxgOdxA0ac,3202
12
12
  cocoindex/index.py,sha256=j93B9jEvvLXHtpzKWL88SY6wCGEoPgpsQhEGHlyYGFg,540
13
13
  cocoindex/lib.py,sha256=f--9dAYd84CZosbDZqNW0oGbBLsY3dXiUTR1VrfQ_QY,817
@@ -15,14 +15,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
18
- cocoindex/setting.py,sha256=Zl8K86r8RVvG9c3pCsH0Ot8BHhDAQAQCjoBp7TnXMLQ,3590
18
+ cocoindex/setting.py,sha256=FMNjer3YVmVyxLuGt6_DJ6vA1QH1mIo7oH0R51OLnk4,4714
19
19
  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=WmgbaQTYPDnjBfMlIrZWBHipPW7SlrvHYsLLqb--KH0,38025
23
+ cocoindex/tests/test_convert.py,sha256=efwF-43SFJiu85sQ78Z9k9OaJphTz_es_1cm5BoPO2Y,42565
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=s_Hk4Npi8pxJUM2h_7Km0VFrojA8wJU9VDtRqVSL6C0,12622
26
+ cocoindex/typing.py,sha256=qQ-nSdkHzu8pSxfuR5sGGfoE8nCKqCDb0D9jbmxVt4M,12635
27
27
  cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
28
- cocoindex-0.1.62.dist-info/RECORD,,
28
+ cocoindex-0.1.64.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: maturin (1.9.0)
2
+ Generator: maturin (1.9.1)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp311-cp311-manylinux_2_28_aarch64