mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42ce750b79 |
@@ -201,7 +201,6 @@ async def update_frontmatter(path: FilePath, updates: Dict[str, Any]) -> str:
|
||||
|
||||
Raises:
|
||||
FileError: If file operations fail
|
||||
ParseError: If frontmatter parsing fails
|
||||
"""
|
||||
try:
|
||||
# Convert string to Path if needed
|
||||
@@ -210,11 +209,20 @@ async def update_frontmatter(path: FilePath, updates: Dict[str, Any]) -> str:
|
||||
# Read current content
|
||||
content = path_obj.read_text(encoding="utf-8")
|
||||
|
||||
# Parse current frontmatter
|
||||
# Parse current frontmatter with error handling for malformed YAML (issue #378)
|
||||
current_fm = {}
|
||||
if has_frontmatter(content):
|
||||
current_fm = parse_frontmatter(content)
|
||||
content = remove_frontmatter(content)
|
||||
try:
|
||||
current_fm = parse_frontmatter(content)
|
||||
content = remove_frontmatter(content)
|
||||
except (ParseError, yaml.YAMLError) as e:
|
||||
# Log warning and treat as plain markdown (same pattern as PR #368)
|
||||
logger.warning(
|
||||
f"Failed to parse YAML frontmatter in {path_obj}: {e}. "
|
||||
"Treating file as plain markdown without frontmatter."
|
||||
)
|
||||
# Keep full content, treat as having no frontmatter
|
||||
current_fm = {}
|
||||
|
||||
# Update frontmatter
|
||||
new_fm = {**current_fm, **updates}
|
||||
@@ -229,11 +237,13 @@ async def update_frontmatter(path: FilePath, updates: Dict[str, Any]) -> str:
|
||||
return await compute_checksum(final_content)
|
||||
|
||||
except Exception as e: # pragma: no cover
|
||||
logger.error(
|
||||
"Failed to update frontmatter",
|
||||
path=str(path) if isinstance(path, (str, Path)) else "<unknown>",
|
||||
error=str(e),
|
||||
)
|
||||
# Only log real errors as ERROR (not YAML parsing errors which are already handled)
|
||||
if not isinstance(e, (ParseError, yaml.YAMLError)):
|
||||
logger.error(
|
||||
"Failed to update frontmatter",
|
||||
path=str(path) if isinstance(path, (str, Path)) else "<unknown>",
|
||||
error=str(e),
|
||||
)
|
||||
raise FileError(f"Failed to update frontmatter: {e}")
|
||||
|
||||
|
||||
|
||||
@@ -259,6 +259,42 @@ async def test_update_frontmatter_errors(tmp_path: Path):
|
||||
await update_frontmatter(nonexistent, {"title": "Test"})
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_frontmatter_malformed_yaml(tmp_path: Path):
|
||||
"""Test that malformed YAML frontmatter is handled gracefully (issue #378)."""
|
||||
test_file = tmp_path / "test.md"
|
||||
|
||||
# Create file with malformed YAML frontmatter (colon in title breaks YAML)
|
||||
malformed_content = """---
|
||||
title: KB: Something
|
||||
---
|
||||
# Test Content
|
||||
|
||||
Some content here"""
|
||||
test_file.write_text(malformed_content, encoding="utf-8")
|
||||
|
||||
# Update frontmatter should succeed by treating file as plain markdown
|
||||
updates = {"type": "note", "tags": ["test"]}
|
||||
checksum = await update_frontmatter(test_file, updates)
|
||||
|
||||
# Verify the update succeeded
|
||||
assert checksum is not None
|
||||
updated = test_file.read_text(encoding="utf-8")
|
||||
|
||||
# Should have new frontmatter
|
||||
assert "type: note" in updated
|
||||
assert "tags:" in updated
|
||||
assert "- test" in updated
|
||||
|
||||
# Original content should be preserved
|
||||
assert "Test Content" in updated
|
||||
assert "Some content here" in updated
|
||||
|
||||
# Verify the new frontmatter is valid
|
||||
fm = parse_frontmatter(updated)
|
||||
assert fm == {"type": "note", "tags": ["test"]}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
def test_sanitize_for_filename_removes_invalid_characters():
|
||||
# Test all invalid characters listed in the regex
|
||||
|
||||
Reference in New Issue
Block a user