migration
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
import pytest
|
||||
|
||||
from personal_mcp.registry.ingest.document import MarkdownDocument
|
||||
|
||||
# Ingest-specific fixtures and factories belong in this subtree conftest.
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def make_doc() -> Callable[[str], MarkdownDocument]:
|
||||
def _make_doc(relpath: str, content: str = "# body\n") -> MarkdownDocument:
|
||||
return MarkdownDocument(relpath=PurePosixPath(relpath), content=content)
|
||||
|
||||
return _make_doc
|
||||
@@ -1,32 +1,21 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
import pytest
|
||||
|
||||
from personal_mcp.registry.ingest.document import MarkdownDocument
|
||||
from personal_mcp.registry.ingest.prompt import PromptFilesBundle
|
||||
from personal_mcp.registry.load import get_docs_registry
|
||||
|
||||
pytestmark = pytest.mark.unit
|
||||
|
||||
REPO_ROOT = Path(__file__).parents[3]
|
||||
DOCS_ROOT = REPO_ROOT / "docs"
|
||||
|
||||
|
||||
class TestCurrentDocsIngestion:
|
||||
"""Covers ingestion of the repository's current docs tree."""
|
||||
|
||||
def test_loads_markdown_documents(self) -> None:
|
||||
"""Ensures all current markdown documents can be loaded."""
|
||||
docs = MarkdownDocument.from_root(DOCS_ROOT)
|
||||
def test_registry_includes_docs_and_excludes_skills(self) -> None:
|
||||
"""Ensures the docs registry cannot duplicate native skill resources."""
|
||||
registry = get_docs_registry()
|
||||
|
||||
assert docs
|
||||
|
||||
def test_bundles_current_prompts(self) -> None:
|
||||
"""Ensures all current canonical prompt documents can be bundled."""
|
||||
docs = MarkdownDocument.from_root(DOCS_ROOT)
|
||||
expected_slugs = {path.parent.name for path in DOCS_ROOT.glob("prompts/*/PROMPT.md")}
|
||||
|
||||
bundles = PromptFilesBundle.from_docs(docs.values())
|
||||
|
||||
assert {bundle.slug for bundle in bundles} == expected_slugs
|
||||
assert PurePosixPath("index.md") in registry.docs_markdown_by_path
|
||||
assert any(path.parts[0] == "prompts" for path in registry.docs_markdown_by_path)
|
||||
assert all(path.parts[0] != "skills" for path in registry.docs_markdown_by_path)
|
||||
|
||||
@@ -1,176 +1,27 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
import pytest
|
||||
|
||||
from personal_mcp.registry.ingest.document import MarkdownDocument
|
||||
from personal_mcp.registry.ingest.document import get_frontmatter_delim_idx
|
||||
from personal_mcp.registry.ingest.document import get_raw_frontmatter
|
||||
from personal_mcp.registry.ingest.document import walk_resources
|
||||
|
||||
pytestmark = pytest.mark.unit
|
||||
|
||||
|
||||
class TestMarkdownDocument:
|
||||
"""Covers MarkdownDocument construction and derived properties."""
|
||||
"""Covers recursive Markdown discovery and loading."""
|
||||
|
||||
class TestFromRoot:
|
||||
"""Covers loading markdown documents from a resource root."""
|
||||
def test_loads_markdown_in_stable_order(self, tmp_path: Path) -> None:
|
||||
nested = tmp_path / "guides"
|
||||
nested.mkdir()
|
||||
(nested / "b.md").write_text("caf\u00e9\n", encoding="utf-8")
|
||||
(nested / "a.md").write_text("alpha\n", encoding="utf-8")
|
||||
(nested / "ignored.txt").write_text("ignored\n", encoding="utf-8")
|
||||
|
||||
def test_keys_by_relpath(self, tmp_path: Path) -> None:
|
||||
"""Ensures from_root returns a mapping keyed by relative path."""
|
||||
skills_dir = tmp_path / "skills" / "demo"
|
||||
skills_dir.mkdir(parents=True)
|
||||
(skills_dir / "SKILL.md").write_text("# demo\n", encoding="utf-8")
|
||||
docs = MarkdownDocument.from_root(tmp_path)
|
||||
|
||||
docs = MarkdownDocument.from_root(tmp_path)
|
||||
|
||||
assert set(docs) == {PurePosixPath("skills/demo/SKILL.md")}
|
||||
|
||||
def test_loads_markdown_only(self, tmp_path: Path) -> None:
|
||||
"""Ensures from_root includes only markdown resources."""
|
||||
(tmp_path / "a.md").write_text("a\n", encoding="utf-8")
|
||||
(tmp_path / "b.MD").write_text("b\n", encoding="utf-8")
|
||||
(tmp_path / "c.txt").write_text("c\n", encoding="utf-8")
|
||||
|
||||
docs = MarkdownDocument.from_root(tmp_path)
|
||||
|
||||
assert set(docs) == {PurePosixPath("a.md"), PurePosixPath("b.MD")}
|
||||
|
||||
def test_preserves_relpaths(self, tmp_path: Path) -> None:
|
||||
"""Ensures from_root preserves PurePosixPath-style relative paths."""
|
||||
nested = tmp_path / "skills" / "slug"
|
||||
nested.mkdir(parents=True)
|
||||
(nested / "SKILL.md").write_text("# slug\n", encoding="utf-8")
|
||||
|
||||
docs = MarkdownDocument.from_root(tmp_path)
|
||||
[relpath] = docs.keys()
|
||||
|
||||
assert isinstance(relpath, PurePosixPath)
|
||||
assert relpath == PurePosixPath("skills/slug/SKILL.md")
|
||||
|
||||
class TestFromResource:
|
||||
"""Covers loading a single markdown document from a resource."""
|
||||
|
||||
def test_reads_utf8(self, tmp_path: Path) -> None:
|
||||
"""Ensures from_resource reads text using UTF-8."""
|
||||
resource = tmp_path / "index.md"
|
||||
resource.write_text("caf\u00e9\n", encoding="utf-8")
|
||||
|
||||
doc = MarkdownDocument.from_resource(PurePosixPath("index.md"), resource)
|
||||
|
||||
assert doc.content == "caf\u00e9\n"
|
||||
|
||||
def test_sets_frontmatter(self, tmp_path: Path) -> None:
|
||||
"""Ensures from_resource stores frontmatter when delimiters exist."""
|
||||
resource = tmp_path / "index.md"
|
||||
resource.write_text("---\nname: demo\n---\n# body\n", encoding="utf-8")
|
||||
|
||||
doc = MarkdownDocument.from_resource(PurePosixPath("index.md"), resource)
|
||||
|
||||
assert doc.frontmatter == "name: demo"
|
||||
|
||||
def test_none_frontmatter(self, tmp_path: Path) -> None:
|
||||
"""Ensures from_resource sets frontmatter to None when absent."""
|
||||
resource = tmp_path / "index.md"
|
||||
resource.write_text("# no frontmatter\n", encoding="utf-8")
|
||||
|
||||
doc = MarkdownDocument.from_resource(PurePosixPath("index.md"), resource)
|
||||
|
||||
assert doc.frontmatter is None
|
||||
|
||||
class TestPromptSlugProperty:
|
||||
"""Covers prompt_slug derivation from document relative paths."""
|
||||
|
||||
def test_returns_slug(self) -> None:
|
||||
"""Ensures prompt_slug returns the slug for valid prompt paths."""
|
||||
doc = MarkdownDocument(relpath=PurePosixPath("prompts/demo/PROMPT.md"), content="#")
|
||||
|
||||
assert doc.prompt_slug == "demo"
|
||||
|
||||
def test_none_for_non_prompt(self) -> None:
|
||||
"""Ensures prompt_slug is None for non-prompt paths."""
|
||||
doc = MarkdownDocument(relpath=PurePosixPath("docs/index.md"), content="#")
|
||||
|
||||
assert doc.prompt_slug is None
|
||||
|
||||
def test_none_for_incomplete_prompt(self) -> None:
|
||||
"""Ensures prompt_slug is None for incomplete prompt paths."""
|
||||
doc = MarkdownDocument(relpath=PurePosixPath("prompts/demo.md"), content="#")
|
||||
|
||||
assert doc.prompt_slug is None
|
||||
|
||||
|
||||
class TestWalkResources:
|
||||
"""Covers recursive resource walking and markdown filtering behavior."""
|
||||
|
||||
def test_yields_markdown(self, tmp_path: Path) -> None:
|
||||
"""Ensures walk_resources yields markdown files from nested directories."""
|
||||
nested = tmp_path / "skills" / "alpha"
|
||||
nested.mkdir(parents=True)
|
||||
(nested / "SKILL.md").write_text("# alpha\n", encoding="utf-8")
|
||||
(tmp_path / "index.md").write_text("# index\n", encoding="utf-8")
|
||||
|
||||
relpaths = [path for path, _ in walk_resources(tmp_path)]
|
||||
|
||||
assert relpaths == [
|
||||
PurePosixPath("index.md"),
|
||||
PurePosixPath("skills/alpha/SKILL.md"),
|
||||
assert list(docs) == [
|
||||
PurePosixPath("guides/a.md"),
|
||||
PurePosixPath("guides/b.md"),
|
||||
]
|
||||
|
||||
def test_ignores_other_suffixes(self, tmp_path: Path) -> None:
|
||||
"""Ensures walk_resources excludes files with non-matching suffixes."""
|
||||
(tmp_path / "a.md").write_text("a\n", encoding="utf-8")
|
||||
(tmp_path / "b.txt").write_text("b\n", encoding="utf-8")
|
||||
(tmp_path / "c.json").write_text("c\n", encoding="utf-8")
|
||||
|
||||
relpaths = [path for path, _ in walk_resources(tmp_path)]
|
||||
|
||||
assert relpaths == [PurePosixPath("a.md")]
|
||||
|
||||
def test_sorted_output(self, tmp_path: Path) -> None:
|
||||
"""Ensures walk_resources yields entries in sorted child-name order."""
|
||||
(tmp_path / "b.md").write_text("b\n", encoding="utf-8")
|
||||
(tmp_path / "a.md").write_text("a\n", encoding="utf-8")
|
||||
(tmp_path / "skills").mkdir()
|
||||
(tmp_path / "skills" / "z.md").write_text("z\n", encoding="utf-8")
|
||||
|
||||
relpaths = [path for path, _ in walk_resources(tmp_path)]
|
||||
|
||||
assert relpaths == [
|
||||
PurePosixPath("a.md"),
|
||||
PurePosixPath("b.md"),
|
||||
PurePosixPath("skills/z.md"),
|
||||
]
|
||||
|
||||
def test_applies_prefix(self, tmp_path: Path) -> None:
|
||||
"""Ensures walk_resources prepends the provided prefix to relpaths."""
|
||||
(tmp_path / "index.md").write_text("# index\n", encoding="utf-8")
|
||||
|
||||
relpaths = [path for path, _ in walk_resources(tmp_path, prefix=PurePosixPath("docs"))]
|
||||
|
||||
assert relpaths == [PurePosixPath("docs/index.md")]
|
||||
|
||||
|
||||
class TestFrontmatterParsing:
|
||||
"""Covers frontmatter delimiter discovery and raw block extraction."""
|
||||
|
||||
def test_extracts_between_delimiters(self) -> None:
|
||||
"""Ensures get_raw_frontmatter returns lines between first delimiters."""
|
||||
raw = "---\nname: demo\ntags:\n - test\n---\n# body\n"
|
||||
|
||||
assert get_raw_frontmatter(raw) == "name: demo\ntags:\n - test"
|
||||
|
||||
def test_none_without_two_delimiters(self) -> None:
|
||||
"""Ensures get_raw_frontmatter returns None without two delimiters."""
|
||||
raw = "---\nname: demo\n# body\n"
|
||||
|
||||
assert get_raw_frontmatter(raw) is None
|
||||
|
||||
def test_allows_leading_whitespace(self) -> None:
|
||||
"""Ensures delimiter detection accepts lines with leading whitespace."""
|
||||
raw = " ---\nname: demo\n ---\n# body\n"
|
||||
|
||||
assert list(get_frontmatter_delim_idx(raw)) == [0, 2]
|
||||
assert docs[PurePosixPath("guides/b.md")].content == "caf\u00e9\n"
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from personal_mcp.registry.ingest.document import MarkdownDocument
|
||||
from personal_mcp.registry.ingest.prompt import PromptFilesBundle
|
||||
from personal_mcp.registry.ingest.prompt import group_prompt_paths
|
||||
|
||||
pytestmark = pytest.mark.unit
|
||||
|
||||
MakeDoc = Callable[[str], MarkdownDocument]
|
||||
|
||||
|
||||
class TestPromptFilesBundle:
|
||||
"""Covers PromptFilesBundle construction and path-based categorization."""
|
||||
|
||||
class TestFromRoot:
|
||||
"""Covers bundle creation from resource roots."""
|
||||
|
||||
def test_builds_bundles(self, tmp_path: Path) -> None:
|
||||
"""Ensures from_root builds bundles from discovered markdown docs."""
|
||||
alpha = tmp_path / "prompts" / "alpha"
|
||||
beta = tmp_path / "prompts" / "beta"
|
||||
alpha.mkdir(parents=True)
|
||||
beta.mkdir(parents=True)
|
||||
(alpha / "PROMPT.md").write_text("# alpha\n", encoding="utf-8")
|
||||
(alpha / "notes.md").write_text("notes\n", encoding="utf-8")
|
||||
(beta / "PROMPT.md").write_text("# beta\n", encoding="utf-8")
|
||||
|
||||
bundles = PromptFilesBundle.from_root(tmp_path)
|
||||
|
||||
assert {bundle.slug for bundle in bundles} == {"alpha", "beta"}
|
||||
|
||||
def test_delegates_to_from_docs(
|
||||
self,
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""Ensures from_root delegates bundle assembly to from_docs."""
|
||||
alpha = tmp_path / "prompts" / "alpha"
|
||||
beta = tmp_path / "prompts" / "beta"
|
||||
alpha.mkdir(parents=True)
|
||||
beta.mkdir(parents=True)
|
||||
(alpha / "PROMPT.md").write_text("# alpha\n", encoding="utf-8")
|
||||
(alpha / "notes.md").write_text("notes\n", encoding="utf-8")
|
||||
(beta / "PROMPT.md").write_text("# beta\n", encoding="utf-8")
|
||||
|
||||
from_root = PromptFilesBundle.from_root(tmp_path)
|
||||
from_docs = PromptFilesBundle.from_docs(MarkdownDocument.from_root(tmp_path).values())
|
||||
|
||||
assert tuple(from_root) == from_docs
|
||||
|
||||
class TestFromDocs:
|
||||
"""Covers bundle creation from preloaded markdown documents."""
|
||||
|
||||
def test_groups_by_slug(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures from_docs groups documents by prompt slug."""
|
||||
docs = [
|
||||
make_doc("prompts/alpha/PROMPT.md"),
|
||||
make_doc("prompts/alpha/notes.md"),
|
||||
make_doc("prompts/beta/PROMPT.md"),
|
||||
]
|
||||
|
||||
bundles = PromptFilesBundle.from_docs(docs)
|
||||
|
||||
assert {bundle.slug for bundle in bundles} == {"alpha", "beta"}
|
||||
|
||||
def test_one_bundle_per_slug(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures from_docs produces one PromptFilesBundle per slug."""
|
||||
docs = [
|
||||
make_doc("prompts/alpha/PROMPT.md"),
|
||||
make_doc("prompts/alpha/notes.md"),
|
||||
make_doc("prompts/alpha/changelog.md"),
|
||||
]
|
||||
|
||||
bundles = PromptFilesBundle.from_docs(docs)
|
||||
|
||||
assert len(bundles) == 1
|
||||
assert bundles[0].slug == "alpha"
|
||||
|
||||
class TestFromPaths:
|
||||
"""Covers classification of prompt and other documents."""
|
||||
|
||||
def test_selects_prompt_md(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures from_paths selects PROMPT.md as the primary document."""
|
||||
docs = {
|
||||
make_doc("prompts/alpha/PROMPT.md"),
|
||||
make_doc("prompts/alpha/notes.md"),
|
||||
}
|
||||
|
||||
bundle = PromptFilesBundle.from_paths("alpha", docs)
|
||||
|
||||
assert bundle.prompt.relpath.name == "PROMPT.md"
|
||||
|
||||
def test_collects_other_docs(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures from_paths classifies non-prompt docs as other docs."""
|
||||
docs = {
|
||||
make_doc("prompts/alpha/PROMPT.md"),
|
||||
make_doc("prompts/alpha/notes.md"),
|
||||
make_doc("prompts/alpha/changelog.md"),
|
||||
}
|
||||
|
||||
bundle = PromptFilesBundle.from_paths("alpha", docs)
|
||||
|
||||
assert {doc.relpath.as_posix() for doc in bundle.other} == {
|
||||
"prompts/alpha/changelog.md",
|
||||
"prompts/alpha/notes.md",
|
||||
}
|
||||
|
||||
|
||||
class TestGroupPromptPaths:
|
||||
"""Covers grouping markdown documents by derived prompt slug."""
|
||||
|
||||
def test_groups_slugged_docs(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures group_prompt_paths groups only documents with a slug."""
|
||||
docs = [
|
||||
make_doc("prompts/alpha/PROMPT.md"),
|
||||
make_doc("prompts/alpha/notes.md"),
|
||||
make_doc("prompts/beta/PROMPT.md"),
|
||||
]
|
||||
|
||||
grouped = group_prompt_paths(docs)
|
||||
|
||||
assert set(grouped) == {"alpha", "beta"}
|
||||
|
||||
def test_excludes_unslugged_docs(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures group_prompt_paths excludes documents without prompt slugs."""
|
||||
docs = [
|
||||
make_doc("docs/index.md"),
|
||||
make_doc("prompts/legacy.md"),
|
||||
]
|
||||
|
||||
assert group_prompt_paths(docs) == {}
|
||||
|
||||
def test_returns_sets(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures group_prompt_paths returns sets of docs per slug."""
|
||||
grouped = group_prompt_paths([make_doc("prompts/alpha/PROMPT.md")])
|
||||
|
||||
assert isinstance(grouped["alpha"], set)
|
||||
|
||||
def test_stable_grouping(self, make_doc: MakeDoc) -> None:
|
||||
"""Ensures group_prompt_paths behaves consistently after internal sorting."""
|
||||
docs = [
|
||||
make_doc("prompts/beta/PROMPT.md"),
|
||||
make_doc("prompts/alpha/notes.md"),
|
||||
make_doc("prompts/alpha/PROMPT.md"),
|
||||
]
|
||||
|
||||
grouped_forward = group_prompt_paths(docs)
|
||||
grouped_reverse = group_prompt_paths(list(reversed(docs)))
|
||||
|
||||
assert grouped_forward == grouped_reverse
|
||||
Reference in New Issue
Block a user