cocoindex 0.1.69__pp311-pypy311_pp73-manylinux_2_28_aarch64.whl → 0.1.71__pp311-pypy311_pp73-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/__init__.py CHANGED
@@ -6,7 +6,7 @@ from . import functions, sources, targets, cli, utils
6
6
 
7
7
  from . import targets as storages # Deprecated: Use targets instead
8
8
 
9
- from .auth_registry import AuthEntryReference, add_auth_entry, ref_auth_entry
9
+ from .auth_registry import AuthEntryReference, add_auth_entry, add_transient_auth_entry
10
10
  from .flow import FlowBuilder, DataScope, DataSlice, Flow, transform_flow
11
11
  from .flow import flow_def
12
12
  from .flow import EvaluateAndDumpOptions, GeneratedField
@@ -38,10 +38,12 @@ __all__ = [
38
38
  "targets",
39
39
  "storages",
40
40
  "cli",
41
+ "op",
41
42
  "utils",
42
43
  # Auth registry
43
44
  "AuthEntryReference",
44
45
  "add_auth_entry",
46
+ "add_transient_auth_entry",
45
47
  "ref_auth_entry",
46
48
  # Flow
47
49
  "FlowBuilder",
@@ -4,20 +4,42 @@ Auth registry is used to register and reference auth entries.
4
4
 
5
5
  from dataclasses import dataclass
6
6
  from typing import Generic, TypeVar
7
+ import threading
7
8
 
8
9
  from . import _engine # type: ignore
9
10
  from .convert import dump_engine_object
10
11
 
11
12
  T = TypeVar("T")
12
13
 
14
+ # Global atomic counter for generating unique auth entry keys
15
+ _counter_lock = threading.Lock()
16
+ _auth_key_counter = 0
17
+
18
+
19
+ def _generate_auth_key() -> str:
20
+ """Generate a unique auth entry key using a global atomic counter."""
21
+ global _auth_key_counter # pylint: disable=global-statement
22
+ with _counter_lock:
23
+ _auth_key_counter += 1
24
+ return f"__auth_{_auth_key_counter}"
25
+
13
26
 
14
27
  @dataclass
15
- class AuthEntryReference(Generic[T]):
16
- """Reference an auth entry by its key."""
28
+ class TransientAuthEntryReference(Generic[T]):
29
+ """Reference an auth entry, may or may not have a stable key."""
17
30
 
18
31
  key: str
19
32
 
20
33
 
34
+ class AuthEntryReference(TransientAuthEntryReference[T]):
35
+ """Reference an auth entry, with a key stable across ."""
36
+
37
+
38
+ def add_transient_auth_entry(value: T) -> TransientAuthEntryReference[T]:
39
+ """Add an auth entry to the registry. Returns its reference."""
40
+ return add_auth_entry(_generate_auth_key(), value)
41
+
42
+
21
43
  def add_auth_entry(key: str, value: T) -> AuthEntryReference[T]:
22
44
  """Add an auth entry to the registry. Returns its reference."""
23
45
  _engine.add_auth_entry(key, dump_engine_object(value))
cocoindex/convert.py CHANGED
@@ -92,10 +92,14 @@ def make_engine_value_decoder(
92
92
  if src_type_kind == "Struct":
93
93
  return _make_engine_struct_to_dict_decoder(field_path, src_type["fields"])
94
94
  if src_type_kind in TABLE_TYPES:
95
- raise ValueError(
96
- f"Missing type annotation for `{''.join(field_path)}`."
97
- f"It's required for {src_type_kind} type."
98
- )
95
+ if src_type_kind == "LTable":
96
+ return _make_engine_ltable_to_list_dict_decoder(
97
+ field_path, src_type["row"]["fields"]
98
+ )
99
+ elif src_type_kind == "KTable":
100
+ return _make_engine_ktable_to_dict_dict_decoder(
101
+ field_path, src_type["row"]["fields"]
102
+ )
99
103
  return lambda value: value
100
104
 
101
105
  # Handle struct -> dict binding for explicit dict annotations
@@ -340,6 +344,77 @@ def _make_engine_struct_to_dict_decoder(
340
344
  return decode_to_dict
341
345
 
342
346
 
347
+ def _make_engine_ltable_to_list_dict_decoder(
348
+ field_path: list[str],
349
+ src_fields: list[dict[str, Any]],
350
+ ) -> Callable[[list[Any] | None], list[dict[str, Any]] | None]:
351
+ """Make a decoder from engine LTable values to a list of dicts."""
352
+
353
+ # Create a decoder for each row (struct) to dict
354
+ row_decoder = _make_engine_struct_to_dict_decoder(field_path, src_fields)
355
+
356
+ def decode_to_list_dict(values: list[Any] | None) -> list[dict[str, Any]] | None:
357
+ if values is None:
358
+ return None
359
+ result = []
360
+ for i, row_values in enumerate(values):
361
+ decoded_row = row_decoder(row_values)
362
+ if decoded_row is None:
363
+ raise ValueError(
364
+ f"LTable row at index {i} decoded to None, which is not allowed."
365
+ )
366
+ result.append(decoded_row)
367
+ return result
368
+
369
+ return decode_to_list_dict
370
+
371
+
372
+ def _make_engine_ktable_to_dict_dict_decoder(
373
+ field_path: list[str],
374
+ src_fields: list[dict[str, Any]],
375
+ ) -> Callable[[list[Any] | None], dict[Any, dict[str, Any]] | None]:
376
+ """Make a decoder from engine KTable values to a dict of dicts."""
377
+
378
+ if not src_fields:
379
+ raise ValueError("KTable must have at least one field for the key")
380
+
381
+ # First field is the key, remaining fields are the value
382
+ key_field_schema = src_fields[0]
383
+ value_fields_schema = src_fields[1:]
384
+
385
+ # Create decoders
386
+ field_path.append(f".{key_field_schema.get('name', KEY_FIELD_NAME)}")
387
+ key_decoder = make_engine_value_decoder(field_path, key_field_schema["type"], Any)
388
+ field_path.pop()
389
+
390
+ value_decoder = _make_engine_struct_to_dict_decoder(field_path, value_fields_schema)
391
+
392
+ def decode_to_dict_dict(
393
+ values: list[Any] | None,
394
+ ) -> dict[Any, dict[str, Any]] | None:
395
+ if values is None:
396
+ return None
397
+ result = {}
398
+ for row_values in values:
399
+ if not row_values:
400
+ raise ValueError("KTable row must have at least 1 value (the key)")
401
+ key = key_decoder(row_values[0])
402
+ if len(row_values) == 1:
403
+ value: dict[str, Any] = {}
404
+ else:
405
+ tmp = value_decoder(row_values[1:])
406
+ if tmp is None:
407
+ value = {}
408
+ else:
409
+ value = tmp
410
+ if isinstance(key, dict):
411
+ key = tuple(key.values())
412
+ result[key] = value
413
+ return result
414
+
415
+ return decode_to_dict_dict
416
+
417
+
343
418
  def dump_engine_object(v: Any) -> Any:
344
419
  """Recursively dump an object for engine. Engine side uses `Pythonized` to catch."""
345
420
  if v is None:
cocoindex/functions.py CHANGED
@@ -66,14 +66,19 @@ class SentenceTransformerEmbed(op.FunctionSpec):
66
66
  args: dict[str, Any] | None = None
67
67
 
68
68
 
69
- @op.executor_class(gpu=True, cache=True, behavior_version=1)
69
+ @op.executor_class(
70
+ gpu=True,
71
+ cache=True,
72
+ behavior_version=1,
73
+ arg_relationship=(op.ArgRelationship.EMBEDDING_ORIGIN_TEXT, "text"),
74
+ )
70
75
  class SentenceTransformerEmbedExecutor:
71
76
  """Executor for SentenceTransformerEmbed."""
72
77
 
73
78
  spec: SentenceTransformerEmbed
74
79
  _model: Any | None = None
75
80
 
76
- def analyze(self, text: Any) -> type:
81
+ def analyze(self, _text: Any) -> type:
77
82
  try:
78
83
  # Only import sentence_transformers locally when it's needed, as its import is very slow.
79
84
  import sentence_transformers # pylint: disable=import-outside-toplevel
@@ -88,11 +93,7 @@ class SentenceTransformerEmbedExecutor:
88
93
  args = self.spec.args or {}
89
94
  self._model = sentence_transformers.SentenceTransformer(self.spec.model, **args)
90
95
  dim = self._model.get_sentence_embedding_dimension()
91
- result: type = Annotated[
92
- Vector[np.float32, Literal[dim]], # type: ignore
93
- TypeAttr("cocoindex.io/vector_origin_text", text.analyzed_value),
94
- ]
95
- return result
96
+ return Vector[np.float32, Literal[dim]] # type: ignore
96
97
 
97
98
  def __call__(self, text: str) -> NDArray[np.float32]:
98
99
  assert self._model is not None
cocoindex/op.py CHANGED
@@ -6,11 +6,11 @@ import asyncio
6
6
  import dataclasses
7
7
  import inspect
8
8
  from enum import Enum
9
- from typing import Any, Awaitable, Callable, Protocol, dataclass_transform
9
+ from typing import Any, Awaitable, Callable, Protocol, dataclass_transform, Annotated
10
10
 
11
11
  from . import _engine # type: ignore
12
12
  from .convert import encode_engine_value, make_engine_value_decoder
13
- from .typing import encode_enriched_type, resolve_forward_ref
13
+ from .typing import TypeAttr, encode_enriched_type, resolve_forward_ref
14
14
 
15
15
 
16
16
  class OpCategory(Enum):
@@ -85,6 +85,17 @@ class _FunctionExecutorFactory:
85
85
  _gpu_dispatch_lock = asyncio.Lock()
86
86
 
87
87
 
88
+ _COCOINDEX_ATTR_PREFIX = "cocoindex.io/"
89
+
90
+
91
+ class ArgRelationship(Enum):
92
+ """Specifies the relationship between an input argument and the output."""
93
+
94
+ EMBEDDING_ORIGIN_TEXT = _COCOINDEX_ATTR_PREFIX + "embedding_origin_text"
95
+ CHUNKS_BASE_TEXT = _COCOINDEX_ATTR_PREFIX + "chunk_base_text"
96
+ RECTS_BASE_IMAGE = _COCOINDEX_ATTR_PREFIX + "rects_base_image"
97
+
98
+
88
99
  @dataclasses.dataclass
89
100
  class OpArgs:
90
101
  """
@@ -92,11 +103,15 @@ class OpArgs:
92
103
  - cache: Whether the executor will be cached.
93
104
  - behavior_version: The behavior version of the executor. Cache will be invalidated if it
94
105
  changes. Must be provided if `cache` is True.
106
+ - arg_relationship: It specifies the relationship between an input argument and the output,
107
+ e.g. `(ArgRelationship.CHUNKS_BASE_TEXT, "content")` means the output is chunks for the
108
+ input argument with name `content`.
95
109
  """
96
110
 
97
111
  gpu: bool = False
98
112
  cache: bool = False
99
113
  behavior_version: int | None = None
114
+ arg_relationship: tuple[ArgRelationship, str] | None = None
100
115
 
101
116
 
102
117
  def _to_async_call(call: Callable[..., Any]) -> Callable[..., Awaitable[Any]]:
@@ -143,6 +158,15 @@ def _register_op_factory(
143
158
  """
144
159
  self._args_decoders = []
145
160
  self._kwargs_decoders = {}
161
+ attributes = []
162
+
163
+ def process_attribute(arg_name: str, arg: _engine.OpArgSchema) -> None:
164
+ if op_args.arg_relationship is not None:
165
+ related_attr, related_arg_name = op_args.arg_relationship
166
+ if related_arg_name == arg_name:
167
+ attributes.append(
168
+ TypeAttr(related_attr.value, arg.analyzed_value)
169
+ )
146
170
 
147
171
  # Match arguments with parameters.
148
172
  next_param_idx = 0
@@ -164,6 +188,7 @@ def _register_op_factory(
164
188
  [arg_name], arg.value_type["type"], arg_param.annotation
165
189
  )
166
190
  )
191
+ process_attribute(arg_name, arg)
167
192
  if arg_param.kind != inspect.Parameter.VAR_POSITIONAL:
168
193
  next_param_idx += 1
169
194
 
@@ -194,6 +219,7 @@ def _register_op_factory(
194
219
  self._kwargs_decoders[kwarg_name] = make_engine_value_decoder(
195
220
  [kwarg_name], kwarg.value_type["type"], arg_param.annotation
196
221
  )
222
+ process_attribute(kwarg_name, kwarg)
197
223
 
198
224
  missing_args = [
199
225
  name
@@ -216,9 +242,12 @@ def _register_op_factory(
216
242
 
217
243
  prepare_method = getattr(executor_cls, "analyze", None)
218
244
  if prepare_method is not None:
219
- return prepare_method(self, *args, **kwargs)
245
+ result = prepare_method(self, *args, **kwargs)
220
246
  else:
221
- return expected_return
247
+ result = expected_return
248
+ if len(attributes) > 0:
249
+ result = Annotated[result, *attributes]
250
+ return result
222
251
 
223
252
  async def prepare(self) -> None:
224
253
  """
cocoindex/sources.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """All builtin sources."""
2
2
 
3
3
  from . import op
4
+ from .auth_registry import TransientAuthEntryReference
4
5
  import datetime
5
6
 
6
7
 
@@ -48,6 +49,11 @@ class AmazonS3(op.SourceSpec):
48
49
  class AzureBlob(op.SourceSpec):
49
50
  """
50
51
  Import data from an Azure Blob Storage container. Supports optional prefix and file filtering by glob patterns.
52
+
53
+ Authentication mechanisms taken in the following order:
54
+ - SAS token (if provided)
55
+ - Account access key (if provided)
56
+ - Default Azure credential
51
57
  """
52
58
 
53
59
  _op_category = op.OpCategory.SOURCE
@@ -58,3 +64,6 @@ class AzureBlob(op.SourceSpec):
58
64
  binary: bool = False
59
65
  included_patterns: list[str] | None = None
60
66
  excluded_patterns: list[str] | None = None
67
+
68
+ sas_token: TransientAuthEntryReference[str] | None = None
69
+ account_access_key: TransientAuthEntryReference[str] | None = None
@@ -1341,3 +1341,130 @@ def test_roundtrip_namedtuple_to_dict_binding() -> None:
1341
1341
  validate_full_roundtrip(
1342
1342
  instance, Point, (expected_dict, dict), (expected_dict, Any)
1343
1343
  )
1344
+
1345
+
1346
+ def test_roundtrip_ltable_to_list_dict_binding() -> None:
1347
+ """Test LTable -> list[dict] binding with Any annotation."""
1348
+
1349
+ @dataclass
1350
+ class User:
1351
+ id: str
1352
+ name: str
1353
+ age: int
1354
+
1355
+ users = [User("u1", "Alice", 25), User("u2", "Bob", 30), User("u3", "Charlie", 35)]
1356
+ expected_list_dict = [
1357
+ {"id": "u1", "name": "Alice", "age": 25},
1358
+ {"id": "u2", "name": "Bob", "age": 30},
1359
+ {"id": "u3", "name": "Charlie", "age": 35},
1360
+ ]
1361
+
1362
+ # Test Any annotation
1363
+ validate_full_roundtrip(users, list[User], (expected_list_dict, Any))
1364
+
1365
+
1366
+ def test_roundtrip_ktable_to_dict_dict_binding() -> None:
1367
+ """Test KTable -> dict[K, dict] binding with Any annotation."""
1368
+
1369
+ @dataclass
1370
+ class Product:
1371
+ name: str
1372
+ price: float
1373
+ active: bool
1374
+
1375
+ products = {
1376
+ "p1": Product("Widget", 29.99, True),
1377
+ "p2": Product("Gadget", 49.99, False),
1378
+ "p3": Product("Tool", 19.99, True),
1379
+ }
1380
+ expected_dict_dict = {
1381
+ "p1": {"name": "Widget", "price": 29.99, "active": True},
1382
+ "p2": {"name": "Gadget", "price": 49.99, "active": False},
1383
+ "p3": {"name": "Tool", "price": 19.99, "active": True},
1384
+ }
1385
+
1386
+ # Test Any annotation
1387
+ validate_full_roundtrip(products, dict[str, Product], (expected_dict_dict, Any))
1388
+
1389
+
1390
+ def test_roundtrip_ktable_with_complex_key() -> None:
1391
+ """Test KTable with complex key types -> dict binding."""
1392
+
1393
+ @dataclass(frozen=True)
1394
+ class OrderKey:
1395
+ shop_id: str
1396
+ version: int
1397
+
1398
+ @dataclass
1399
+ class Order:
1400
+ customer: str
1401
+ total: float
1402
+
1403
+ orders = {
1404
+ OrderKey("shop1", 1): Order("Alice", 100.0),
1405
+ OrderKey("shop2", 2): Order("Bob", 200.0),
1406
+ }
1407
+ expected_dict_dict = {
1408
+ ("shop1", 1): {"customer": "Alice", "total": 100.0},
1409
+ ("shop2", 2): {"customer": "Bob", "total": 200.0},
1410
+ }
1411
+
1412
+ # Test Any annotation
1413
+ validate_full_roundtrip(orders, dict[OrderKey, Order], (expected_dict_dict, Any))
1414
+
1415
+
1416
+ def test_roundtrip_ltable_with_nested_structs() -> None:
1417
+ """Test LTable with nested structs -> list[dict] binding."""
1418
+
1419
+ @dataclass
1420
+ class Address:
1421
+ street: str
1422
+ city: str
1423
+
1424
+ @dataclass
1425
+ class Person:
1426
+ name: str
1427
+ age: int
1428
+ address: Address
1429
+
1430
+ people = [
1431
+ Person("John", 30, Address("123 Main St", "Anytown")),
1432
+ Person("Jane", 25, Address("456 Oak Ave", "Somewhere")),
1433
+ ]
1434
+ expected_list_dict = [
1435
+ {
1436
+ "name": "John",
1437
+ "age": 30,
1438
+ "address": {"street": "123 Main St", "city": "Anytown"},
1439
+ },
1440
+ {
1441
+ "name": "Jane",
1442
+ "age": 25,
1443
+ "address": {"street": "456 Oak Ave", "city": "Somewhere"},
1444
+ },
1445
+ ]
1446
+
1447
+ # Test Any annotation
1448
+ validate_full_roundtrip(people, list[Person], (expected_list_dict, Any))
1449
+
1450
+
1451
+ def test_roundtrip_ktable_with_list_fields() -> None:
1452
+ """Test KTable with list fields -> dict binding."""
1453
+
1454
+ @dataclass
1455
+ class Team:
1456
+ name: str
1457
+ members: list[str]
1458
+ active: bool
1459
+
1460
+ teams = {
1461
+ "team1": Team("Dev Team", ["Alice", "Bob"], True),
1462
+ "team2": Team("QA Team", ["Charlie", "David"], False),
1463
+ }
1464
+ expected_dict_dict = {
1465
+ "team1": {"name": "Dev Team", "members": ["Alice", "Bob"], "active": True},
1466
+ "team2": {"name": "QA Team", "members": ["Charlie", "David"], "active": False},
1467
+ }
1468
+
1469
+ # Test Any annotation
1470
+ validate_full_roundtrip(teams, dict[str, Team], (expected_dict_dict, Any))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cocoindex
3
- Version: 0.1.69
3
+ Version: 0.1.71
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
@@ -52,18 +52,18 @@ Ultra performant data transformation framework for AI, with core engine written
52
52
  ⭐ Drop a star to help us grow!
53
53
 
54
54
  <div align="center">
55
-
55
+
56
56
  <!-- Keep these links. Translations will automatically update with the README. -->
57
- [Deutsch](https://readme-i18n.com/cocoindex-io/cocoindex?lang=de) |
58
- [English](https://readme-i18n.com/cocoindex-io/cocoindex?lang=en) |
59
- [Español](https://readme-i18n.com/cocoindex-io/cocoindex?lang=es) |
60
- [français](https://readme-i18n.com/cocoindex-io/cocoindex?lang=fr) |
61
- [日本語](https://readme-i18n.com/cocoindex-io/cocoindex?lang=ja) |
62
- [한국어](https://readme-i18n.com/cocoindex-io/cocoindex?lang=ko) |
63
- [Português](https://readme-i18n.com/cocoindex-io/cocoindex?lang=pt) |
64
- [Русский](https://readme-i18n.com/cocoindex-io/cocoindex?lang=ru) |
57
+ [Deutsch](https://readme-i18n.com/cocoindex-io/cocoindex?lang=de) |
58
+ [English](https://readme-i18n.com/cocoindex-io/cocoindex?lang=en) |
59
+ [Español](https://readme-i18n.com/cocoindex-io/cocoindex?lang=es) |
60
+ [français](https://readme-i18n.com/cocoindex-io/cocoindex?lang=fr) |
61
+ [日本語](https://readme-i18n.com/cocoindex-io/cocoindex?lang=ja) |
62
+ [한국어](https://readme-i18n.com/cocoindex-io/cocoindex?lang=ko) |
63
+ [Português](https://readme-i18n.com/cocoindex-io/cocoindex?lang=pt) |
64
+ [Русский](https://readme-i18n.com/cocoindex-io/cocoindex?lang=ru) |
65
65
  [中文](https://readme-i18n.com/cocoindex-io/cocoindex?lang=zh)
66
-
66
+
67
67
  </div>
68
68
 
69
69
  </br>
@@ -208,6 +208,7 @@ It defines an index flow like this:
208
208
  | [FastAPI Server with Docker](examples/fastapi_server_docker) | Run the semantic search server in a Dockerized FastAPI setup |
209
209
  | [Product Recommendation](examples/product_recommendation) | Build real-time product recommendations with LLM and graph database|
210
210
  | [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|
211
+ | [Face Recognition](examples/face_recognition) | Recognize faces in images and build embedding index |
211
212
  | [Paper Metadata](examples/paper_metadata) | Index papers in PDF files, and build metadata tables for each paper |
212
213
 
213
214
  More coming and stay tuned 👀!
@@ -1,28 +1,28 @@
1
- cocoindex-0.1.69.dist-info/METADATA,sha256=zrovdJq1T7tqAOwvXq0lf8AaVJ5_mU3YpsIAZ-fxDYY,11216
2
- cocoindex-0.1.69.dist-info/WHEEL,sha256=7zxhuuBJUuil6R_MfVJvTZXJmNSPMntESIcLB40BBxA,116
3
- cocoindex-0.1.69.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
- cocoindex-0.1.69.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
5
- cocoindex/__init__.py,sha256=AChibZmC8DYGLKesIYjqF5ZxR-SECwFXJ7usTDBl5Lk,2062
6
- cocoindex/_engine.pypy311-pp73-aarch64-linux-gnu.so,sha256=KdD-X3Pv3Rmhf3EW14bIhqcv8PFdDi5R0qFQ50p8Xw0,68447136
7
- cocoindex/auth_registry.py,sha256=1XqO7ibjmBBd8i11XSJTvTgdz8p1ptW-ZpuSgo_5zzk,716
1
+ cocoindex-0.1.71.dist-info/METADATA,sha256=RSKXAZDg4Ysyqr36-BCRZlxvTdXmHvsQseQnNJaSxX8,11304
2
+ cocoindex-0.1.71.dist-info/WHEEL,sha256=7zxhuuBJUuil6R_MfVJvTZXJmNSPMntESIcLB40BBxA,116
3
+ cocoindex-0.1.71.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
+ cocoindex-0.1.71.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
5
+ cocoindex/__init__.py,sha256=kfTgbh2haepo7kIbzJqfxU6Kx7wPol5_t1SYF2x6cBM,2114
6
+ cocoindex/_engine.pypy311-pp73-aarch64-linux-gnu.so,sha256=_FRWgxMNueMMGeEKYIZ-bm6cpHZbfNzq3WyZg6555zs,68466536
7
+ cocoindex/auth_registry.py,sha256=PE1-kVkcyC1G2C_V7b1kvYzeq73OFQehWKQP7ln7fJ8,1478
8
8
  cocoindex/cli.py,sha256=-gp639JSyQN6YjnhGqCakIzYoSSqXxQMbxbkcYGP0QY,22359
9
- cocoindex/convert.py,sha256=RYfRUungabr-dHakG4k2kDvYambxHFljAmTuPQeQths,13117
9
+ cocoindex/convert.py,sha256=fOzfbMlQ8WQ_nAv8WpX-EEHdZdBV8QXV3qIe1_Ird_U,15806
10
10
  cocoindex/flow.py,sha256=XS63KkRr8JV8Mxg3KzW2Y7Y-GyUlaFTdRrw_sc7l0H4,36046
11
- cocoindex/functions.py,sha256=Ih1rtaTvZzQ2wucCOSpzSUu2-eu0mgtBVi1mh9M-Buw,3162
11
+ cocoindex/functions.py,sha256=LLu_ausirvqnsx_k3euZpv8sLCpBZ4DF77h2HOzbinE,3109
12
12
  cocoindex/index.py,sha256=j93B9jEvvLXHtpzKWL88SY6wCGEoPgpsQhEGHlyYGFg,540
13
13
  cocoindex/lib.py,sha256=f--9dAYd84CZosbDZqNW0oGbBLsY3dXiUTR1VrfQ_QY,817
14
14
  cocoindex/llm.py,sha256=WxmWUbNcf9HOCM5xkbDeFs9lF67M3mr810B7deDDc-8,673
15
- cocoindex/op.py,sha256=r_Usx7Jqh49Cck3tsYLx2vLRNUZArkQP_g7bIID6LPU,11809
15
+ cocoindex/op.py,sha256=Afi5CfgU3wPQoPPKFb2WUYCVLmCPhBuK-2NT1AzC2zU,13161
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=ADuv7RaWd9k-m3V0Cfy2jmaCt6DupJCviWdOm0CTiVw,4734
19
19
  cocoindex/setup.py,sha256=7uIHKN4FOCuoidPXcKyGTrkqpkl9luL49-6UcnMxYzw,3068
20
- cocoindex/sources.py,sha256=8MR_oyr7t0m-gUFq7FO6HHM-tDLmQSBAjheFXJzRd8g,1733
20
+ cocoindex/sources.py,sha256=69COA4qbZDipzGYfXv-WJSmicFkA509xIShRGDh6A0A,2083
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=48-fnWKv02gmFETV3b-8IC89SKMUZfJLEH-ucRtXGuI,45450
23
+ cocoindex/tests/test_convert.py,sha256=CnPDAK8QdzWTS9II-prbwIHeiq5htvRFhkfR8YdUE10,48960
24
24
  cocoindex/tests/test_optional_database.py,sha256=snAmkNa6wtOSaxoZE1HgjvL5v_ylitt3Jt_9df4Cgdc,8506
25
25
  cocoindex/tests/test_typing.py,sha256=NB4nUzoumOF_wGFa4D2Xf6d0bUVtOiSXyb78M1pYSG4,14827
26
26
  cocoindex/typing.py,sha256=MO9HkrNpargvMPvpkd7jgSu2R-21KE_NaB9-WI4YOZA,13241
27
27
  cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
28
- cocoindex-0.1.69.dist-info/RECORD,,
28
+ cocoindex-0.1.71.dist-info/RECORD,,