feat(harness): manifest archived/group fields + session mutation helpers
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Tests for session manifest mutations (rename, group, archive, delete)."""
|
||||
import pytest
|
||||
|
||||
from tht.config import DatabaseConfig
|
||||
from tht.session.store import (
|
||||
SessionError,
|
||||
create_session,
|
||||
delete_session,
|
||||
load_session,
|
||||
set_archived,
|
||||
set_group,
|
||||
set_name,
|
||||
)
|
||||
|
||||
|
||||
def _db():
|
||||
return DatabaseConfig(
|
||||
database="testdb", user="u", password="p", # noqa: S106
|
||||
**{"schema": "public"},
|
||||
)
|
||||
|
||||
|
||||
def test_manifest_defaults(tmp_path):
|
||||
m = create_session("domanda", _db(), tmp_path)
|
||||
assert m.archived is False
|
||||
assert m.group is None
|
||||
assert m.name is None
|
||||
|
||||
|
||||
def test_set_name(tmp_path):
|
||||
m = create_session("domanda", _db(), tmp_path)
|
||||
set_name(m.id, "Pazienti 2024", tmp_path)
|
||||
assert load_session(m.id, tmp_path).name == "Pazienti 2024"
|
||||
|
||||
|
||||
def test_set_name_empty_clears(tmp_path):
|
||||
m = create_session("domanda", _db(), tmp_path)
|
||||
set_name(m.id, "x", tmp_path)
|
||||
set_name(m.id, "", tmp_path)
|
||||
assert load_session(m.id, tmp_path).name is None
|
||||
|
||||
|
||||
def test_set_group_and_clear(tmp_path):
|
||||
m = create_session("domanda", _db(), tmp_path)
|
||||
set_group(m.id, "Aritmologia", tmp_path)
|
||||
assert load_session(m.id, tmp_path).group == "Aritmologia"
|
||||
set_group(m.id, "", tmp_path)
|
||||
assert load_session(m.id, tmp_path).group is None
|
||||
|
||||
|
||||
def test_set_archived(tmp_path):
|
||||
m = create_session("domanda", _db(), tmp_path)
|
||||
set_archived(m.id, True, tmp_path)
|
||||
assert load_session(m.id, tmp_path).archived is True
|
||||
set_archived(m.id, False, tmp_path)
|
||||
assert load_session(m.id, tmp_path).archived is False
|
||||
|
||||
|
||||
def test_delete_session(tmp_path):
|
||||
m = create_session("domanda", _db(), tmp_path)
|
||||
delete_session(m.id, tmp_path)
|
||||
assert not (tmp_path / m.id).exists()
|
||||
with pytest.raises(SessionError):
|
||||
load_session(m.id, tmp_path)
|
||||
|
||||
|
||||
def test_delete_missing_raises(tmp_path):
|
||||
with pytest.raises(SessionError):
|
||||
delete_session("nope", tmp_path)
|
||||
@@ -44,6 +44,9 @@ def _list_sessions(sessions_root: Path) -> list[dict]:
|
||||
"created_at": m.created_at.isoformat(),
|
||||
"updated_at": m.updated_at.isoformat() if m.updated_at else None,
|
||||
"author": m.author,
|
||||
"name": m.name,
|
||||
"group": m.group,
|
||||
"archived": m.archived,
|
||||
})
|
||||
out.sort(key=lambda r: r["created_at"], reverse=True)
|
||||
return out
|
||||
|
||||
@@ -43,6 +43,8 @@ class SessionManifest(_YamlModel):
|
||||
model: str | None = None
|
||||
thinking: str | None = None
|
||||
name: str | None = None
|
||||
archived: bool = False
|
||||
group: str | None = None
|
||||
|
||||
|
||||
class Candidate(BaseModel):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import shutil
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
@@ -127,3 +128,39 @@ def close_session(session_id: str, sessions_root: Path) -> SessionManifest:
|
||||
manifest.updated_by = current_author()
|
||||
manifest.to_yaml(sessions_root / session_id / MANIFEST)
|
||||
return manifest
|
||||
|
||||
|
||||
def _save_touched(manifest: SessionManifest, sessions_root: Path) -> SessionManifest:
|
||||
"""Persist `manifest` updating updated_at/updated_by (single save path for mutations)."""
|
||||
manifest.updated_at = datetime.now(UTC)
|
||||
manifest.updated_by = current_author()
|
||||
manifest.to_yaml(sessions_root / manifest.id / MANIFEST)
|
||||
return manifest
|
||||
|
||||
|
||||
def set_name(session_id: str, name: str | None, sessions_root: Path) -> SessionManifest:
|
||||
"""Set the descriptive name (empty/blank clears it back to None)."""
|
||||
manifest = load_session(session_id, sessions_root)
|
||||
manifest.name = (name or "").strip() or None
|
||||
return _save_touched(manifest, sessions_root)
|
||||
|
||||
|
||||
def set_group(session_id: str, group: str | None, sessions_root: Path) -> SessionManifest:
|
||||
"""Set the group (empty/blank clears it back to None)."""
|
||||
manifest = load_session(session_id, sessions_root)
|
||||
manifest.group = (group or "").strip() or None
|
||||
return _save_touched(manifest, sessions_root)
|
||||
|
||||
|
||||
def set_archived(session_id: str, archived: bool, sessions_root: Path) -> SessionManifest:
|
||||
"""Flip the archived flag. Archiving does NOT change resumability (a finalized
|
||||
session stays read-only); unarchive only moves it back to the active list."""
|
||||
manifest = load_session(session_id, sessions_root)
|
||||
manifest.archived = archived
|
||||
return _save_touched(manifest, sessions_root)
|
||||
|
||||
|
||||
def delete_session(session_id: str, sessions_root: Path) -> None:
|
||||
"""Hard-delete the session directory. SessionError if it does not exist."""
|
||||
load_session(session_id, sessions_root) # raises SessionError if absent
|
||||
shutil.rmtree(sessions_root / session_id)
|
||||
|
||||
Reference in New Issue
Block a user