Skip to content

Commit 3c45acc

Browse files
feat: change capture mechanism
1 parent 4c6bb6e commit 3c45acc

File tree

5 files changed

+401
-351
lines changed

5 files changed

+401
-351
lines changed

check_implementation.sh

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/bin/bash
2+
# Script to check if the CLI feature is implemented
3+
4+
echo "Checking CLI feature implementation..."
5+
echo "======================================"
6+
7+
echo ""
8+
echo "1. Checking Rust core changes..."
9+
if grep -q "source_interval_enabled" src/execution/live_updater.rs; then
10+
echo " ✓ source_interval_enabled field found"
11+
else
12+
echo " ✗ source_interval_enabled field NOT found"
13+
fi
14+
15+
if grep -q "source_change_capture_enabled" src/execution/live_updater.rs; then
16+
echo " ✓ source_change_capture_enabled field found"
17+
else
18+
echo " ✗ source_change_capture_enabled field NOT found"
19+
fi
20+
21+
if grep -q "print_cli_status" src/execution/live_updater.rs; then
22+
echo " ✓ print_cli_status method found"
23+
else
24+
echo " ✗ print_cli_status method NOT found"
25+
fi
26+
27+
echo ""
28+
echo "2. Checking Python CLI changes..."
29+
if grep -q "--live-status" python/cocoindex/cli.py; then
30+
echo " ✓ --live-status option found"
31+
else
32+
echo " ✗ --live-status option NOT found"
33+
fi
34+
35+
if grep -q "print_cli_status" python/cocoindex/flow.py; then
36+
echo " ✓ print_cli_status method found in flow.py"
37+
else
38+
echo " ✗ print_cli_status method NOT found in flow.py"
39+
fi
40+
41+
echo ""
42+
echo "3. Checking Rust bindings..."
43+
if grep -q "print_cli_status_async" src/py/mod.rs; then
44+
echo " ✓ print_cli_status_async binding found"
45+
else
46+
echo " ✗ print_cli_status_async binding NOT found"
47+
fi
48+
49+
echo ""
50+
echo "4. Testing compilation..."
51+
if cargo check --quiet 2>/dev/null; then
52+
echo " ✓ Rust code compiles successfully"
53+
else
54+
echo " ✗ Rust code has compilation errors"
55+
fi
56+
57+
echo ""
58+
echo "======================================"
59+
echo "Implementation check complete!"

python/cocoindex/cli.py

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ def ls(app_target: str | None) -> None:
136136
"""
137137
List all flows.
138138
139-
If `APP_TARGET` (`path/to/app.py` or a module) is provided, lists flows defined in the app and their backend setup status.
139+
If APP_TARGET (path/to/app.py or a module) is provided, lists flows defined in the app and their backend setup status.
140140
141-
If `APP_TARGET` is omitted, lists all flows that have a persisted setup in the backend.
141+
If APP_TARGET is omitted, lists all flows that have a persisted setup in the backend.
142142
"""
143143
persisted_flow_names = flow_names_with_setup()
144144
if app_target:
@@ -182,19 +182,20 @@ def ls(app_target: str | None) -> None:
182182
"--color/--no-color", default=True, help="Enable or disable colored output."
183183
)
184184
@click.option("--verbose", is_flag=True, help="Show verbose output with full details.")
185-
def show(app_flow_specifier: str, color: bool, verbose: bool) -> None:
185+
@click.option("--live-status", is_flag=True, help="Show live update status for each data source.")
186+
def show(app_flow_specifier: str, color: bool, verbose: bool, live_status: bool) -> None:
186187
"""
187188
Show the flow spec and schema.
188189
189-
`APP_FLOW_SPECIFIER`: Specifies the application and optionally the target flow. Can be one of the following formats:
190+
APP_FLOW_SPECIFIER: Specifies the application and optionally the target flow. Can be one of the following formats:
190191
191192
\b
192-
- `path/to/your_app.py`
193-
- `an_installed.module_name`
194-
- `path/to/your_app.py:SpecificFlowName`
195-
- `an_installed.module_name:SpecificFlowName`
193+
- path/to/your_app.py
194+
- an_installed.module_name
195+
- path/to/your_app.py:SpecificFlowName
196+
- an_installed.module_name:SpecificFlowName
196197
197-
`:SpecificFlowName` can be omitted only if the application defines a single flow.
198+
:SpecificFlowName can be omitted only if the application defines a single flow.
198199
"""
199200
app_ref, flow_ref = _parse_app_flow_specifier(app_flow_specifier)
200201
_load_user_app(app_ref)
@@ -203,6 +204,15 @@ def show(app_flow_specifier: str, color: bool, verbose: bool) -> None:
203204
console = Console(no_color=not color)
204205
console.print(fl._render_spec(verbose=verbose))
205206
console.print()
207+
208+
if live_status:
209+
# Show live update status
210+
console.print("\n[bold cyan]Live Update Status:[/bold cyan]")
211+
options = flow.FlowLiveUpdaterOptions(live_mode=False, reexport_targets=False, print_stats=False)
212+
with flow.FlowLiveUpdater(fl, options) as updater:
213+
updater.print_cli_status()
214+
console.print()
215+
206216
table = Table(
207217
title=f"Schema for Flow: {fl.name}",
208218
title_style="cyan",
@@ -251,23 +261,6 @@ def _drop_flows(flows: Iterable[flow.Flow], app_ref: str, force: bool = False) -
251261
setup_bundle.apply(report_to_stdout=True)
252262

253263

254-
def _deprecate_setup_flag(
255-
ctx: click.Context, param: click.Parameter, value: bool
256-
) -> bool:
257-
"""Callback to warn users that --setup flag is deprecated."""
258-
# Check if the parameter was explicitly provided by the user
259-
if param.name is not None:
260-
param_source = ctx.get_parameter_source(param.name)
261-
if param_source == click.core.ParameterSource.COMMANDLINE:
262-
click.secho(
263-
"Warning: The --setup flag is deprecated and will be removed in a future version. "
264-
"Setup is now always enabled by default.",
265-
fg="yellow",
266-
err=True,
267-
)
268-
return value
269-
270-
271264
def _setup_flows(
272265
flow_iter: Iterable[flow.Flow],
273266
*,
@@ -292,6 +285,22 @@ def _setup_flows(
292285
setup_bundle.apply(report_to_stdout=not quiet)
293286

294287

288+
def _deprecate_setup_flag(
289+
ctx: click.Context, param: click.Parameter, value: bool
290+
) -> bool:
291+
"""Callback to warn users that --setup flag is deprecated."""
292+
if param.name is not None:
293+
param_source = ctx.get_parameter_source(param.name)
294+
if param_source == click.core.ParameterSource.COMMANDLINE:
295+
click.secho(
296+
"Warning: The --setup flag is deprecated and will be removed in a future version. "
297+
"Setup is now always enabled by default.",
298+
fg="yellow",
299+
err=True,
300+
)
301+
return value
302+
303+
295304
def _show_no_live_update_hint() -> None:
296305
click.secho(
297306
"NOTE: No change capture mechanism exists. See https://cocoindex.io/docs/core/flow_methods#live-update for more details.\n",
@@ -328,7 +337,7 @@ def setup(app_target: str, force: bool, reset: bool) -> None:
328337
"""
329338
Check and apply backend setup changes for flows, including the internal storage and target (to export to).
330339
331-
`APP_TARGET`: `path/to/app.py` or `installed_module`.
340+
APP_TARGET: path/to/app.py or installed_module.
332341
"""
333342
app_ref = _get_app_ref_from_specifier(app_target)
334343
_load_user_app(app_ref)
@@ -357,8 +366,8 @@ def drop(app_target: str | None, flow_name: tuple[str, ...], force: bool) -> Non
357366
358367
\b
359368
Modes of operation:
360-
1. Drop all flows defined in an app: `cocoindex drop <APP_TARGET>`
361-
2. Drop specific named flows: `cocoindex drop <APP_TARGET> [FLOW_NAME...]`
369+
1. Drop all flows defined in an app: cocoindex drop <APP_TARGET>
370+
2. Drop specific named flows: cocoindex drop <APP_TARGET> [FLOW_NAME...]
362371
"""
363372
app_ref = None
364373

@@ -379,7 +388,7 @@ def drop(app_target: str | None, flow_name: tuple[str, ...], force: bool) -> Non
379388
flows.append(flow.flow_by_name(name))
380389
except KeyError:
381390
click.echo(
382-
f"Warning: Failed to get flow `{name}`. Ignored.",
391+
f"Warning: Failed to get flow {name}. Ignored.",
383392
err=True,
384393
)
385394
else:
@@ -418,7 +427,7 @@ def drop(app_target: str | None, flow_name: tuple[str, ...], force: bool) -> Non
418427
is_flag=True,
419428
show_default=True,
420429
default=False,
421-
help="Drop existing setup before updating (equivalent to running 'cocoindex drop' first). `--reset` implies `--setup`.",
430+
help="Drop existing setup before updating (equivalent to running 'cocoindex drop' first). --reset implies --setup.",
422431
)
423432
@click.option(
424433
"-f",
@@ -448,7 +457,7 @@ def update(
448457
"""
449458
Update the index to reflect the latest data from data sources.
450459
451-
`APP_FLOW_SPECIFIER`: `path/to/app.py`, module, `path/to/app.py:FlowName`, or `module:FlowName`. If `:FlowName` is omitted, updates all flows.
460+
APP_FLOW_SPECIFIER: path/to/app.py, module, path/to/app.py:FlowName, or module:FlowName. If :FlowName is omitted, updates all flows.
452461
"""
453462
app_ref, flow_name = _parse_app_flow_specifier(app_flow_specifier)
454463
_load_user_app(app_ref)
@@ -479,6 +488,10 @@ def update(
479488
else:
480489
assert len(flow_list) == 1
481490
with flow.FlowLiveUpdater(flow_list[0], options) as updater:
491+
if options.live_mode:
492+
# Show initial status
493+
updater.print_cli_status()
494+
click.echo()
482495
updater.wait()
483496
if options.live_mode:
484497
_show_no_live_update_hint()
@@ -509,20 +522,20 @@ def evaluate(
509522
Instead of updating the index, it dumps what should be indexed to files. Mainly used for evaluation purpose.
510523
511524
\b
512-
`APP_FLOW_SPECIFIER`: Specifies the application and optionally the target flow. Can be one of the following formats:
513-
- `path/to/your_app.py`
514-
- `an_installed.module_name`
515-
- `path/to/your_app.py:SpecificFlowName`
516-
- `an_installed.module_name:SpecificFlowName`
525+
APP_FLOW_SPECIFIER: Specifies the application and optionally the target flow. Can be one of the following formats:
526+
- path/to/your_app.py
527+
- an_installed.module_name
528+
- path/to/your_app.py:SpecificFlowName
529+
- an_installed.module_name:SpecificFlowName
517530
518-
`:SpecificFlowName` can be omitted only if the application defines a single flow.
531+
:SpecificFlowName can be omitted only if the application defines a single flow.
519532
"""
520533
app_ref, flow_ref = _parse_app_flow_specifier(app_flow_specifier)
521534
_load_user_app(app_ref)
522535

523536
fl = _flow_by_name(flow_ref)
524537
if output_dir is None:
525-
output_dir = f"eval_{setting.get_app_namespace(trailing_delimiter='_')}{fl.name}_{datetime.datetime.now().strftime('%y%m%d_%H%M%S')}"
538+
output_dir = f"eval_{setting.get_app_namespace(trailing_delimiter='')}{fl.name}{datetime.datetime.now().strftime('%y%m%d_%H%M%S')}"
526539
options = flow.EvaluateAndDumpOptions(output_dir=output_dir, use_cache=cache)
527540
fl.evaluate_and_dump(options)
528541

@@ -542,7 +555,7 @@ def evaluate(
542555
type=str,
543556
help="The origins of the clients (e.g. CocoInsight UI) to allow CORS from. "
544557
"Multiple origins can be specified as a comma-separated list. "
545-
"e.g. `https://cocoindex.io,http://localhost:3000`. "
558+
"e.g. https://cocoindex.io,http://localhost:3000. "
546559
"Origins specified in COCOINDEX_SERVER_CORS_ORIGINS will also be included.",
547560
)
548561
@click.option(
@@ -580,7 +593,7 @@ def evaluate(
580593
is_flag=True,
581594
show_default=True,
582595
default=False,
583-
help="Drop existing setup before starting server (equivalent to running 'cocoindex drop' first). `--reset` implies `--setup`.",
596+
help="Drop existing setup before starting server (equivalent to running 'cocoindex drop' first). --reset implies --setup.",
584597
)
585598
@click.option(
586599
"--reexport",
@@ -632,7 +645,7 @@ def server(
632645
633646
It will allow tools like CocoInsight to access the server.
634647
635-
`APP_TARGET`: `path/to/app.py` or `installed_module`.
648+
APP_TARGET: path/to/app.py or installed_module.
636649
"""
637650
app_ref = _get_app_ref_from_specifier(app_target)
638651
args = (
@@ -826,5 +839,5 @@ def _flow_by_name(name: str | None) -> flow.Flow:
826839
return flow.flow_by_name(_flow_name(name))
827840

828841

829-
if __name__ == "__main__":
830-
cli()
842+
if _name_ == "_main_":
843+
cli()

0 commit comments

Comments
 (0)