Files
wehub-resource-sync 15dadb5432
Link Check / link-check (push) Waiting to run
CI / build (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:38:09 +08:00

349 lines
12 KiB
Python

import asyncio
import json
import pickle
from pathlib import Path
import pytest
from leann.cli import LeannCLI
def test_reconstruct_build_args_replays_stored_build_config(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
docs_root = tmp_path / "docs"
docs_root.mkdir()
docs_file = docs_root / "only.md"
docs_file.write_text("hello", encoding="utf-8")
cli = LeannCLI()
index_dir = tmp_path / ".leann" / "indexes" / "sample"
index_dir.mkdir(parents=True)
meta_path = index_dir / "documents.leann.meta.json"
meta_path.write_text(
json.dumps(
{
"backend_name": "hnsw",
"embedding_model": "text-embedding-3-small",
"embedding_mode": "openai",
"backend_kwargs": {
"graph_degree": 32,
"complexity": 64,
"num_threads": 1,
"is_compact": False,
"is_recompute": True,
},
"embedding_options": {
"base_url": "https://metadata.example/v1",
"api_key": "secret-should-not-be-replayed",
"build_prompt_template": "metadata passage: ",
"query_prompt_template": "metadata query: ",
},
}
),
encoding="utf-8",
)
sync_config = {
"roots": [str(docs_root)],
"include_extensions": [".md"],
"ignore_patterns": ["**/.*"],
"build_config": {
"docs": [str(docs_file.resolve())],
"file_types": ".md,.txt",
"include_hidden": True,
"doc_chunk_size": 384,
"doc_chunk_overlap": 96,
"code_chunk_size": 640,
"code_chunk_overlap": 80,
"use_ast_chunking": True,
"ast_chunk_size": 420,
"ast_chunk_overlap": 72,
"ast_fallback_traditional": True,
"graph_degree": 48,
"complexity": 96,
"num_threads": 4,
"compact": True,
"recompute": False,
"embedding_api_base": "https://stored.example/v1",
"embedding_prompt_template": "stored passage: ",
"query_prompt_template": "stored query: ",
},
}
(index_dir / "sync_roots.json").write_text(json.dumps(sync_config), encoding="utf-8")
reconstructed = cli._reconstruct_build_args("sample", force=True)
assert reconstructed is not None
assert "--embedding-api-key" not in reconstructed
parsed = cli.create_parser().parse_args(reconstructed)
assert parsed.docs == [str(docs_file.resolve())]
assert parsed.file_types == ".md,.txt"
assert parsed.include_hidden is True
assert parsed.doc_chunk_size == 384
assert parsed.doc_chunk_overlap == 96
assert parsed.code_chunk_size == 640
assert parsed.code_chunk_overlap == 80
assert parsed.use_ast_chunking is True
assert parsed.ast_chunk_size == 420
assert parsed.ast_chunk_overlap == 72
assert parsed.graph_degree == 48
assert parsed.complexity == 96
assert parsed.num_threads == 4
assert parsed.compact is True
assert parsed.recompute is False
assert parsed.embedding_api_base == "https://stored.example/v1"
assert parsed.embedding_prompt_template == "stored passage: "
assert parsed.query_prompt_template == "stored query: "
assert parsed.force is True
def test_reconstruct_build_args_falls_back_to_metadata_and_sync_config(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
docs_root = tmp_path / "docs"
docs_root.mkdir()
cli = LeannCLI()
index_dir = tmp_path / ".leann" / "indexes" / "legacy"
index_dir.mkdir(parents=True)
(index_dir / "documents.leann.meta.json").write_text(
json.dumps(
{
"backend_name": "hnsw",
"embedding_model": "facebook/contriever",
"embedding_mode": "ollama",
"backend_kwargs": {
"graph_degree": 40,
"complexity": 88,
"num_threads": 3,
"is_compact": True,
"is_recompute": False,
},
"embedding_options": {
"host": "http://ollama.example:11434",
"prompt_template": "passage: ",
},
}
),
encoding="utf-8",
)
(index_dir / "sync_roots.json").write_text(
json.dumps(
{
"roots": [str(docs_root)],
"include_extensions": [".md", ".py"],
"ignore_patterns": None,
}
),
encoding="utf-8",
)
reconstructed = cli._reconstruct_build_args("legacy")
assert reconstructed is not None
parsed = cli.create_parser().parse_args(reconstructed)
assert parsed.docs == [str(docs_root)]
assert parsed.file_types == ".md,.py"
assert parsed.include_hidden is True
assert parsed.graph_degree == 40
assert parsed.complexity == 88
assert parsed.num_threads == 3
assert parsed.compact is True
assert parsed.recompute is False
assert parsed.embedding_host == "http://ollama.example:11434"
assert parsed.embedding_prompt_template == "passage: "
def test_successful_full_build_persists_rebuild_config(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
docs_root = tmp_path / "docs"
docs_root.mkdir()
docs_file = docs_root / "only.py"
docs_file.write_text("def hello():\n return 'world'\n", encoding="utf-8")
cli = LeannCLI()
args = cli.create_parser().parse_args(
[
"build",
"sample",
"--docs",
str(docs_file),
"--backend-name",
"hnsw",
"--file-types",
".py",
"--include-hidden",
"--doc-chunk-size",
"10",
"--doc-chunk-overlap",
"12",
"--code-chunk-size",
"20",
"--code-chunk-overlap",
"25",
"--use-ast-chunking",
"--ast-chunk-size",
"123",
"--ast-chunk-overlap",
"17",
"--graph-degree",
"44",
"--complexity",
"77",
"--num-threads",
"2",
"--compact",
"--no-recompute",
]
)
class FakeSynchronizer:
def detect_changes(self):
return {str(docs_file.resolve())}, set(), set()
def create_snapshot(self):
pass
class SuccessfulBuilder:
def __init__(self, **kwargs):
self.kwargs = kwargs
def add_text(self, _text, metadata=None):
pass
def build_index(self, index_path):
target_dir = Path(index_path).parent
target_dir.mkdir(parents=True, exist_ok=True)
(target_dir / "documents.leann.meta.json").write_text(
json.dumps(
{
"backend_name": self.kwargs["backend_name"],
"embedding_model": self.kwargs["embedding_model"],
"embedding_mode": self.kwargs["embedding_mode"],
"backend_kwargs": {
"graph_degree": self.kwargs["graph_degree"],
"complexity": self.kwargs["complexity"],
"num_threads": self.kwargs["num_threads"],
"is_compact": self.kwargs["is_compact"],
"is_recompute": self.kwargs["is_recompute"],
},
}
),
encoding="utf-8",
)
monkeypatch.setattr(cli, "_build_synchronizers", lambda *_args, **_kwargs: [FakeSynchronizer()])
monkeypatch.setattr(
cli,
"load_documents",
lambda *_args, **_kwargs: [{"text": "rebuilt", "metadata": {"file_path": str(docs_file)}}],
)
monkeypatch.setattr(cli, "register_project_dir", lambda: None)
monkeypatch.setattr("leann.cli.LeannBuilder", SuccessfulBuilder)
asyncio.run(cli.build_index(args))
sync_config = json.loads(
(tmp_path / ".leann" / "indexes" / "sample" / "sync_roots.json").read_text(encoding="utf-8")
)
build_config = sync_config["build_config"]
assert build_config["docs"] == [str(docs_file.resolve())]
assert build_config["file_types"] == ".py"
assert build_config["include_hidden"] is True
assert build_config["doc_chunk_size"] == 10
assert build_config["doc_chunk_overlap"] == 9
assert build_config["code_chunk_size"] == 20
assert build_config["code_chunk_overlap"] == 19
assert build_config["use_ast_chunking"] is True
assert build_config["ast_chunk_size"] == 123
assert build_config["ast_chunk_overlap"] == 17
assert build_config["graph_degree"] == 44
assert build_config["complexity"] == 77
assert build_config["num_threads"] == 2
assert build_config["compact"] is True
assert build_config["recompute"] is False
def test_full_rebuild_failure_preserves_existing_index(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
docs_root = tmp_path / "docs"
docs_root.mkdir()
docs_file = docs_root / "only.md"
docs_file.write_text("hello", encoding="utf-8")
cli = LeannCLI()
index_dir = tmp_path / ".leann" / "indexes" / "sample"
index_dir.mkdir(parents=True)
meta_path = index_dir / "documents.leann.meta.json"
meta_path.write_text(
json.dumps(
{
"backend_name": "hnsw",
"embedding_model": "facebook/contriever",
"embedding_mode": "sentence-transformers",
"backend_kwargs": {"is_compact": False, "is_recompute": True},
}
),
encoding="utf-8",
)
passages_file = index_dir / "documents.leann.passages.jsonl"
passages_file.write_text(
json.dumps({"id": "old", "text": "old text", "metadata": {}}) + "\n",
encoding="utf-8",
)
offset_file = index_dir / "documents.leann.passages.idx"
with open(offset_file, "wb") as f:
pickle.dump({"old": 0}, f)
original_artifacts = {
path: path.read_bytes() for path in (meta_path, passages_file, offset_file)
}
args = cli.create_parser().parse_args(
[
"build",
"sample",
"--docs",
str(docs_file),
"--backend-name",
"hnsw",
"--force",
]
)
built_paths: list[str] = []
class FakeSynchronizer:
def create_snapshot(self):
pass
class FailingBuilder:
def __init__(self, **_kwargs):
pass
def add_text(self, _text, metadata=None):
pass
def build_index(self, index_path):
built_paths.append(index_path)
target_dir = Path(index_path).parent
target_dir.mkdir(parents=True, exist_ok=True)
(target_dir / "documents.leann.passages.jsonl").write_text(
json.dumps({"id": "new", "text": "new text", "metadata": {}}) + "\n",
encoding="utf-8",
)
raise RuntimeError("simulated build failure")
monkeypatch.setattr(cli, "_build_synchronizers", lambda *_args, **_kwargs: [FakeSynchronizer()])
monkeypatch.setattr(
cli,
"load_documents",
lambda *_args, **_kwargs: [{"text": "rebuilt", "metadata": {"file_path": str(docs_file)}}],
)
monkeypatch.setattr(cli, "register_project_dir", lambda: None)
monkeypatch.setattr("leann.cli.LeannBuilder", FailingBuilder)
with pytest.raises(RuntimeError, match="simulated build failure"):
asyncio.run(cli.build_index(args))
assert built_paths
assert built_paths[0] != str(index_dir / "documents.leann")
assert {
path: path.read_bytes() for path in (meta_path, passages_file, offset_file)
} == original_artifacts
assert not list(index_dir.parent.glob(".sample.rebuild-*"))