Coverage for merco/memory/backends/json_backend.py: 100%
45 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 14:04 +0800
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 14:04 +0800
1"""JSONBackend — 每记忆一个 .json 文件"""
2from __future__ import annotations
4import json
5from datetime import datetime
6from pathlib import Path
8from merco.memory.backend import MemoryBackend
11class JSONBackend(MemoryBackend):
12 """JSON 文件后端"""
13 name = "json"
15 def __init__(self, base_path: str):
16 self.base_path = Path(base_path).expanduser()
17 self.base_path.mkdir(parents=True, exist_ok=True)
19 def save(self, key: str, value, tags: list = None) -> None:
20 entry = {
21 "key": key,
22 "value": value,
23 "tags": tags or [],
24 "created_at": datetime.now().isoformat(),
25 }
26 file_path = self.base_path / f"{key}.json"
27 with open(file_path, "w") as f:
28 json.dump(entry, f, indent=2)
30 def load(self, key: str) -> dict | None:
31 file_path = self.base_path / f"{key}.json"
32 if not file_path.exists():
33 return None
34 with open(file_path) as f:
35 return json.load(f)
37 def delete(self, key: str) -> None:
38 file_path = self.base_path / f"{key}.json"
39 if file_path.exists():
40 file_path.unlink()
42 def list_keys(self, tag: str = None) -> list[str]:
43 keys = []
44 for f in self.base_path.glob("*.json"):
45 if tag:
46 with open(f) as fh:
47 data = json.load(fh)
48 if tag in data.get("tags", []):
49 keys.append(f.stem)
50 else:
51 keys.append(f.stem)
52 return keys
54 def search(self, query: str) -> list[dict]:
55 results = []
56 query_lower = query.lower()
57 for f in self.base_path.glob("*.json"):
58 with open(f) as fh:
59 data = json.load(fh)
60 content = json.dumps(data).lower()
61 if query_lower in content:
62 results.append(data)
63 return results