Skip invalid memory CLI rows (#1552)
This commit is contained in:
@@ -47,8 +47,12 @@ def _manager() -> MemoryManager:
|
|||||||
return _mgr
|
return _mgr
|
||||||
|
|
||||||
|
|
||||||
|
def _memory_entries(entries):
|
||||||
|
return [e for e in entries or [] if isinstance(e, dict)]
|
||||||
|
|
||||||
|
|
||||||
def cmd_list(args):
|
def cmd_list(args):
|
||||||
entries = _manager().load_all()
|
entries = _memory_entries(_manager().load_all())
|
||||||
if args.category:
|
if args.category:
|
||||||
entries = [e for e in entries if (e.get("category") or "fact") == args.category]
|
entries = [e for e in entries if (e.get("category") or "fact") == args.category]
|
||||||
if args.source:
|
if args.source:
|
||||||
@@ -62,14 +66,14 @@ def cmd_list(args):
|
|||||||
|
|
||||||
def cmd_search(args):
|
def cmd_search(args):
|
||||||
q = args.query.lower()
|
q = args.query.lower()
|
||||||
entries = _manager().load_all()
|
entries = _memory_entries(_manager().load_all())
|
||||||
matches = [e for e in entries if q in (e.get("text") or "").lower()]
|
matches = [e for e in entries if q in (e.get("text") or "").lower()]
|
||||||
matches = sorted(matches, key=lambda e: e.get("timestamp", 0), reverse=True)
|
matches = sorted(matches, key=lambda e: e.get("timestamp", 0), reverse=True)
|
||||||
emit(matches[: args.limit], args)
|
emit(matches[: args.limit], args)
|
||||||
|
|
||||||
|
|
||||||
def cmd_show(args):
|
def cmd_show(args):
|
||||||
for e in _manager().load_all():
|
for e in _memory_entries(_manager().load_all()):
|
||||||
if e.get("id") == args.id:
|
if e.get("id") == args.id:
|
||||||
emit(e, args)
|
emit(e, args)
|
||||||
return
|
return
|
||||||
@@ -93,7 +97,7 @@ def cmd_add(args):
|
|||||||
|
|
||||||
|
|
||||||
def cmd_delete(args):
|
def cmd_delete(args):
|
||||||
entries = _manager().load_all()
|
entries = _memory_entries(_manager().load_all())
|
||||||
target = next((e for e in entries if e.get("id") == args.id), None)
|
target = next((e for e in entries if e.get("id") == args.id), None)
|
||||||
if not target:
|
if not target:
|
||||||
fail(f"no memory with id {args.id!r}")
|
fail(f"no memory with id {args.id!r}")
|
||||||
@@ -104,7 +108,7 @@ def cmd_delete(args):
|
|||||||
|
|
||||||
def cmd_categories(args):
|
def cmd_categories(args):
|
||||||
counts: dict[str, int] = {}
|
counts: dict[str, int] = {}
|
||||||
for e in _manager().load_all():
|
for e in _memory_entries(_manager().load_all()):
|
||||||
cat = e.get("category") or "fact"
|
cat = e.get("category") or "fact"
|
||||||
counts[cat] = counts.get(cat, 0) + 1
|
counts[cat] = counts.get(cat, 0) + 1
|
||||||
rows = sorted(counts.items(), key=lambda kv: -kv[1])
|
rows = sorted(counts.items(), key=lambda kv: -kv[1])
|
||||||
|
|||||||
31
tests/test_memory_cli_rows.py
Normal file
31
tests/test_memory_cli_rows.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import importlib.machinery
|
||||||
|
import importlib.util
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
|
|
||||||
|
def _load_cli(monkeypatch):
|
||||||
|
svc = types.ModuleType("services.memory.memory")
|
||||||
|
svc.MemoryManager = MagicMock()
|
||||||
|
monkeypatch.setitem(sys.modules, "services.memory.memory", svc)
|
||||||
|
path = ROOT / "scripts" / "odysseus-memory"
|
||||||
|
loader = importlib.machinery.SourceFileLoader("odysseus_memory_cli", str(path))
|
||||||
|
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
def test_memory_entries_skips_invalid_rows(monkeypatch):
|
||||||
|
cli = _load_cli(monkeypatch)
|
||||||
|
|
||||||
|
assert cli._memory_entries([
|
||||||
|
{"id": "m1", "text": "ok"},
|
||||||
|
"bad-row",
|
||||||
|
None,
|
||||||
|
]) == [{"id": "m1", "text": "ok"}]
|
||||||
Reference in New Issue
Block a user