88 lines
3.5 KiB
Python
88 lines
3.5 KiB
Python
from datetime import UTC, datetime
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
import uuid
|
|
|
|
from tht.cli import session_cmd
|
|
from tht.decisions import DecisionInput
|
|
from tht.session.filesystem_repository import FilesystemSessionRepository
|
|
from tht.session.models import PrincipalContext, SessionManifest
|
|
|
|
|
|
def test_finalize_commits_session_before_best_effort_post_commit_read_failure(
|
|
tmp_path, monkeypatch, capsys
|
|
):
|
|
repository = FilesystemSessionRepository(
|
|
tmp_path / "home",
|
|
"demo",
|
|
PrincipalContext(issuer="local", subject="reviewer"),
|
|
root=tmp_path / "sessions",
|
|
)
|
|
session_id = str(uuid.uuid4())
|
|
repository.create(SessionManifest(
|
|
id=session_id,
|
|
created_at=datetime(2026, 8, 24, tzinfo=UTC),
|
|
question="active patients",
|
|
database="analytics",
|
|
schema="mart",
|
|
))
|
|
repository.write_artifact(session_id, "sql_final", "SELECT 1\n")
|
|
repository.write_artifact(
|
|
session_id,
|
|
"schema_linking",
|
|
'{"question":"active patients","candidates":[],"excluded":[]}',
|
|
)
|
|
repository.append_decisions(session_id, [
|
|
DecisionInput(type="sql_approved", subject="phase:7"),
|
|
*[
|
|
DecisionInput(type="phase_approved", subject=f"phase:{phase}")
|
|
for phase in range(1, 9)
|
|
],
|
|
])
|
|
cfg = SimpleNamespace(
|
|
execution=SimpleNamespace(forbidden_functions=[], max_preview_rows=10),
|
|
paths=SimpleNamespace(artifacts=tmp_path / "artifacts"),
|
|
embeddings=object(),
|
|
)
|
|
|
|
class FailingPostCommitRead:
|
|
def get(self, sid):
|
|
snapshot = repository.get(sid)
|
|
if snapshot.manifest.status == "finalized":
|
|
raise RuntimeError("finalized snapshot unavailable")
|
|
return snapshot
|
|
|
|
def finalize(self, manifest, artifacts):
|
|
return repository.finalize(manifest, artifacts)
|
|
|
|
failing_read_repository = FailingPostCommitRead()
|
|
|
|
monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda config: cfg)
|
|
monkeypatch.setattr(
|
|
session_cmd,
|
|
"session_repository",
|
|
lambda config: failing_read_repository,
|
|
)
|
|
monkeypatch.setattr(session_cmd, "load_snapshot_or_exit", lambda config, sid: repository.get(sid))
|
|
monkeypatch.setattr(session_cmd, "session_problems", lambda config, sid: [])
|
|
monkeypatch.setattr("tht.cli.sql_cmd._load_physical_or_exit", lambda config: object())
|
|
monkeypatch.setattr("tht.cli.sql_cmd.promoted_tables_for", lambda config, sid: set())
|
|
monkeypatch.setattr("tht.cli.sql_cmd.do_explain", lambda config, sql: object())
|
|
monkeypatch.setattr("tht.cli.sql_cmd.do_run", lambda config, sql, limit: object())
|
|
monkeypatch.setattr(
|
|
"tht.sqlcheck.validate_sql",
|
|
lambda *args, **kwargs: SimpleNamespace(ok=True, errors=[], ast=object()),
|
|
)
|
|
monkeypatch.setattr("tht.execute.warnings.plan_warnings", lambda *args: [])
|
|
monkeypatch.setattr("tht.execute.warnings.runtime_warnings", lambda *args: [])
|
|
monkeypatch.setattr("tht.execute.warnings.static_warnings", lambda *args: [])
|
|
monkeypatch.setattr("tht.report.render_validation_report", lambda **kwargs: "verified\n")
|
|
monkeypatch.setattr("tht.session.artifacts.build_evidence_entries", lambda *args: [])
|
|
|
|
session_cmd.finalize_cmd(session_id, config=Path("unused.yaml"))
|
|
|
|
captured = capsys.readouterr()
|
|
assert repository.get(session_id).manifest.status == "finalized"
|
|
assert "finalized snapshot unavailable" in captured.err
|
|
assert f"OK: sessione {session_id} finalizzata" in captured.out
|