mirror of
https://github.com/natelandau/obsidian-metadata.git
synced 2025-11-08 05:03:47 -05:00
492 lines
16 KiB
Python
492 lines
16 KiB
Python
# type: ignore
|
|
"""Test metadata.py."""
|
|
from pathlib import Path
|
|
|
|
from obsidian_metadata.models.metadata import (
|
|
Frontmatter,
|
|
InlineMetadata,
|
|
InlineTags,
|
|
VaultMetadata,
|
|
)
|
|
from tests.helpers import Regex
|
|
|
|
FILE_CONTENT: str = Path("tests/fixtures/test_vault/test1.md").read_text()
|
|
METADATA: dict[str, list[str]] = {
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["note", "article"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"shared_key2": ["shared_key2_value"],
|
|
"tags": ["tag 2", "tag 1", "tag 3"],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value"],
|
|
"intext_key": ["intext_key_value"],
|
|
}
|
|
FRONTMATTER_CONTENT: str = """
|
|
---
|
|
tags:
|
|
- tag_1
|
|
- tag_2
|
|
-
|
|
- 📅/tag_3
|
|
frontmatter_Key1: "frontmatter_Key1_value"
|
|
frontmatter_Key2: ["note", "article"]
|
|
shared_key1: "shared_key1_value"
|
|
---
|
|
more content
|
|
|
|
---
|
|
horizontal: rule
|
|
---
|
|
"""
|
|
INLINE_CONTENT = """\
|
|
repeated_key:: repeated_key_value1
|
|
|
|
#inline_tag_top1,#inline_tag_top2
|
|
**bold_key1**:: bold_key1_value
|
|
**bold_key2:: bold_key2_value**
|
|
link_key:: [[link_key_value]]
|
|
tag_key:: #tag_key_value
|
|
emoji_📅_key:: emoji_📅_key_value
|
|
**#bold_tag**
|
|
|
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. [in_text_key1:: in_text_key1_value] Ut enim ad minim veniam, quis nostrud exercitation [in_text_key2:: in_text_key2_value] ullamco laboris nisi ut aliquip ex ea commodo consequat. #in_text_tag Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
|
|
|
```python
|
|
#ffffff
|
|
# This is sample text [no_key:: value]with tags and metadata
|
|
#in_codeblock_tag1
|
|
#ffffff;
|
|
in_codeblock_key:: in_codeblock_value
|
|
The quick brown fox jumped over the #in_codeblock_tag2
|
|
```
|
|
repeated_key:: repeated_key_value2
|
|
"""
|
|
|
|
|
|
def test_vault_metadata(capsys) -> None:
|
|
"""Test VaultMetadata class."""
|
|
vm = VaultMetadata()
|
|
assert vm.dict == {}
|
|
|
|
vm.add_metadata(METADATA)
|
|
assert vm.dict == {
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"intext_key": ["intext_key_value"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"shared_key2": ["shared_key2_value"],
|
|
"tags": ["tag 1", "tag 2", "tag 3"],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value"],
|
|
}
|
|
|
|
vm.print_keys()
|
|
captured = capsys.readouterr()
|
|
assert captured.out == Regex(r"frontmatter_Key1 +frontmatter_Key2 +intext_key")
|
|
|
|
vm.print_tags()
|
|
captured = capsys.readouterr()
|
|
assert captured.out == Regex(r"tag 1 +tag 2 +tag 3")
|
|
|
|
vm.print_metadata()
|
|
captured = capsys.readouterr()
|
|
assert captured.out == Regex(r"┃ Keys +┃ Values +┃")
|
|
assert captured.out == Regex(r"│ +│ tag 3 +│")
|
|
assert captured.out == Regex(r"│ frontmatter_Key1 +│ author name +│")
|
|
|
|
new_metadata = {"added_key": ["added_value"], "frontmatter_Key2": ["new_value"]}
|
|
vm.add_metadata(new_metadata)
|
|
assert vm.dict == {
|
|
"added_key": ["added_value"],
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "new_value", "note"],
|
|
"intext_key": ["intext_key_value"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"shared_key2": ["shared_key2_value"],
|
|
"tags": ["tag 1", "tag 2", "tag 3"],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value"],
|
|
}
|
|
|
|
|
|
def test_vault_metadata_contains() -> None:
|
|
"""Test contains method."""
|
|
vm = VaultMetadata()
|
|
vm.add_metadata(METADATA)
|
|
assert vm.dict == {
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"intext_key": ["intext_key_value"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"shared_key2": ["shared_key2_value"],
|
|
"tags": ["tag 1", "tag 2", "tag 3"],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value"],
|
|
}
|
|
|
|
assert vm.contains("frontmatter_Key1") is True
|
|
assert vm.contains("frontmatter_Key2", "article") is True
|
|
assert vm.contains("frontmatter_Key3") is False
|
|
assert vm.contains("frontmatter_Key2", "no value") is False
|
|
assert vm.contains("1$", is_regex=True) is True
|
|
assert vm.contains("5$", is_regex=True) is False
|
|
assert vm.contains("tags", r"\d", is_regex=True) is True
|
|
assert vm.contains("tags", r"^\d", is_regex=True) is False
|
|
|
|
|
|
def test_vault_metadata_delete() -> None:
|
|
"""Test delete method."""
|
|
vm = VaultMetadata()
|
|
vm.add_metadata(METADATA)
|
|
assert vm.dict == {
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"intext_key": ["intext_key_value"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"shared_key2": ["shared_key2_value"],
|
|
"tags": ["tag 1", "tag 2", "tag 3"],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value"],
|
|
}
|
|
|
|
assert vm.delete("no key") is False
|
|
assert vm.delete("tags", "no value") is False
|
|
assert vm.delete("tags", "tag 2") is True
|
|
assert vm.dict["tags"] == ["tag 1", "tag 3"]
|
|
assert vm.delete("tags") is True
|
|
assert "tags" not in vm.dict
|
|
|
|
|
|
def test_vault_metadata_rename() -> None:
|
|
"""Test rename method."""
|
|
vm = VaultMetadata()
|
|
vm.add_metadata(METADATA)
|
|
assert vm.dict == {
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"intext_key": ["intext_key_value"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"shared_key2": ["shared_key2_value"],
|
|
"tags": ["tag 1", "tag 2", "tag 3"],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value"],
|
|
}
|
|
|
|
assert vm.rename("no key", "new key") is False
|
|
assert vm.rename("tags", "no tag", "new key") is False
|
|
assert vm.rename("tags", "tag 2", "new tag") is True
|
|
assert vm.dict["tags"] == ["new tag", "tag 1", "tag 3"]
|
|
assert vm.rename("tags", "old_tags") is True
|
|
assert vm.dict["old_tags"] == ["new tag", "tag 1", "tag 3"]
|
|
assert "tags" not in vm.dict
|
|
|
|
|
|
def test_frontmatter_create() -> None:
|
|
"""Test frontmatter creation."""
|
|
frontmatter = Frontmatter(INLINE_CONTENT)
|
|
assert frontmatter.dict == {}
|
|
|
|
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
|
assert frontmatter.dict == {
|
|
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
|
}
|
|
assert frontmatter.dict_original == {
|
|
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
|
}
|
|
|
|
|
|
def test_frontmatter_contains() -> None:
|
|
"""Test frontmatter contains."""
|
|
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
|
|
|
assert frontmatter.contains("frontmatter_Key1") is True
|
|
assert frontmatter.contains("frontmatter_Key2", "article") is True
|
|
assert frontmatter.contains("frontmatter_Key3") is False
|
|
assert frontmatter.contains("frontmatter_Key2", "no value") is False
|
|
|
|
assert frontmatter.contains(r"\d$", is_regex=True) is True
|
|
assert frontmatter.contains(r"^\d", is_regex=True) is False
|
|
assert frontmatter.contains("key", r"_\d", is_regex=True) is False
|
|
assert frontmatter.contains("key", r"\w\d_", is_regex=True) is True
|
|
|
|
|
|
def test_frontmatter_rename() -> None:
|
|
"""Test frontmatter rename."""
|
|
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
|
assert frontmatter.dict == {
|
|
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
|
}
|
|
|
|
assert frontmatter.rename("no key", "new key") is False
|
|
assert frontmatter.rename("tags", "no tag", "new key") is False
|
|
|
|
assert frontmatter.has_changes() is False
|
|
assert frontmatter.rename("tags", "tag_2", "new tag") is True
|
|
|
|
assert frontmatter.dict["tags"] == ["new tag", "tag_1", "📅/tag_3"]
|
|
assert frontmatter.rename("tags", "old_tags") is True
|
|
assert frontmatter.dict["old_tags"] == ["new tag", "tag_1", "📅/tag_3"]
|
|
assert "tags" not in frontmatter.dict
|
|
|
|
assert frontmatter.has_changes() is True
|
|
|
|
|
|
def test_frontmatter_delete() -> None:
|
|
"""Test Frontmatter delete method."""
|
|
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
|
assert frontmatter.dict == {
|
|
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"shared_key1": ["shared_key1_value"],
|
|
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
|
}
|
|
|
|
assert frontmatter.delete("no key") is False
|
|
assert frontmatter.delete("tags", "no value") is False
|
|
assert frontmatter.delete(r"\d{3}") is False
|
|
assert frontmatter.has_changes() is False
|
|
assert frontmatter.delete("tags", "tag_2") is True
|
|
assert frontmatter.dict["tags"] == ["tag_1", "📅/tag_3"]
|
|
assert frontmatter.delete("tags") is True
|
|
assert "tags" not in frontmatter.dict
|
|
assert frontmatter.has_changes() is True
|
|
assert frontmatter.delete("shared_key1", r"\w+") is True
|
|
assert frontmatter.dict["shared_key1"] == []
|
|
assert frontmatter.delete(r"\w.tter") is True
|
|
assert frontmatter.dict == {"shared_key1": []}
|
|
|
|
|
|
def test_frontmatter_yaml_conversion():
|
|
"""Test Frontmatter to_yaml method."""
|
|
new_frontmatter: str = """\
|
|
tags:
|
|
- tag_1
|
|
- tag_2
|
|
- 📅/tag_3
|
|
frontmatter_Key1: frontmatter_Key1_value
|
|
frontmatter_Key2:
|
|
- article
|
|
- note
|
|
shared_key1: shared_key1_value
|
|
"""
|
|
new_frontmatter_sorted: str = """\
|
|
frontmatter_Key1: frontmatter_Key1_value
|
|
frontmatter_Key2:
|
|
- article
|
|
- note
|
|
shared_key1: shared_key1_value
|
|
tags:
|
|
- tag_1
|
|
- tag_2
|
|
- 📅/tag_3
|
|
"""
|
|
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
|
assert frontmatter.to_yaml() == new_frontmatter
|
|
assert frontmatter.to_yaml(sort_keys=True) == new_frontmatter_sorted
|
|
|
|
|
|
def test_inline_metadata_create() -> None:
|
|
"""Test inline metadata creation."""
|
|
inline = InlineMetadata(FRONTMATTER_CONTENT)
|
|
assert inline.dict == {}
|
|
inline = InlineMetadata(INLINE_CONTENT)
|
|
assert inline.dict == {
|
|
"bold_key1": ["bold_key1_value"],
|
|
"bold_key2": ["bold_key2_value"],
|
|
"emoji_📅_key": ["emoji_📅_key_value"],
|
|
"in_text_key1": ["in_text_key1_value"],
|
|
"in_text_key2": ["in_text_key2_value"],
|
|
"link_key": ["link_key_value"],
|
|
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
|
"tag_key": ["tag_key_value"],
|
|
}
|
|
assert inline.dict_original == {
|
|
"bold_key1": ["bold_key1_value"],
|
|
"bold_key2": ["bold_key2_value"],
|
|
"emoji_📅_key": ["emoji_📅_key_value"],
|
|
"in_text_key1": ["in_text_key1_value"],
|
|
"in_text_key2": ["in_text_key2_value"],
|
|
"link_key": ["link_key_value"],
|
|
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
|
"tag_key": ["tag_key_value"],
|
|
}
|
|
|
|
|
|
def test_inline_contains() -> None:
|
|
"""Test inline metadata contains method."""
|
|
inline = InlineMetadata(INLINE_CONTENT)
|
|
|
|
assert inline.contains("bold_key1") is True
|
|
assert inline.contains("bold_key2", "bold_key2_value") is True
|
|
assert inline.contains("bold_key3") is False
|
|
assert inline.contains("bold_key2", "no value") is False
|
|
|
|
assert inline.contains(r"\w{4}_key", is_regex=True) is True
|
|
assert inline.contains(r"^\d", is_regex=True) is False
|
|
assert inline.contains("1$", r"\d_value", is_regex=True) is True
|
|
assert inline.contains("key", r"^\d_value", is_regex=True) is False
|
|
|
|
|
|
def test_inline_metadata_rename() -> None:
|
|
"""Test inline metadata rename."""
|
|
inline = InlineMetadata(INLINE_CONTENT)
|
|
assert inline.dict == {
|
|
"bold_key1": ["bold_key1_value"],
|
|
"bold_key2": ["bold_key2_value"],
|
|
"emoji_📅_key": ["emoji_📅_key_value"],
|
|
"in_text_key1": ["in_text_key1_value"],
|
|
"in_text_key2": ["in_text_key2_value"],
|
|
"link_key": ["link_key_value"],
|
|
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
|
"tag_key": ["tag_key_value"],
|
|
}
|
|
|
|
assert inline.rename("no key", "new key") is False
|
|
assert inline.rename("repeated_key", "no value", "new key") is False
|
|
assert inline.has_changes() is False
|
|
assert inline.rename("repeated_key", "repeated_key_value1", "new value") is True
|
|
assert inline.dict["repeated_key"] == ["new value", "repeated_key_value2"]
|
|
assert inline.rename("repeated_key", "old_key") is True
|
|
assert inline.dict["old_key"] == ["new value", "repeated_key_value2"]
|
|
assert "repeated_key" not in inline.dict
|
|
assert inline.has_changes() is True
|
|
|
|
|
|
def test_inline_metadata_delete() -> None:
|
|
"""Test inline metadata delete."""
|
|
inline = InlineMetadata(INLINE_CONTENT)
|
|
assert inline.dict == {
|
|
"bold_key1": ["bold_key1_value"],
|
|
"bold_key2": ["bold_key2_value"],
|
|
"emoji_📅_key": ["emoji_📅_key_value"],
|
|
"in_text_key1": ["in_text_key1_value"],
|
|
"in_text_key2": ["in_text_key2_value"],
|
|
"link_key": ["link_key_value"],
|
|
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
|
"tag_key": ["tag_key_value"],
|
|
}
|
|
|
|
assert inline.delete("no key") is False
|
|
assert inline.delete("repeated_key", "no value") is False
|
|
assert inline.has_changes() is False
|
|
assert inline.delete("repeated_key", "repeated_key_value1") is True
|
|
assert inline.dict["repeated_key"] == ["repeated_key_value2"]
|
|
assert inline.delete("repeated_key") is True
|
|
assert "repeated_key" not in inline.dict
|
|
assert inline.has_changes() is True
|
|
assert inline.delete(r"\d{3}") is False
|
|
assert inline.delete(r"bold_key\d") is True
|
|
assert inline.dict == {
|
|
"emoji_📅_key": ["emoji_📅_key_value"],
|
|
"in_text_key1": ["in_text_key1_value"],
|
|
"in_text_key2": ["in_text_key2_value"],
|
|
"link_key": ["link_key_value"],
|
|
"tag_key": ["tag_key_value"],
|
|
}
|
|
assert inline.delete("emoji_📅_key", ".*📅.*") is True
|
|
assert inline.dict == {
|
|
"emoji_📅_key": [],
|
|
"in_text_key1": ["in_text_key1_value"],
|
|
"in_text_key2": ["in_text_key2_value"],
|
|
"link_key": ["link_key_value"],
|
|
"tag_key": ["tag_key_value"],
|
|
}
|
|
|
|
|
|
def test_inline_tags_create() -> None:
|
|
"""Test inline tags creation."""
|
|
tags = InlineTags(FRONTMATTER_CONTENT)
|
|
tags.metadata_key
|
|
assert tags.list == []
|
|
|
|
tags = InlineTags(INLINE_CONTENT)
|
|
assert tags.list == [
|
|
"bold_tag",
|
|
"in_text_tag",
|
|
"inline_tag_top1",
|
|
"inline_tag_top2",
|
|
"tag_key_value",
|
|
]
|
|
assert tags.list_original == [
|
|
"bold_tag",
|
|
"in_text_tag",
|
|
"inline_tag_top1",
|
|
"inline_tag_top2",
|
|
"tag_key_value",
|
|
]
|
|
|
|
|
|
def test_inline_tags_contains() -> None:
|
|
"""Test inline tags contains."""
|
|
tags = InlineTags(INLINE_CONTENT)
|
|
assert tags.contains("bold_tag") is True
|
|
assert tags.contains("no tag") is False
|
|
|
|
assert tags.contains(r"\w_\w", is_regex=True) is True
|
|
assert tags.contains(r"\d_\d", is_regex=True) is False
|
|
|
|
|
|
def test_inline_tags_rename() -> None:
|
|
"""Test inline tags rename."""
|
|
tags = InlineTags(INLINE_CONTENT)
|
|
assert tags.list == [
|
|
"bold_tag",
|
|
"in_text_tag",
|
|
"inline_tag_top1",
|
|
"inline_tag_top2",
|
|
"tag_key_value",
|
|
]
|
|
|
|
assert tags.rename("no tag", "new tag") is False
|
|
assert tags.has_changes() is False
|
|
assert tags.rename("bold_tag", "new tag") is True
|
|
assert tags.list == [
|
|
"in_text_tag",
|
|
"inline_tag_top1",
|
|
"inline_tag_top2",
|
|
"new tag",
|
|
"tag_key_value",
|
|
]
|
|
assert tags.has_changes() is True
|
|
|
|
|
|
def test_inline_tags_delete() -> None:
|
|
"""Test inline tags delete."""
|
|
tags = InlineTags(INLINE_CONTENT)
|
|
assert tags.list == [
|
|
"bold_tag",
|
|
"in_text_tag",
|
|
"inline_tag_top1",
|
|
"inline_tag_top2",
|
|
"tag_key_value",
|
|
]
|
|
|
|
assert tags.delete("no tag") is False
|
|
assert tags.has_changes() is False
|
|
assert tags.delete("bold_tag") is True
|
|
assert tags.list == [
|
|
"in_text_tag",
|
|
"inline_tag_top1",
|
|
"inline_tag_top2",
|
|
"tag_key_value",
|
|
]
|
|
assert tags.has_changes() is True
|
|
assert tags.delete(r"\d{3}") is False
|
|
assert tags.delete(r"inline_tag_top\d") is True
|
|
assert tags.list == ["in_text_tag", "tag_key_value"]
|