mirror of
https://github.com/natelandau/obsidian-metadata.git
synced 2025-11-17 17:33:40 -05:00
feat: bulk update metadata from a CSV file
This commit is contained in:
@@ -58,7 +58,8 @@ def test_usage(capsys):
|
||||
assert captured.out == "USAGE | This prints in usage\n"
|
||||
|
||||
alerts.usage(
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua",
|
||||
width=80,
|
||||
)
|
||||
captured = capsys.readouterr()
|
||||
assert "USAGE | Lorem ipsum dolor sit amet" in captured.out
|
||||
|
||||
@@ -68,8 +68,13 @@ repeated_key:: repeated_key_value2
|
||||
"""
|
||||
|
||||
|
||||
def test_frontmatter_create() -> None:
|
||||
"""Test frontmatter creation."""
|
||||
def test_frontmatter_create_1() -> None:
|
||||
"""Test frontmatter creation.
|
||||
|
||||
GIVEN valid frontmatter content
|
||||
WHEN a Frontmatter object is created
|
||||
THEN parse the YAML frontmatter and add it to the object
|
||||
"""
|
||||
frontmatter = Frontmatter(INLINE_CONTENT)
|
||||
assert frontmatter.dict == {}
|
||||
|
||||
@@ -88,11 +93,11 @@ def test_frontmatter_create() -> None:
|
||||
}
|
||||
|
||||
|
||||
def test_frontmatter_create_error() -> None:
|
||||
def test_frontmatter_create_2() -> None:
|
||||
"""Test frontmatter creation error.
|
||||
|
||||
GIVEN frontmatter content
|
||||
WHEN frontmatter is invalid
|
||||
GIVEN invalid frontmatter content
|
||||
WHEN a Frontmatter object is created
|
||||
THEN raise ValueError
|
||||
"""
|
||||
fn = """---
|
||||
@@ -104,21 +109,118 @@ invalid = = "content"
|
||||
Frontmatter(fn)
|
||||
|
||||
|
||||
def test_frontmatter_contains() -> None:
|
||||
"""Test frontmatter contains."""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
def test_frontmatter_create_3():
|
||||
"""Test frontmatter creation error.
|
||||
|
||||
GIVEN empty frontmatter content
|
||||
WHEN a Frontmatter object is created
|
||||
THEN set the dict to an empty dict
|
||||
"""
|
||||
content = "---\n\n---"
|
||||
frontmatter = Frontmatter(content)
|
||||
assert frontmatter.dict == {}
|
||||
|
||||
|
||||
def test_frontmatter_create_4():
|
||||
"""Test frontmatter creation error.
|
||||
|
||||
GIVEN empty frontmatter content with a yaml marker
|
||||
WHEN a Frontmatter object is created
|
||||
THEN set the dict to an empty dict
|
||||
"""
|
||||
content = "---\n-\n---"
|
||||
frontmatter = Frontmatter(content)
|
||||
assert frontmatter.dict == {}
|
||||
|
||||
|
||||
def test_frontmatter_contains_1():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key
|
||||
THEN return True if the key is found
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains("frontmatter_Key1") is True
|
||||
|
||||
|
||||
def test_frontmatter_contains_2():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key
|
||||
THEN return False if the key is not found
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains("no_key") is False
|
||||
|
||||
|
||||
def test_frontmatter_contains_3():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key and a value
|
||||
THEN return True if the key and value is found
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains("frontmatter_Key2", "article") is True
|
||||
assert frontmatter.contains("frontmatter_Key3") is False
|
||||
|
||||
|
||||
def test_frontmatter_contains_4():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key and a value
|
||||
THEN return False if the key and value is not found
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains("frontmatter_Key2", "no value") is False
|
||||
|
||||
|
||||
def test_frontmatter_contains_5():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key regex
|
||||
THEN return True if a key matches the regex
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains(r"\d$", is_regex=True) is True
|
||||
|
||||
|
||||
def test_frontmatter_contains_6():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key regex
|
||||
THEN return False if no key matches the regex
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains(r"^\d", is_regex=True) is False
|
||||
assert frontmatter.contains("key", r"_\d", is_regex=True) is False
|
||||
|
||||
|
||||
def test_frontmatter_contains_7():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key and value regex
|
||||
THEN return True if a value matches the regex
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains("key", r"\w\d_", is_regex=True) is True
|
||||
|
||||
|
||||
def test_frontmatter_contains_8():
|
||||
"""Test frontmatter contains() method.
|
||||
|
||||
GIVEN a Frontmatter object
|
||||
WHEN the contains() method is called with a key and value regex
|
||||
THEN return False if a value does not match the regex
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.contains("key", r"_\d", is_regex=True) is False
|
||||
|
||||
|
||||
def test_frontmatter_add() -> None:
|
||||
"""Test frontmatter add."""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
@@ -233,6 +335,18 @@ def test_frontmatter_delete() -> None:
|
||||
assert frontmatter.dict == {"shared_key1": []}
|
||||
|
||||
|
||||
def test_frontmatter_delete_all():
|
||||
"""Test Frontmatter delete_all method.
|
||||
|
||||
GIVEN Frontmatter with multiple keys
|
||||
WHEN delete_all is called
|
||||
THEN all keys and values are deleted
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
frontmatter.delete_all()
|
||||
assert frontmatter.dict == {}
|
||||
|
||||
|
||||
def test_frontmatter_yaml_conversion():
|
||||
"""Test Frontmatter to_yaml method."""
|
||||
new_frontmatter: str = """\
|
||||
|
||||
@@ -229,16 +229,17 @@ def test_add_metadata_method_10(sample_note):
|
||||
"""Test add_metadata() method.
|
||||
|
||||
GIVEN a note object
|
||||
WHEN add_metadata() is with a new tag
|
||||
WHEN add_metadata() is called with a new tag
|
||||
THEN the tag is added to the InlineTags object and the file content
|
||||
"""
|
||||
note = Note(note_path=sample_note)
|
||||
assert "new_tag" not in note.inline_tags.list
|
||||
assert "new_tag2" not in note.inline_tags.list
|
||||
assert (
|
||||
note.add_metadata(MetadataType.TAGS, value="new_tag", location=InsertLocation.TOP) is True
|
||||
note.add_metadata(MetadataType.TAGS, value="new_tag2", location=InsertLocation.BOTTOM)
|
||||
is True
|
||||
)
|
||||
assert "new_tag" in note.inline_tags.list
|
||||
assert "#new_tag" in note.file_content
|
||||
assert "new_tag2" in note.inline_tags.list
|
||||
assert "#new_tag2" in note.file_content
|
||||
|
||||
|
||||
def test_commit_1(sample_note, tmp_path) -> None:
|
||||
@@ -313,6 +314,24 @@ def test_contains_metadata(sample_note) -> None:
|
||||
assert note.contains_metadata(r"bottom_key\d$", r"bottom_key\d_value", is_regex=True) is True
|
||||
|
||||
|
||||
def test_delete_all_metadata(sample_note):
|
||||
"""Test delete_all_metadata() method.
|
||||
|
||||
GIVEN a note object
|
||||
WHEN delete_all_metadata() is called
|
||||
THEN all tags, frontmatter, and inline metadata are deleted
|
||||
"""
|
||||
note = Note(note_path=sample_note)
|
||||
note.delete_all_metadata()
|
||||
assert note.inline_tags.list == []
|
||||
assert note.frontmatter.dict == {}
|
||||
assert note.inline_metadata.dict == {}
|
||||
assert note.file_content == Regex("consequat. Duis")
|
||||
assert "codeblock_key:: some text" in note.file_content
|
||||
assert "#ffffff" in note.file_content
|
||||
assert "---" not in note.file_content
|
||||
|
||||
|
||||
def test_delete_inline_tag(sample_note) -> None:
|
||||
"""Test delete_inline_tag method.
|
||||
|
||||
|
||||
@@ -431,6 +431,38 @@ def test_export_json(tmp_path, test_vault):
|
||||
assert '"frontmatter": {' in export_file.read_text()
|
||||
|
||||
|
||||
def test_export_notes_to_csv_1(tmp_path, test_vault):
|
||||
"""Test export_notes_to_csv() method.
|
||||
|
||||
GIVEN a vault object
|
||||
WHEN the export_notes_to_csv method is called with a path
|
||||
THEN the notes are exported to a CSV file
|
||||
"""
|
||||
vault = Vault(config=test_vault)
|
||||
export_file = Path(f"{tmp_path}/export.csv")
|
||||
vault.export_notes_to_csv(path=export_file)
|
||||
assert export_file.exists() is True
|
||||
assert "path,type,key,value" in export_file.read_text()
|
||||
assert "test1.md,frontmatter,shared_key1,shared_key1_value" in export_file.read_text()
|
||||
assert "test1.md,inline_metadata,shared_key1,shared_key1_value" in export_file.read_text()
|
||||
assert "test1.md,tag,,shared_tag" in export_file.read_text()
|
||||
assert "test1.md,frontmatter,tags,📅/frontmatter_tag3" in export_file.read_text()
|
||||
assert "test1.md,inline_metadata,key📅,📅_key_value" in export_file.read_text()
|
||||
|
||||
|
||||
def test_export_notes_to_csv_2(test_vault):
|
||||
"""Test export_notes_to_csv() method.
|
||||
|
||||
GIVEN a vault object
|
||||
WHEN the export_notes_to_csv method is called with a path where the parent directory does not exist
|
||||
THEN an error is raised
|
||||
"""
|
||||
vault = Vault(config=test_vault)
|
||||
export_file = Path("/I/do/not/exist/export.csv")
|
||||
with pytest.raises(typer.Exit):
|
||||
vault.export_notes_to_csv(path=export_file)
|
||||
|
||||
|
||||
def test_get_filtered_notes_1(sample_vault) -> None:
|
||||
"""Test filtering notes.
|
||||
|
||||
@@ -688,3 +720,60 @@ def test_transpose_metadata(test_vault) -> None:
|
||||
)
|
||||
== 0
|
||||
)
|
||||
|
||||
|
||||
def test_update_from_dict_1(test_vault):
|
||||
"""Test update_from_dict() method.
|
||||
|
||||
GIVEN a vault object and an update dictionary
|
||||
WHEN no dictionary keys match paths in the vault
|
||||
THEN no notes are updated and 0 is returned
|
||||
"""
|
||||
vault = Vault(config=test_vault)
|
||||
update_dict = {
|
||||
"path1": {"type": "frontmatter", "key": "new_key", "value": "new_value"},
|
||||
"path2": {"type": "frontmatter", "key": "new_key", "value": "new_value"},
|
||||
}
|
||||
|
||||
assert vault.update_from_dict(update_dict) == 0
|
||||
assert vault.get_changed_notes() == []
|
||||
|
||||
|
||||
def test_update_from_dict_2(test_vault):
|
||||
"""Test update_from_dict() method.
|
||||
|
||||
GIVEN a vault object and an update dictionary
|
||||
WHEN the dictionary is empty
|
||||
THEN no notes are updated and 0 is returned
|
||||
"""
|
||||
vault = Vault(config=test_vault)
|
||||
update_dict = {}
|
||||
|
||||
assert vault.update_from_dict(update_dict) == 0
|
||||
assert vault.get_changed_notes() == []
|
||||
|
||||
|
||||
def test_update_from_dict_3(test_vault):
|
||||
"""Test update_from_dict() method.
|
||||
|
||||
GIVEN a vault object and an update dictionary
|
||||
WHEN a dictionary key matches a path in the vault
|
||||
THEN the note is updated to match the dictionary values
|
||||
"""
|
||||
vault = Vault(config=test_vault)
|
||||
|
||||
update_dict = {
|
||||
"test1.md": [
|
||||
{"type": "frontmatter", "key": "new_key", "value": "new_value"},
|
||||
{"type": "inline_metadata", "key": "new_key2", "value": "new_value"},
|
||||
{"type": "tags", "key": "", "value": "new_tag"},
|
||||
]
|
||||
}
|
||||
assert vault.update_from_dict(update_dict) == 1
|
||||
assert vault.get_changed_notes()[0].note_path.name == "test1.md"
|
||||
assert vault.get_changed_notes()[0].frontmatter.dict == {"new_key": ["new_value"]}
|
||||
assert vault.get_changed_notes()[0].inline_metadata.dict == {"new_key2": ["new_value"]}
|
||||
assert vault.get_changed_notes()[0].inline_tags.list == ["new_tag"]
|
||||
assert vault.metadata.frontmatter == {"new_key": ["new_value"]}
|
||||
assert vault.metadata.inline_metadata == {"new_key2": ["new_value"]}
|
||||
assert vault.metadata.tags == ["new_tag"]
|
||||
|
||||
Reference in New Issue
Block a user