cocoindex 0.1.63__cp313-cp313-win_amd64.whl → 0.1.65__cp313-cp313-win_amd64.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 CHANGED
@@ -11,6 +11,7 @@ from .flow import FlowBuilder, DataScope, DataSlice, Flow, transform_flow
11
11
  from .flow import flow_def
12
12
  from .flow import EvaluateAndDumpOptions, GeneratedField
13
13
  from .flow import FlowLiveUpdater, FlowLiveUpdaterOptions
14
+ from .flow import add_flow_def, remove_flow
14
15
  from .flow import update_all_flows_async, setup_all_flows, drop_all_flows
15
16
  from .lib import init, start_server, stop
16
17
  from .llm import LlmSpec, LlmApiType
@@ -52,6 +53,8 @@ __all__ = [
52
53
  "GeneratedField",
53
54
  "FlowLiveUpdater",
54
55
  "FlowLiveUpdaterOptions",
56
+ "add_flow_def",
57
+ "remove_flow",
55
58
  "update_all_flows_async",
56
59
  "setup_all_flows",
57
60
  "drop_all_flows",
Binary file
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,
@@ -595,7 +624,7 @@ class Flow:
595
624
 
596
625
  _name: str
597
626
  _full_name: str
598
- _lazy_engine_flow: Callable[[], _engine.Flow]
627
+ _lazy_engine_flow: Callable[[], _engine.Flow] | None
599
628
 
600
629
  def __init__(
601
630
  self, name: str, full_name: str, engine_flow_creator: Callable[[], _engine.Flow]
@@ -635,18 +664,18 @@ class Flow:
635
664
  return tree
636
665
 
637
666
  def _get_spec(self, verbose: bool = False) -> _engine.RenderedSpec:
638
- return self._lazy_engine_flow().get_spec(
667
+ return self.internal_flow().get_spec(
639
668
  output_mode="verbose" if verbose else "concise"
640
669
  )
641
670
 
642
671
  def _get_schema(self) -> list[tuple[str, str, str]]:
643
- return cast(list[tuple[str, str, str]], self._lazy_engine_flow().get_schema())
672
+ return cast(list[tuple[str, str, str]], self.internal_flow().get_schema())
644
673
 
645
674
  def __str__(self) -> str:
646
675
  return str(self._get_spec())
647
676
 
648
677
  def __repr__(self) -> str:
649
- return repr(self._lazy_engine_flow())
678
+ return repr(self.internal_flow())
650
679
 
651
680
  @property
652
681
  def name(self) -> str:
@@ -686,12 +715,14 @@ class Flow:
686
715
  """
687
716
  Evaluate the flow and dump flow outputs to files.
688
717
  """
689
- return self._lazy_engine_flow().evaluate_and_dump(dump_engine_object(options))
718
+ return self.internal_flow().evaluate_and_dump(dump_engine_object(options))
690
719
 
691
720
  def internal_flow(self) -> _engine.Flow:
692
721
  """
693
722
  Get the engine flow.
694
723
  """
724
+ if self._lazy_engine_flow is None:
725
+ raise RuntimeError(f"Flow {self.full_name} is already removed")
695
726
  return self._lazy_engine_flow()
696
727
 
697
728
  async def internal_flow_async(self) -> _engine.Flow:
@@ -702,13 +733,13 @@ class Flow:
702
733
 
703
734
  def setup(self, report_to_stdout: bool = False) -> None:
704
735
  """
705
- Setup the flow.
736
+ Setup persistent backends of the flow.
706
737
  """
707
738
  execution_context.run(self.setup_async(report_to_stdout=report_to_stdout))
708
739
 
709
740
  async def setup_async(self, report_to_stdout: bool = False) -> None:
710
741
  """
711
- Setup the flow. The async version.
742
+ Setup persistent backends of the flow. The async version.
712
743
  """
713
744
  await make_setup_bundle([self]).describe_and_apply_async(
714
745
  report_to_stdout=report_to_stdout
@@ -716,13 +747,18 @@ class Flow:
716
747
 
717
748
  def drop(self, report_to_stdout: bool = False) -> None:
718
749
  """
719
- Drop the flow.
750
+ Drop persistent backends of the flow.
751
+
752
+ The current instance is still valid after it's called.
753
+ For example, you can still call `setup()` after it, to setup the persistent backends again.
754
+
755
+ Call `cocoindex.remove_flow()` if you want to remove the flow from the current process.
720
756
  """
721
757
  execution_context.run(self.drop_async(report_to_stdout=report_to_stdout))
722
758
 
723
759
  async def drop_async(self, report_to_stdout: bool = False) -> None:
724
760
  """
725
- Drop the flow. The async version.
761
+ Drop persistent backends of the flow. The async version.
726
762
  """
727
763
  await make_drop_bundle([self]).describe_and_apply_async(
728
764
  report_to_stdout=report_to_stdout
@@ -776,6 +812,19 @@ def add_flow_def(name: str, fl_def: Callable[[FlowBuilder, DataScope], None]) ->
776
812
  return fl
777
813
 
778
814
 
815
+ def remove_flow(fl: Flow) -> None:
816
+ """
817
+ Remove a flow from the current process to free up resources.
818
+ After it's called, methods of the flow should no longer be called.
819
+
820
+ This will NOT touch the persistent backends of the flow.
821
+ """
822
+ _engine.remove_flow_context(fl.full_name)
823
+ fl._lazy_engine_flow = None # pylint: disable=protected-access
824
+ with _flows_lock:
825
+ del _flows[fl.name]
826
+
827
+
779
828
  def flow_def(
780
829
  name: str | None = None,
781
830
  ) -> Callable[[Callable[[FlowBuilder, DataScope], None]], Flow]:
cocoindex/setting.py CHANGED
@@ -43,6 +43,15 @@ class DatabaseConnectionSpec:
43
43
  password: str | None = None
44
44
 
45
45
 
46
+ @dataclass
47
+ class GlobalExecutionOptions:
48
+ """Global execution options."""
49
+
50
+ # The maximum number of concurrent inflight requests, shared among all sources from all flows.
51
+ source_max_inflight_rows: int | None = None
52
+ source_max_inflight_bytes: int | None = None
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
+ global_execution_options: GlobalExecutionOptions | 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
+ global_execution_options = GlobalExecutionOptions(**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
+ global_execution_options=global_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.63
3
+ Version: 0.1.65
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
@@ -1,13 +1,13 @@
1
- cocoindex-0.1.63.dist-info/METADATA,sha256=r699EP8rvD8WQNrCfd584NHo-eL_g6_I6DjuMlWvFjI,10302
2
- cocoindex-0.1.63.dist-info/WHEEL,sha256=AUbk9LW_pz5a6zxr9a09TpfZobAyvDuruoOj7fuVtLM,96
3
- cocoindex-0.1.63.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
- cocoindex-0.1.63.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
5
- cocoindex/__init__.py,sha256=X5EgczBY26snczX7iDR4rshwHrHeNxWaiXxQxChvwSE,1993
6
- cocoindex/_engine.cp313-win_amd64.pyd,sha256=p2DrcrbfzPQcGyCrvf6ZxxhNXP_yJnbL92LBOtrWnN8,62023680
1
+ cocoindex-0.1.65.dist-info/METADATA,sha256=KsJCxDEvhpyJ6t44FoDuTesesP-DxVKnPAkNQezGu8k,10302
2
+ cocoindex-0.1.65.dist-info/WHEEL,sha256=oXe_QNnB5QbkkMcbfZh2d88Kje6edNs5JzpWke0-klE,96
3
+ cocoindex-0.1.65.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
+ cocoindex-0.1.65.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
5
+ cocoindex/__init__.py,sha256=d9hy0c8-vwc4aAgGzggjWaTrD0s9vHl_FvDlpBNHo9g,2079
6
+ cocoindex/_engine.cp313-win_amd64.pyd,sha256=K-X0ycCeyBA127WMw7aivq09fu5P8yBx6NBtkTayrOc,62298112
7
7
  cocoindex/auth_registry.py,sha256=LojDKoX0ccO-G3bboFMlAti50_t5GK9BS0ouPJZfyUs,745
8
8
  cocoindex/cli.py,sha256=zjZv7EH-ZLoO1-3Ua2U7Yt3n2A_T7pN2NCuv7FB8WA0,23097
9
- cocoindex/convert.py,sha256=cOqouCbaGHf2kaUrN99dQxVOJH1XyT4lXhnVZUZtgo4,11516
10
- cocoindex/flow.py,sha256=WJ2fZpzUDe3p8zAw0SJq4eLD4dMBcwR_D2U9Fh_EM4s,34414
9
+ cocoindex/convert.py,sha256=IL0jKB_J2v-gFCOOnQQrPMVsRYDgwCHaaueQ6dpmShY,11717
10
+ cocoindex/flow.py,sha256=D9J3JG6vi5COGsmJvDlBmTx58t7nE01QefPp2vRH_pg,36214
11
11
  cocoindex/functions.py,sha256=ShHLmFPN8DYqxUDFm4EUJhuoKlax8HdU7q69V47ljQo,3307
12
12
  cocoindex/index.py,sha256=GrqTm1rLwICQ8hadtNvJAxVg7GWMvtMmFcbiNtNzmP0,569
13
13
  cocoindex/lib.py,sha256=cZosix4nwROvod4QJOwCzrm6U1CVy_wKMMk7sDDG_Z0,849
@@ -15,14 +15,14 @@ cocoindex/llm.py,sha256=lNVoJ4qxNahqWoH9_bpm4gSS8A_DyeVXnnAYUftWbJ4,472
15
15
  cocoindex/op.py,sha256=h1bp56NEVxCRrOjzyta1h52u6d9Vol_Qau9Pv1sUlVE,12141
16
16
  cocoindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  cocoindex/runtime.py,sha256=saKEZntVwUVQNASRhiO9bHRVIFmQccemq2f9mo4mo1A,1090
18
- cocoindex/setting.py,sha256=dRNdX-rPBn321zGx6GGoSMggS4F2879A6EBLOUbX8R4,3717
18
+ cocoindex/setting.py,sha256=E_5Z_MqDt6vaMcqPNA67QB7h_36OBcNu50EN3WjNDts,4898
19
19
  cocoindex/setup.py,sha256=KbJvmeFu0NbeoH-5iDmHZP86f26HIId8kHmGUNZAePI,3160
20
20
  cocoindex/sources.py,sha256=4hxsntuyClp_jKH4oZbx3iE3UM4P2bZTpWy28dqdyFY,1375
21
21
  cocoindex/targets.py,sha256=7FfG9kuEf5KTXtLwXMFaPFIut3PsIbpb3XIEjjeF7Bg,2931
22
22
  cocoindex/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- cocoindex/tests/test_convert.py,sha256=Hm8n1XZx58tkKbFiN43cre38bAAV1j9XorBE2x01M4M,39132
23
+ cocoindex/tests/test_convert.py,sha256=WfHIs4UTdK-FmihFrso9urPtb31gGi2SAfdk3PfUlYk,43796
24
24
  cocoindex/tests/test_optional_database.py,sha256=dnzmTgaJf37D3q8fQsjP5UDER6FYETaUokDnFBMLtIk,8755
25
25
  cocoindex/tests/test_typing.py,sha256=6W2NQmyTj4LMuWegV5m4NVP2clVNrUa5eD28_3nwzjs,15300
26
- cocoindex/typing.py,sha256=qdVwkp3jCfWDuvzYKRih4KFLEWKwAbnkSe9MKh9xHr8,13028
26
+ cocoindex/typing.py,sha256=dlpURZCGqZWkF0NfEyF5xc5RNGKN8crom9K36R5-6tY,13041
27
27
  cocoindex/utils.py,sha256=U3W39zD2uZpXX8v84tJD7sRmbC5ar3z_ljAP1cJrYXI,618
28
- cocoindex-0.1.63.dist-info/RECORD,,
28
+ cocoindex-0.1.65.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: cp313-cp313-win_amd64