cocoindex 0.1.54__cp311-cp311-macosx_11_0_arm64.whl → 0.1.55__cp311-cp311-macosx_11_0_arm64.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.
Binary file
cocoindex/cli.py CHANGED
@@ -2,11 +2,15 @@ import atexit
2
2
  import datetime
3
3
  import importlib.util
4
4
  import os
5
+ import signal
5
6
  import sys
7
+ import threading
6
8
  import types
9
+ from types import FrameType
7
10
  from typing import Any
8
11
 
9
12
  import click
13
+ import watchfiles
10
14
  from dotenv import find_dotenv, load_dotenv
11
15
  from rich.console import Console
12
16
  from rich.panel import Panel
@@ -116,6 +120,12 @@ def _load_user_app(app_target: str) -> types.ModuleType:
116
120
  )
117
121
 
118
122
 
123
+ def _initialize_cocoindex_in_process() -> None:
124
+ settings = setting.Settings.from_env()
125
+ lib.init(settings)
126
+ atexit.register(lib.stop)
127
+
128
+
119
129
  @click.group()
120
130
  @click.version_option(package_name="cocoindex", message="%(prog)s version %(version)s")
121
131
  @click.option(
@@ -128,7 +138,7 @@ def _load_user_app(app_target: str) -> types.ModuleType:
128
138
  default=None,
129
139
  show_default=False,
130
140
  )
131
- def cli(env_file: str | None) -> None:
141
+ def cli(env_file: str | None = None) -> None:
132
142
  """
133
143
  CLI for Cocoindex.
134
144
  """
@@ -139,9 +149,7 @@ def cli(env_file: str | None) -> None:
139
149
  click.echo(f"Loaded environment variables from: {loaded_env_path}", err=True)
140
150
 
141
151
  try:
142
- settings = setting.Settings.from_env()
143
- lib.init(settings)
144
- atexit.register(lib.stop)
152
+ _initialize_cocoindex_in_process()
145
153
  except Exception as e:
146
154
  raise click.ClickException(f"Failed to initialize CocoIndex library: {e}")
147
155
 
@@ -485,6 +493,14 @@ def evaluate(
485
493
  default=False,
486
494
  help="Avoid printing anything to the standard output, e.g. statistics.",
487
495
  )
496
+ @click.option(
497
+ "-r",
498
+ "--reload",
499
+ is_flag=True,
500
+ show_default=True,
501
+ default=False,
502
+ help="Enable auto-reload on code changes.",
503
+ )
488
504
  def server(
489
505
  app_target: str,
490
506
  address: str | None,
@@ -493,6 +509,7 @@ def server(
493
509
  cors_origin: str | None,
494
510
  cors_cocoindex: bool,
495
511
  cors_local: int | None,
512
+ reload: bool,
496
513
  ) -> None:
497
514
  """
498
515
  Start a HTTP server providing REST APIs.
@@ -502,6 +519,58 @@ def server(
502
519
  APP_TARGET: path/to/app.py or installed_module.
503
520
  """
504
521
  app_ref = _get_app_ref_from_specifier(app_target)
522
+ args = (
523
+ app_ref,
524
+ address,
525
+ cors_origin,
526
+ cors_cocoindex,
527
+ cors_local,
528
+ live_update,
529
+ quiet,
530
+ )
531
+
532
+ if reload:
533
+ watch_paths = {os.getcwd()}
534
+ if os.path.isfile(app_ref):
535
+ watch_paths.add(os.path.dirname(os.path.abspath(app_ref)))
536
+ else:
537
+ try:
538
+ spec = importlib.util.find_spec(app_ref)
539
+ if spec and spec.origin:
540
+ watch_paths.add(os.path.dirname(os.path.abspath(spec.origin)))
541
+ except ImportError:
542
+ pass
543
+
544
+ watchfiles.run_process(
545
+ *watch_paths,
546
+ target=_reloadable_server_target,
547
+ args=args,
548
+ watch_filter=watchfiles.PythonFilter(),
549
+ callback=lambda changes: click.secho(
550
+ f"\nDetected changes in {len(changes)} file(s), reloading server...\n",
551
+ fg="cyan",
552
+ ),
553
+ )
554
+ else:
555
+ _run_server(*args)
556
+
557
+
558
+ def _reloadable_server_target(*args: Any, **kwargs: Any) -> None:
559
+ """Reloadable target for the watchfiles process."""
560
+ _initialize_cocoindex_in_process()
561
+ _run_server(*args, **kwargs)
562
+
563
+
564
+ def _run_server(
565
+ app_ref: str,
566
+ address: str | None = None,
567
+ cors_origin: str | None = None,
568
+ cors_cocoindex: bool = False,
569
+ cors_local: int | None = None,
570
+ live_update: bool = False,
571
+ quiet: bool = False,
572
+ ) -> None:
573
+ """Helper function to run the server with specified settings."""
505
574
  _load_user_app(app_ref)
506
575
 
507
576
  server_settings = setting.ServerSettings.from_env()
@@ -525,7 +594,17 @@ def server(
525
594
  if live_update:
526
595
  options = flow.FlowLiveUpdaterOptions(live_mode=True, print_stats=not quiet)
527
596
  flow.update_all_flows(options)
528
- input("Press Enter to stop...")
597
+
598
+ click.secho("Press Ctrl+C to stop the server.", fg="yellow")
599
+
600
+ shutdown_event = threading.Event()
601
+
602
+ def handle_signal(signum: int, frame: FrameType | None) -> None:
603
+ shutdown_event.set()
604
+
605
+ signal.signal(signal.SIGINT, handle_signal)
606
+ signal.signal(signal.SIGTERM, handle_signal)
607
+ shutdown_event.wait()
529
608
 
530
609
 
531
610
  def _flow_name(name: str | None) -> str:
cocoindex/convert.py CHANGED
@@ -42,8 +42,6 @@ def encode_engine_value(value: Any) -> Any:
42
42
  return [
43
43
  [encode_engine_value(k)] + encode_engine_value(v) for k, v in value.items()
44
44
  ]
45
- if isinstance(value, uuid.UUID):
46
- return value.bytes
47
45
  return value
48
46
 
49
47
 
@@ -92,9 +90,6 @@ def make_engine_value_decoder(
92
90
  f"passed in {src_type_kind}, declared {dst_annotation} ({dst_type_info.kind})"
93
91
  )
94
92
 
95
- if src_type_kind == "Uuid":
96
- return lambda value: uuid.UUID(bytes=value)
97
-
98
93
  if dst_type_info is None:
99
94
  if src_type_kind == "Struct" or src_type_kind in TABLE_TYPES:
100
95
  raise ValueError(
@@ -122,7 +122,7 @@ def test_encode_engine_value_basic_types() -> None:
122
122
 
123
123
  def test_encode_engine_value_uuid() -> None:
124
124
  u = uuid.uuid4()
125
- assert encode_engine_value(u) == u.bytes
125
+ assert encode_engine_value(u) == u
126
126
 
127
127
 
128
128
  def test_encode_engine_value_date_time_types() -> None:
@@ -285,8 +285,8 @@ def test_non_ndarray_vector_decoding() -> None:
285
285
  decoder = make_engine_value_decoder(["field"], src_type, dst_type_uuid)
286
286
  uuid1 = uuid.uuid4()
287
287
  uuid2 = uuid.uuid4()
288
- input_bytes = [uuid1.bytes, uuid2.bytes]
289
- result = decoder(input_bytes)
288
+ input_uuids = [uuid1, uuid2]
289
+ result = decoder(input_uuids)
290
290
  assert isinstance(result, list)
291
291
  assert all(isinstance(x, uuid.UUID) for x in result)
292
292
  assert result == [uuid1, uuid2]
@@ -579,7 +579,7 @@ def test_roundtrip_union_simple() -> None:
579
579
 
580
580
  def test_roundtrip_union_with_active_uuid() -> None:
581
581
  t = str | uuid.UUID | int
582
- value = uuid.uuid4().bytes
582
+ value = uuid.uuid4()
583
583
  validate_full_roundtrip(value, t)
584
584
 
585
585
 
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cocoindex
3
- Version: 0.1.54
3
+ Version: 0.1.55
4
4
  Requires-Dist: sentence-transformers>=3.3.1
5
5
  Requires-Dist: click>=8.1.8
6
6
  Requires-Dist: rich>=14.0.0
7
7
  Requires-Dist: python-dotenv>=1.1.0
8
+ Requires-Dist: watchfiles>=1.1.0
8
9
  Requires-Dist: pytest ; extra == 'test'
9
10
  Requires-Dist: ruff ; extra == 'dev'
10
11
  Requires-Dist: pre-commit ; extra == 'dev'
@@ -1,12 +1,12 @@
1
- cocoindex-0.1.54.dist-info/METADATA,sha256=YhrfcjAPuh3OkyFCVB_tkaT_dY9NV7HMhOHIQVBqnCk,9907
2
- cocoindex-0.1.54.dist-info/WHEEL,sha256=8hL2oHqulIPF_TJ_OfB-8kD2X9O6HJL0emTmeguFbqc,104
3
- cocoindex-0.1.54.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
- cocoindex-0.1.54.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1
+ cocoindex-0.1.55.dist-info/METADATA,sha256=fBybxUgGTU6YgheU84q4bZUx0Y4Vz_N7Nt2Puo-os_k,9940
2
+ cocoindex-0.1.55.dist-info/WHEEL,sha256=uknsTnQ4D3qZvtLjoBwOrQ-H3LYkwihRUx6jxoJPLSU,104
3
+ cocoindex-0.1.55.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
4
+ cocoindex-0.1.55.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
5
5
  cocoindex/__init__.py,sha256=3potlGouaGAznMTEqU5QKuB934qpD1xR6ZH6EL3YMWw,1782
6
- cocoindex/_engine.cpython-311-darwin.so,sha256=DCV77kRyWJLfkrvc59a8nwMQUqSwwp_e6DdyUiJHy7c,57472480
6
+ cocoindex/_engine.cpython-311-darwin.so,sha256=Azzx_tOFZQa28dl3jxT9lLclvWapymtN4CAEEASXyR8,57618192
7
7
  cocoindex/auth_registry.py,sha256=1XqO7ibjmBBd8i11XSJTvTgdz8p1ptW-ZpuSgo_5zzk,716
8
- cocoindex/cli.py,sha256=yXlUZqJuB9baofnpHFOu3S-0x0xGglmJ88nd9_T-fEs,18223
9
- cocoindex/convert.py,sha256=4-a0uWLOfQ_e2OOwHjIYAsBMZIDRnGbK01Ye1E2ybIQ,10377
8
+ cocoindex/cli.py,sha256=6SiViK_aSfIaYWvzLm-TFOlH-GVEaLALNnxnSatfo3k,20341
9
+ cocoindex/convert.py,sha256=XeSr0ykudBrB-RWRmcbdbt3WCihlLDSBIYUcDtPbTdA,10228
10
10
  cocoindex/flow.py,sha256=djpGsQlSZV10OCS_81GY9k8q_0l-6MeismLnoF9XteE,30023
11
11
  cocoindex/functions.py,sha256=Lh1aSovd6HaikAWvDi6dX0poyma1MqBX5S9FAzIR8c4,2622
12
12
  cocoindex/index.py,sha256=j93B9jEvvLXHtpzKWL88SY6wCGEoPgpsQhEGHlyYGFg,540
@@ -20,9 +20,9 @@ cocoindex/setup.py,sha256=u5dYZFKfz4yZLiGHD0guNaR0s4zY9JAoZWrWHpAHw_0,773
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=RxbCmW3cSZQVJtAWZBBH9YNAViWVSi7u0JO8JGJl7M8,36174
23
+ cocoindex/tests/test_convert.py,sha256=1IoJzfPtM5zoy0YKhTsZTX-fF4xA3w_4usyS4UN44vE,36150
24
24
  cocoindex/tests/test_optional_database.py,sha256=snAmkNa6wtOSaxoZE1HgjvL5v_ylitt3Jt_9df4Cgdc,8506
25
25
  cocoindex/tests/test_typing.py,sha256=t6UCYShcfonTfjBlGRWPiFGMZ8DGFfABXo6idekPoJE,14757
26
26
  cocoindex/typing.py,sha256=kPMFVKs2i4SCLzW1Tn5NP_Ev9DAc-2qW6eJ68gpLexU,12580
27
27
  cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
28
- cocoindex-0.1.54.dist-info/RECORD,,
28
+ cocoindex-0.1.55.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: maturin (1.8.7)
2
+ Generator: maturin (1.9.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp311-cp311-macosx_11_0_arm64