feat(cli): 'tht session set-schema-linking' (file/stdin, validated)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 16:44:36 +02:00
co-authored by Claude Opus 4.8
parent 92caaac18d
commit 00777922d8
2 changed files with 98 additions and 0 deletions
@@ -0,0 +1,67 @@
"""L1: `tht session set-schema-linking` — stdin/file JSON → validate → write."""
import json
from typer.testing import CliRunner
from tht.cli.session_cmd import session_app
from tht.config import DatabaseConfig
from tht.session.store import create_session
def _db():
return DatabaseConfig(database="testdb", user="u", password="p", **{"schema": "public"}) # noqa: S106
def _patch_cfg(monkeypatch, tmp_path):
from tht.cli import session_cmd
class FakePaths:
sessions = tmp_path
class FakeCfg:
paths = FakePaths()
database = _db()
monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda _: FakeCfg())
_VALID = json.dumps({
"question": "q",
"candidates": [{"kind": "table", "name": "fact_x", "decision": "promoted"}],
})
def test_cli_stdin_writes(tmp_path, monkeypatch):
m = create_session("q", _db(), tmp_path)
_patch_cfg(monkeypatch, tmp_path)
res = CliRunner().invoke(session_app, ["set-schema-linking", m.id, "--file", "-"], input=_VALID)
assert res.exit_code == 0, res.output
assert (tmp_path / m.id / "schema_linking.json").exists()
def test_cli_file_writes(tmp_path, monkeypatch):
m = create_session("q", _db(), tmp_path)
p = tmp_path / "sl.json"
p.write_text(_VALID)
_patch_cfg(monkeypatch, tmp_path)
res = CliRunner().invoke(session_app, ["set-schema-linking", m.id, "--file", str(p)])
assert res.exit_code == 0, res.output
assert (tmp_path / m.id / "schema_linking.json").exists()
def test_cli_invalid_json_exit5(tmp_path, monkeypatch):
m = create_session("q", _db(), tmp_path)
_patch_cfg(monkeypatch, tmp_path)
res = CliRunner().invoke(session_app, ["set-schema-linking", m.id, "--file", "-"], input="{not json")
assert res.exit_code == 5
assert not (tmp_path / m.id / "schema_linking.json").exists()
def test_cli_invalid_model_exit5(tmp_path, monkeypatch):
m = create_session("q", _db(), tmp_path)
_patch_cfg(monkeypatch, tmp_path)
res = CliRunner().invoke(
session_app, ["set-schema-linking", m.id, "--file", "-"], input='{"question":"q","bogus":1}'
)
assert res.exit_code == 5
assert not (tmp_path / m.id / "schema_linking.json").exists()
+31
View File
@@ -110,6 +110,37 @@ def set_question_cmd(
typer.secho(f"OK: question.md aggiornato ({path}).", fg=typer.colors.GREEN)
@session_app.command("set-schema-linking")
def set_schema_linking_cmd(
session_id: str = typer.Argument(...),
file: str = typer.Option(
..., "--file", "-f",
help="Path al JSON dello schema-linking, oppure '-' per leggere da stdin."),
config: Path = CONFIG_OPT,
) -> None:
"""Valida (modello SchemaLinking) e scrive schema_linking.json deterministicamente."""
import sys
from pydantic import ValidationError
from tht.session.store import set_schema_linking
cfg = _load_config_or_exit(config)
load_session_or_exit(cfg, session_id)
raw = sys.stdin.read() if file == "-" else Path(file).read_text()
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
typer.secho(f"ERRORE: JSON non valido: {e}", fg=typer.colors.RED, err=True)
raise typer.Exit(code=5)
try:
path = set_schema_linking(session_id, data, cfg.paths.sessions)
except ValidationError as e:
typer.secho(f"ERRORE: schema_linking non valido:\n{e}", fg=typer.colors.RED, err=True)
raise typer.Exit(code=5)
typer.secho(f"OK: schema_linking.json aggiornato ({path}).", fg=typer.colors.GREEN)
@session_app.command("show")
def show_cmd(
session_id: str = typer.Argument(...),