Coverage for src/lilbee/cli/commands/dataset.py: 100%
46 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-09-28 17:20 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-09-28 17:20 +0000
1"""Export and import the per-page text dataset."""
3from __future__ import annotations
5import asyncio
6from pathlib import Path
7from typing import NoReturn
9import typer
10from rich.text import Text
12from lilbee.cli import theme
13from lilbee.cli.app import apply_overrides, console, data_dir_option, global_option
14from lilbee.cli.helpers import json_output, print_prefixed, sigint_cancel
15from lilbee.core.config import cfg
16from lilbee.runtime.cancellation import TaskCancelledError
17from lilbee.runtime.console import styled
19_export_output_argument = typer.Argument(
20 Path("pages.parquet"),
21 help="Output file (suffix sets the format unless --format is given).",
22)
23_import_dataset_argument = typer.Argument(
24 ...,
25 help="Dataset file to import (parquet or jsonl).",
26)
27_format_option = typer.Option(
28 "",
29 "--format",
30 help="Dataset format: parquet or jsonl. Inferred from the file suffix when omitted.",
31)
32_export_source_option = typer.Option(
33 None,
34 "--source",
35 help="Export only this source (default: every source).",
36)
39def _fail(message: str) -> NoReturn:
40 """Emit *message* as an error in the active output mode and exit non-zero."""
41 if cfg.json_mode:
42 json_output({"error": message})
43 else:
44 print_prefixed(console, "Error: ", message, style=theme.ERROR)
45 raise SystemExit(1)
48def export_cmd(
49 output: Path = _export_output_argument,
50 fmt: str = _format_option,
51 source: str | None = _export_source_option,
52 data_dir: Path | None = data_dir_option,
53 use_global: bool = global_option,
54) -> None:
55 """Write a per-page {source, page, text} dataset (drops vectors)."""
56 apply_overrides(data_dir=data_dir, use_global=use_global)
57 from lilbee.app.dataset import DatasetError, export_to_path
59 try:
60 with sigint_cancel() as cancel:
61 summary = export_to_path(output, fmt, source, cancel=cancel)
62 except TaskCancelledError:
63 _fail("Export cancelled; the partial file was removed.")
64 except DatasetError as exc:
65 _fail(str(exc))
67 if cfg.json_mode:
68 json_output(summary.model_dump())
69 return
70 console.print(
71 Text.assemble(
72 "Wrote ",
73 (str(summary.pages), theme.LABEL),
74 " pages from ",
75 (str(summary.sources), theme.LABEL),
76 " source(s) to ",
77 (str(output), theme.ACCENT),
78 ),
79 soft_wrap=True,
80 )
83def import_cmd(
84 dataset: Path = _import_dataset_argument,
85 fmt: str = _format_option,
86 data_dir: Path | None = data_dir_option,
87 use_global: bool = global_option,
88) -> None:
89 """Import a per-page text dataset, re-embedding it with the current model."""
90 apply_overrides(data_dir=data_dir, use_global=use_global)
91 from lilbee.app.dataset import DatasetError, import_from_path
93 try:
94 summary = asyncio.run(import_from_path(dataset, fmt))
95 except DatasetError as exc:
96 _fail(str(exc))
98 if cfg.json_mode:
99 json_output(summary.model_dump())
100 return
101 console.print(
102 styled(
103 "Imported ",
104 (str(len(summary.sources)), theme.LABEL),
105 " source(s) (",
106 (str(summary.pages), theme.LABEL),
107 " pages, ",
108 (str(summary.chunks), theme.LABEL),
109 " chunks)",
110 )
111 )