72c548b729
- Migrate from setuptools to hatchling build backend - Add dependency-groups (PEP 735) for dev tooling (pytest, ruff) - Remove redundant requirements.txt in favor of uv.lock - Fix __version__ mismatch (2.0.0 -> 3.0.0 to match pyproject.toml) New test files: - conftest.py: shared fixtures (isolated palace, KG, ChromaDB collection) - test_knowledge_graph.py: 17 tests (entity CRUD, temporal queries, timeline) - test_mcp_server.py: 25 tests (protocol dispatch, read/write/KG/diary tools) - test_searcher.py: 7 tests (search_memories API, filters, error handling) - test_dialect.py: 13 tests (AAAK compression, entity/emotion detection, zettel encoding) All 92 tests pass on Python 3.13 with chromadb 0.6.3.
107 lines
3.7 KiB
Python
107 lines
3.7 KiB
Python
"""
|
|
conftest.py — Shared fixtures for MemPalace tests.
|
|
|
|
Provides isolated palace and knowledge graph instances so tests never
|
|
touch the user's real data or leak temp files on failure.
|
|
"""
|
|
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
|
|
import chromadb
|
|
import pytest
|
|
|
|
from mempalace.config import MempalaceConfig
|
|
from mempalace.knowledge_graph import KnowledgeGraph
|
|
|
|
|
|
@pytest.fixture
|
|
def tmp_dir():
|
|
"""Create and auto-cleanup a temporary directory."""
|
|
d = tempfile.mkdtemp(prefix="mempalace_test_")
|
|
yield d
|
|
shutil.rmtree(d, ignore_errors=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def palace_path(tmp_dir):
|
|
"""Path to an empty palace directory inside tmp_dir."""
|
|
p = os.path.join(tmp_dir, "palace")
|
|
os.makedirs(p)
|
|
return p
|
|
|
|
|
|
@pytest.fixture
|
|
def config(tmp_dir, palace_path):
|
|
"""A MempalaceConfig pointing at the temp palace."""
|
|
cfg_dir = os.path.join(tmp_dir, "config")
|
|
os.makedirs(cfg_dir)
|
|
import json
|
|
|
|
with open(os.path.join(cfg_dir, "config.json"), "w") as f:
|
|
json.dump({"palace_path": palace_path}, f)
|
|
return MempalaceConfig(config_dir=cfg_dir)
|
|
|
|
|
|
@pytest.fixture
|
|
def collection(palace_path):
|
|
"""A ChromaDB collection pre-seeded in the temp palace."""
|
|
client = chromadb.PersistentClient(path=palace_path)
|
|
col = client.get_or_create_collection("mempalace_drawers")
|
|
return col
|
|
|
|
|
|
@pytest.fixture
|
|
def seeded_collection(collection):
|
|
"""Collection with a handful of representative drawers."""
|
|
collection.add(
|
|
ids=[
|
|
"drawer_proj_backend_aaa",
|
|
"drawer_proj_backend_bbb",
|
|
"drawer_proj_frontend_ccc",
|
|
"drawer_notes_planning_ddd",
|
|
],
|
|
documents=[
|
|
"The authentication module uses JWT tokens for session management. "
|
|
"Tokens expire after 24 hours. Refresh tokens are stored in HttpOnly cookies.",
|
|
"Database migrations are handled by Alembic. We use PostgreSQL 15 "
|
|
"with connection pooling via pgbouncer.",
|
|
"The React frontend uses TanStack Query for server state management. "
|
|
"All API calls go through a centralized fetch wrapper.",
|
|
"Sprint planning: migrate auth to passkeys by Q3. "
|
|
"Evaluate ChromaDB alternatives for vector search.",
|
|
],
|
|
metadatas=[
|
|
{"wing": "project", "room": "backend", "source_file": "auth.py", "chunk_index": 0, "added_by": "miner", "filed_at": "2026-01-01T00:00:00"},
|
|
{"wing": "project", "room": "backend", "source_file": "db.py", "chunk_index": 0, "added_by": "miner", "filed_at": "2026-01-02T00:00:00"},
|
|
{"wing": "project", "room": "frontend", "source_file": "App.tsx", "chunk_index": 0, "added_by": "miner", "filed_at": "2026-01-03T00:00:00"},
|
|
{"wing": "notes", "room": "planning", "source_file": "sprint.md", "chunk_index": 0, "added_by": "miner", "filed_at": "2026-01-04T00:00:00"},
|
|
],
|
|
)
|
|
return collection
|
|
|
|
|
|
@pytest.fixture
|
|
def kg(tmp_dir):
|
|
"""An isolated KnowledgeGraph using a temp SQLite file."""
|
|
db_path = os.path.join(tmp_dir, "test_kg.sqlite3")
|
|
return KnowledgeGraph(db_path=db_path)
|
|
|
|
|
|
@pytest.fixture
|
|
def seeded_kg(kg):
|
|
"""KnowledgeGraph pre-loaded with sample triples."""
|
|
kg.add_entity("Alice", entity_type="person")
|
|
kg.add_entity("Max", entity_type="person")
|
|
kg.add_entity("swimming", entity_type="activity")
|
|
kg.add_entity("chess", entity_type="activity")
|
|
|
|
kg.add_triple("Alice", "parent_of", "Max", valid_from="2015-04-01")
|
|
kg.add_triple("Max", "does", "swimming", valid_from="2025-01-01")
|
|
kg.add_triple("Max", "does", "chess", valid_from="2024-06-01")
|
|
kg.add_triple("Alice", "works_at", "Acme Corp", valid_from="2020-01-01", valid_to="2024-12-31")
|
|
kg.add_triple("Alice", "works_at", "NewCo", valid_from="2025-01-01")
|
|
|
|
return kg
|