refactor: cleanup rename and delete from dict functions

This commit is contained in:
Nathaniel Landau
2023-03-21 17:15:36 -04:00
parent 696e19f3e2
commit fa568de369
9 changed files with 1632 additions and 558 deletions

View File

@@ -5,12 +5,14 @@ from obsidian_metadata._utils.alerts import LoggerManager
from obsidian_metadata._utils.utilities import (
clean_dictionary,
clear_screen,
delete_from_dict,
dict_contains,
dict_keys_to_lower,
dict_values_to_lists_strings,
docstring_parameter,
merge_dictionaries,
remove_markdown_sections,
rename_in_dict,
validate_csv_bulk_imports,
version_callback,
)
@@ -19,12 +21,14 @@ __all__ = [
"alerts",
"clean_dictionary",
"clear_screen",
"delete_from_dict",
"dict_contains",
"dict_keys_to_lower",
"dict_values_to_lists_strings",
"docstring_parameter",
"LoggerManager",
"merge_dictionaries",
"rename_in_dict",
"remove_markdown_sections",
"validate_csv_bulk_imports",
"version_callback",

View File

@@ -1,4 +1,5 @@
"""Utility functions."""
import copy
import csv
import re
from os import name, system
@@ -118,6 +119,48 @@ def dict_values_to_lists_strings(
return new_dict
def delete_from_dict( # noqa: C901
dictionary: dict, key: str, value: str = None, is_regex: bool = False
) -> dict:
"""Delete a key or a value from a dictionary.
Args:
dictionary (dict): Dictionary to delete from
is_regex (bool, optional): Whether the key is a regex. Defaults to False.
key (str): Key to delete
value (str, optional): Value to delete. Defaults to None.
Returns:
dict: Dictionary without the key
"""
dictionary = copy.deepcopy(dictionary)
if value is None:
if is_regex:
return {k: v for k, v in dictionary.items() if not re.search(key, str(k))}
return {k: v for k, v in dictionary.items() if k != key}
if is_regex:
keys_to_delete = []
for _key in dictionary:
if re.search(key, str(_key)):
if isinstance(dictionary[_key], list):
dictionary[_key] = [v for v in dictionary[_key] if not re.search(value, v)]
elif isinstance(dictionary[_key], str) and re.search(value, dictionary[_key]):
keys_to_delete.append(_key)
for key in keys_to_delete:
dictionary.pop(key)
elif key in dictionary and isinstance(dictionary[key], list):
dictionary[key] = [v for v in dictionary[key] if v != value]
elif key in dictionary and dictionary[key] == value:
dictionary.pop(key)
return dictionary
def docstring_parameter(*sub: Any) -> Any:
"""Replace variables within docstrings.
@@ -167,6 +210,31 @@ def merge_dictionaries(dict1: dict, dict2: dict) -> dict:
return dict(sorted(dict1.items()))
def rename_in_dict(
dictionary: dict[str, list[str]], key: str, value_1: str, value_2: str = None
) -> dict:
"""Rename a key or a value in a dictionary who's values are lists of strings.
Args:
dictionary (dict): Dictionary to rename in.
key (str): Key to check.
value_1 (str): `With value_2` this is the value to rename. If `value_2` is None this is the renamed key
value_2 (str, Optional): New value.
Returns:
dict: Dictionary with renamed key or value
"""
dictionary = copy.deepcopy(dictionary)
if value_2 is None:
if key in dictionary and value_1 not in dictionary:
dictionary[value_1] = dictionary.pop(key)
elif key in dictionary and value_1 in dictionary[key]:
dictionary[key] = sorted({value_2 if x == value_1 else x for x in dictionary[key]})
return dictionary
def remove_markdown_sections(
text: str,
strip_codeblocks: bool = False,

View File

@@ -10,10 +10,12 @@ from ruamel.yaml import YAML
from obsidian_metadata._utils import (
clean_dictionary,
delete_from_dict,
dict_contains,
dict_values_to_lists_strings,
merge_dictionaries,
remove_markdown_sections,
rename_in_dict,
)
from obsidian_metadata._utils.console import console
from obsidian_metadata.models import Patterns # isort: ignore
@@ -24,7 +26,14 @@ INLINE_TAG_KEY: str = "inline_tag"
class VaultMetadata:
"""Representation of all Metadata in the Vault."""
"""Representation of all Metadata in the Vault.
Attributes:
dict (dict): Dictionary of all frontmatter and inline metadata. Does not include tags.
frontmatter (dict): Dictionary of all frontmatter metadata.
inline_metadata (dict): Dictionary of all inline metadata.
tags (list): List of all tags.
"""
def __init__(self) -> None:
self.dict: dict[str, list[str]] = {}
@@ -59,7 +68,7 @@ class VaultMetadata:
self.tags.extend(metadata)
self.tags = sorted({s.strip("#") for s in self.tags})
def contains( # noqa: PLR0911
def contains(
self, area: MetadataType, key: str = None, value: str = None, is_regex: bool = False
) -> bool:
"""Check if a key and/or a value exists in the metadata.
@@ -82,13 +91,7 @@ class VaultMetadata:
match area:
case MetadataType.ALL:
if dict_contains(self.dict, key, value, is_regex):
return True
if key is None and value is not None:
if is_regex:
return any(re.search(value, tag) for tag in self.tags)
return value in self.tags
return dict_contains(self.dict, key, value, is_regex)
case MetadataType.FRONTMATTER:
return dict_contains(self.frontmatter, key, value, is_regex)
case MetadataType.INLINE:
@@ -102,10 +105,8 @@ class VaultMetadata:
return any(re.search(value, tag) for tag in self.tags)
return value in self.tags
return False
def delete(self, key: str, value_to_delete: str = None) -> bool:
"""Delete a key or a key's value from the metadata. Regex is supported to allow deleting more than one key or value.
"""Delete a key or a value from the VaultMetadata dict object. Regex is supported to allow deleting more than one key or value.
Args:
key (str): Key to check.
@@ -114,17 +115,12 @@ class VaultMetadata:
Returns:
bool: True if a value was deleted
"""
new_dict = copy.deepcopy(self.dict)
if value_to_delete is None:
for _k in list(new_dict):
if re.search(key, _k):
del new_dict[_k]
else:
for _k, _v in new_dict.items():
if re.search(key, _k):
new_values = [x for x in _v if not re.search(value_to_delete, x)]
new_dict[_k] = sorted(new_values)
new_dict = delete_from_dict(
dictionary=self.dict,
key=key,
value=value_to_delete,
is_regex=True,
)
if new_dict != self.dict:
self.dict = dict(new_dict)
@@ -138,28 +134,24 @@ class VaultMetadata:
Args:
area (MetadataType): Type of metadata to print
"""
dict_to_print: dict[str, list[str]] = None
list_to_print: list[str] = None
dict_to_print = None
list_to_print = None
match area:
case MetadataType.INLINE:
dict_to_print = self.inline_metadata.copy()
dict_to_print = self.inline_metadata
header = "All inline metadata"
case MetadataType.FRONTMATTER:
dict_to_print = self.frontmatter.copy()
dict_to_print = self.frontmatter
header = "All frontmatter"
case MetadataType.TAGS:
list_to_print = []
for tag in self.tags:
list_to_print.append(f"#{tag}")
list_to_print = [f"#{x}" for x in self.tags]
header = "All inline tags"
case MetadataType.KEYS:
list_to_print = sorted(self.dict.keys())
header = "All Keys"
case MetadataType.ALL:
dict_to_print = self.dict.copy()
list_to_print = []
for tag in self.tags:
list_to_print.append(f"#{tag}")
dict_to_print = self.dict
list_to_print = [f"#{x}" for x in self.tags]
header = "All metadata"
if dict_to_print is not None:
@@ -189,19 +181,14 @@ class VaultMetadata:
key (str): Key to check.
value_1 (str): `With value_2` this is the value to rename. If `value_2` is None this is the renamed key
value_2 (str, Optional): New value.
bypass_check (bool, optional): Bypass the check if the key exists. Defaults to False.
Returns:
bool: True if a value was renamed
"""
if value_2 is None:
if key in self.dict and value_1 not in self.dict:
self.dict[value_1] = self.dict.pop(key)
return True
return False
new_dict = rename_in_dict(dictionary=self.dict, key=key, value_1=value_1, value_2=value_2)
if key in self.dict and value_1 in self.dict[key]:
self.dict[key] = sorted({value_2 if x == value_1 else x for x in self.dict[key]})
if new_dict != self.dict:
self.dict = dict(new_dict)
return True
return False
@@ -312,17 +299,12 @@ class Frontmatter:
Returns:
bool: True if a value was deleted
"""
new_dict = copy.deepcopy(self.dict)
if value_to_delete is None:
for _k in list(new_dict):
if re.search(key, _k):
del new_dict[_k]
else:
for _k, _v in new_dict.items():
if re.search(key, _k):
new_values = [x for x in _v if not re.search(value_to_delete, x)]
new_dict[_k] = sorted(new_values)
new_dict = delete_from_dict(
dictionary=self.dict,
key=key,
value=value_to_delete,
is_regex=True,
)
if new_dict != self.dict:
self.dict = dict(new_dict)
@@ -353,14 +335,10 @@ class Frontmatter:
Returns:
bool: True if a value was renamed
"""
if value_2 is None:
if key in self.dict and value_1 not in self.dict:
self.dict[value_1] = self.dict.pop(key)
return True
return False
new_dict = rename_in_dict(dictionary=self.dict, key=key, value_1=value_1, value_2=value_2)
if key in self.dict and value_1 in self.dict[key]:
self.dict[key] = sorted({value_2 if x == value_1 else x for x in self.dict[key]})
if new_dict != self.dict:
self.dict = dict(new_dict)
return True
return False
@@ -491,17 +469,12 @@ class InlineMetadata:
Returns:
bool: True if a value was deleted
"""
new_dict = dict(self.dict)
if value_to_delete is None:
for _k in list(new_dict):
if re.search(key, _k):
del new_dict[_k]
else:
for _k, _v in new_dict.items():
if re.search(key, _k):
new_values = [x for x in _v if not re.search(value_to_delete, x)]
new_dict[_k] = sorted(new_values)
new_dict = delete_from_dict(
dictionary=self.dict,
key=key,
value=value_to_delete,
is_regex=True,
)
if new_dict != self.dict:
self.dict = dict(new_dict)
@@ -528,14 +501,10 @@ class InlineMetadata:
Returns:
bool: True if a value was renamed
"""
if value_2 is None:
if key in self.dict and value_1 not in self.dict:
self.dict[value_1] = self.dict.pop(key)
return True
return False
new_dict = rename_in_dict(dictionary=self.dict, key=key, value_1=value_1, value_2=value_2)
if key in self.dict and value_1 in self.dict[key]:
self.dict[key] = sorted({value_2 if x == value_1 else x for x in self.dict[key]})
if new_dict != self.dict:
self.dict = dict(new_dict)
return True
return False
@@ -580,32 +549,34 @@ class InlineTags:
"""Add a new inline tag.
Args:
new_tag (str): Tag to add.
new_tag (str, list[str]): Tag to add.
Returns:
bool: True if a tag was added.
"""
added_tag = False
if isinstance(new_tag, list):
for _tag in new_tag:
if _tag.startswith("#"):
_tag = _tag[1:]
if _tag in self.list:
return False
new_list = self.list.copy()
new_list.append(_tag)
self.list = sorted(new_list)
return True
else:
if new_tag.startswith("#"):
new_tag = new_tag[1:]
if new_tag in self.list:
return False
new_list = self.list.copy()
new_list.append(new_tag)
self.list = sorted(new_list)
return True
continue
self.list.append(_tag)
added_tag = True
return False
if added_tag:
self.list = sorted(self.list)
return True
return False
if new_tag.startswith("#"):
new_tag = new_tag[1:]
if new_tag in self.list:
return False
new_list = self.list.copy()
new_list.append(new_tag)
self.list = sorted(new_list)
return True
def contains(self, tag: str, is_regex: bool = False) -> bool:
"""Check if a tag exists in the metadata.
@@ -653,13 +624,13 @@ class InlineTags:
"""Replace an inline tag with another string.
Args:
old_tag (str): `With value_2` this is the value to rename. If `value_2` is None this is the renamed key
new_tag (str, Optional): New value.
old_tag (str): `With value_2` this is the value to rename.
new_tag (str): New value
Returns:
bool: True if a value was renamed
"""
if old_tag in self.list:
self.list = sorted([new_tag if i == old_tag else i for i in self.list])
if old_tag in self.list and new_tag is not None and new_tag:
self.list = sorted({new_tag if i == old_tag else i for i in self.list})
return True
return False

View File

@@ -47,7 +47,7 @@ repeated_key:: repeated_key_value2
"""
def test_frontmatter_create_1() -> None:
def test_create_1() -> None:
"""Test frontmatter creation.
GIVEN valid frontmatter content
@@ -72,7 +72,7 @@ def test_frontmatter_create_1() -> None:
}
def test_frontmatter_create_2() -> None:
def test_create_2() -> None:
"""Test frontmatter creation error.
GIVEN invalid frontmatter content
@@ -88,7 +88,7 @@ invalid = = "content"
Frontmatter(fn)
def test_frontmatter_create_3():
def test_create_3():
"""Test frontmatter creation error.
GIVEN empty frontmatter content
@@ -100,7 +100,7 @@ def test_frontmatter_create_3():
assert frontmatter.dict == {}
def test_frontmatter_create_4():
def test_create_4():
"""Test frontmatter creation error.
GIVEN empty frontmatter content with a yaml marker
@@ -112,7 +112,7 @@ def test_frontmatter_create_4():
assert frontmatter.dict == {}
def test_frontmatter_add_1():
def test_add_1():
"""Test frontmatter add() method.
GIVEN a Frontmatter object
@@ -124,7 +124,7 @@ def test_frontmatter_add_1():
assert frontmatter.add("frontmatter_Key1") is False
def test_frontmatter_add_2():
def test_add_2():
"""Test frontmatter add() method.
GIVEN a Frontmatter object
@@ -135,7 +135,7 @@ def test_frontmatter_add_2():
assert frontmatter.add("frontmatter_Key1", "frontmatter_Key1_value") is False
def test_frontmatter_add_3():
def test_add_3():
"""Test frontmatter add() method.
GIVEN a Frontmatter object
@@ -147,7 +147,7 @@ def test_frontmatter_add_3():
assert "added_key" in frontmatter.dict
def test_frontmatter_add_4():
def test_add_4():
"""Test frontmatter add() method.
GIVEN a Frontmatter object
@@ -159,7 +159,7 @@ def test_frontmatter_add_4():
assert frontmatter.dict["added_key"] == ["added_value"]
def test_frontmatter_add_5():
def test_add_5():
"""Test frontmatter add() method.
GIVEN a Frontmatter object
@@ -171,7 +171,7 @@ def test_frontmatter_add_5():
assert frontmatter.dict["frontmatter_Key1"] == ["frontmatter_Key1_value", "new_value"]
def test_frontmatter_add_6():
def test_add_6():
"""Test frontmatter add() method.
GIVEN a Frontmatter object
@@ -187,7 +187,7 @@ def test_frontmatter_add_6():
]
def test_frontmatter_add_7():
def test_add_7():
"""Test frontmatter add() method.
GIVEN a Frontmatter object
@@ -206,7 +206,7 @@ def test_frontmatter_add_7():
]
def test_frontmatter_contains_1():
def test_contains_1():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -217,7 +217,7 @@ def test_frontmatter_contains_1():
assert frontmatter.contains("frontmatter_Key1") is True
def test_frontmatter_contains_2():
def test_contains_2():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -228,7 +228,7 @@ def test_frontmatter_contains_2():
assert frontmatter.contains("no_key") is False
def test_frontmatter_contains_3():
def test_contains_3():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -239,7 +239,7 @@ def test_frontmatter_contains_3():
assert frontmatter.contains("frontmatter_Key2", "article") is True
def test_frontmatter_contains_4():
def test_contains_4():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -250,7 +250,7 @@ def test_frontmatter_contains_4():
assert frontmatter.contains("frontmatter_Key2", "no value") is False
def test_frontmatter_contains_5():
def test_contains_5():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -261,7 +261,7 @@ def test_frontmatter_contains_5():
assert frontmatter.contains(r"\d$", is_regex=True) is True
def test_frontmatter_contains_6():
def test_contains_6():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -272,7 +272,7 @@ def test_frontmatter_contains_6():
assert frontmatter.contains(r"^\d", is_regex=True) is False
def test_frontmatter_contains_7():
def test_contains_7():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -283,7 +283,7 @@ def test_frontmatter_contains_7():
assert frontmatter.contains("key", r"\w\d_", is_regex=True) is True
def test_frontmatter_contains_8():
def test_contains_8():
"""Test frontmatter contains() method.
GIVEN a Frontmatter object
@@ -294,7 +294,7 @@ def test_frontmatter_contains_8():
assert frontmatter.contains("key", r"_\d", is_regex=True) is False
def test_frontmatter_delete_1():
def test_delete_1():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -305,7 +305,7 @@ def test_frontmatter_delete_1():
assert frontmatter.delete("no key") is False
def test_frontmatter_delete_2():
def test_delete_2():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -316,7 +316,7 @@ def test_frontmatter_delete_2():
assert frontmatter.delete("tags", "no value") is False
def test_frontmatter_delete_3():
def test_delete_3():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -327,7 +327,7 @@ def test_frontmatter_delete_3():
assert frontmatter.delete(r"\d{3}") is False
def test_frontmatter_delete_4():
def test_delete_4():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -338,7 +338,7 @@ def test_frontmatter_delete_4():
assert frontmatter.delete("tags", r"\d{5}") is False
def test_frontmatter_delete_5():
def test_delete_5():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -351,7 +351,7 @@ def test_frontmatter_delete_5():
assert "tags" in frontmatter.dict
def test_frontmatter_delete_6():
def test_delete_6():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -363,7 +363,7 @@ def test_frontmatter_delete_6():
assert "tags" not in frontmatter.dict
def test_frontmatter_delete_7():
def test_delete_7():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -376,7 +376,7 @@ def test_frontmatter_delete_7():
assert "frontmatter_Key2" not in frontmatter.dict
def test_frontmatter_delete_8():
def test_delete_8():
"""Test frontmatter delete() method.
GIVEN a Frontmatter object
@@ -390,7 +390,7 @@ def test_frontmatter_delete_8():
assert "tag_1" in frontmatter.dict["tags"]
def test_frontmatter_delete_all():
def test_delete_all():
"""Test Frontmatter delete_all method.
GIVEN Frontmatter with multiple keys
@@ -402,7 +402,7 @@ def test_frontmatter_delete_all():
assert frontmatter.dict == {}
def test_frontmatter_has_changes_1():
def test_has_changes_1():
"""Test frontmatter has_changes() method.
GIVEN a Frontmatter object
@@ -413,7 +413,7 @@ def test_frontmatter_has_changes_1():
assert frontmatter.has_changes() is False
def test_frontmatter_has_changes_2():
def test_has_changes_2():
"""Test frontmatter has_changes() method.
GIVEN a Frontmatter object
@@ -425,7 +425,7 @@ def test_frontmatter_has_changes_2():
assert frontmatter.has_changes() is True
def test_frontmatter_rename_1():
def test_rename_1():
"""Test frontmatter rename() method.
GIVEN a Frontmatter object
@@ -436,7 +436,7 @@ def test_frontmatter_rename_1():
assert frontmatter.rename("no key", "new key") is False
def test_frontmatter_rename_2():
def test_rename_2():
"""Test frontmatter rename() method.
GIVEN a Frontmatter object
@@ -447,7 +447,7 @@ def test_frontmatter_rename_2():
assert frontmatter.rename("tags", "no tag", "new key") is False
def test_frontmatter_rename_3():
def test_rename_3():
"""Test frontmatter rename() method.
GIVEN a Frontmatter object
@@ -460,7 +460,7 @@ def test_frontmatter_rename_3():
assert frontmatter.dict["new key"] == ["frontmatter_Key1_value"]
def test_frontmatter_rename_4():
def test_rename_4():
"""Test frontmatter rename() method.
GIVEN a Frontmatter object
@@ -473,7 +473,7 @@ def test_frontmatter_rename_4():
assert "new tag" in frontmatter.dict["tags"]
def test_frontmatter_rename_5():
def test_rename_5():
"""Test frontmatter rename() method.
GIVEN a Frontmatter object
@@ -486,7 +486,7 @@ def test_frontmatter_rename_5():
assert frontmatter.dict["tags"] == ["tag_2", "📅/tag_3"]
def test_frontmatter_to_yaml_1():
def test_to_yaml_1():
"""Test Frontmatter to_yaml method.
GIVEN a dictionary
@@ -508,7 +508,7 @@ shared_key1: shared_key1_value
assert frontmatter.to_yaml() == new_frontmatter
def test_frontmatter_to_yaml_2():
def test_to_yaml_2():
"""Test Frontmatter to_yaml method.
GIVEN a dictionary

View File

@@ -77,7 +77,7 @@ def test__grab_inline_metadata_2():
}
def test_inline_metadata_add_1():
def test_add_1():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
@@ -88,7 +88,7 @@ def test_inline_metadata_add_1():
assert inline.add("key1") is False
def test_inline_metadata_add_2():
def test_add_2():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
@@ -99,7 +99,7 @@ def test_inline_metadata_add_2():
assert inline.add("key1", "value1") is False
def test_inline_metadata_add_3():
def test_add_3():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
@@ -111,7 +111,7 @@ def test_inline_metadata_add_3():
assert "added_key" in inline.dict
def test_inline_metadata_add_4():
def test_add_4():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
@@ -123,7 +123,7 @@ def test_inline_metadata_add_4():
assert inline.dict["added_key"] == ["added_value"]
def test_inline_metadata_add_5():
def test_add_5():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
@@ -135,7 +135,7 @@ def test_inline_metadata_add_5():
assert inline.dict["key1"] == ["value1", "value2", "value3", "new_value"]
def test_inline_metadata_add_6():
def test_add_6():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
@@ -147,7 +147,7 @@ def test_inline_metadata_add_6():
assert inline.dict["key2"] == ["new_value", "new_value2", "value1"]
def test_inline_metadata_add_7():
def test_add_7():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
@@ -159,7 +159,19 @@ def test_inline_metadata_add_7():
assert inline.dict["key1"] == ["new_value", "new_value2", "value1", "value2", "value3"]
def test_inline_metadata_contains_1():
def test_add_8():
"""Test InlineMetadata add() method.
GIVEN a InlineMetadata object
WHEN the add() method is called with a new key and a list of values
THEN return True and add the new values to the dict
"""
inline = InlineMetadata(INLINE_CONTENT)
assert inline.add("new_key", ["value1", "new_value", "new_value2"]) is True
assert inline.dict["new_key"] == ["value1", "new_value", "new_value2"]
def test_contains_1():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -170,7 +182,7 @@ def test_inline_metadata_contains_1():
assert inline.contains("key1") is True
def test_inline_metadata_contains_2():
def test_contains_2():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -181,7 +193,7 @@ def test_inline_metadata_contains_2():
assert inline.contains("no_key") is False
def test_inline_metadata_contains_3():
def test_contains_3():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -192,7 +204,7 @@ def test_inline_metadata_contains_3():
assert inline.contains("key1", "value1") is True
def test_inline_metadata_contains_4():
def test_contains_4():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -203,7 +215,7 @@ def test_inline_metadata_contains_4():
assert inline.contains("key1", "no value") is False
def test_inline_metadata_contains_5():
def test_contains_5():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -214,7 +226,7 @@ def test_inline_metadata_contains_5():
assert inline.contains(r"\d$", is_regex=True) is True
def test_inline_metadata_contains_6():
def test_contains_6():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -225,7 +237,7 @@ def test_inline_metadata_contains_6():
assert inline.contains(r"^\d", is_regex=True) is False
def test_inline_metadata_contains_7():
def test_contains_7():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -236,7 +248,7 @@ def test_inline_metadata_contains_7():
assert inline.contains(r"key\d", r"\w\d", is_regex=True) is True
def test_inline_metadata_contains_8():
def test_contains_8():
"""Test InlineMetadata contains() method.
GIVEN a InlineMetadata object
@@ -247,7 +259,7 @@ def test_inline_metadata_contains_8():
assert inline.contains("key1", r"_\d", is_regex=True) is False
def test_inline_metadata_delete_1():
def test_delete_1():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -258,7 +270,7 @@ def test_inline_metadata_delete_1():
assert inline.delete("no key") is False
def test_inline_metadata_delete_2():
def test_delete_2():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -269,7 +281,7 @@ def test_inline_metadata_delete_2():
assert inline.delete("key1", "no value") is False
def test_inline_metadata_delete_3():
def test_delete_3():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -280,7 +292,7 @@ def test_inline_metadata_delete_3():
assert inline.delete(r"\d{3}") is False
def test_inline_metadata_delete_4():
def test_delete_4():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -291,7 +303,7 @@ def test_inline_metadata_delete_4():
assert inline.delete("key1", r"\d{5}") is False
def test_inline_metadata_delete_5():
def test_delete_5():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -304,7 +316,7 @@ def test_inline_metadata_delete_5():
assert "key1" in inline.dict
def test_inline_metadata_delete_6():
def test_delete_6():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -316,7 +328,7 @@ def test_inline_metadata_delete_6():
assert "key1" not in inline.dict
def test_inline_metadata_delete_7():
def test_delete_7():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -329,7 +341,7 @@ def test_inline_metadata_delete_7():
assert "key2" not in inline.dict
def test_inline_metadata_delete_8():
def test_delete_8():
"""Test InlineMetadata delete() method.
GIVEN a InlineMetadata object
@@ -343,7 +355,7 @@ def test_inline_metadata_delete_8():
assert "value3" not in inline.dict["key1"]
def test_inline_metadata_has_changes_1():
def test_has_changes_1():
"""Test InlineMetadata has_changes() method.
GIVEN a InlineMetadata object
@@ -354,7 +366,7 @@ def test_inline_metadata_has_changes_1():
assert inline.has_changes() is False
def test_inline_metadata_has_changes_2():
def test_has_changes_2():
"""Test InlineMetadata has_changes() method.
GIVEN a InlineMetadata object
@@ -366,7 +378,7 @@ def test_inline_metadata_has_changes_2():
assert inline.has_changes() is True
def test_inline_metadata_rename_1():
def test_rename_1():
"""Test InlineMetadata rename() method.
GIVEN a InlineMetadata object
@@ -377,7 +389,7 @@ def test_inline_metadata_rename_1():
assert inline.rename("no key", "new key") is False
def test_inline_metadata_rename_2():
def test_rename_2():
"""Test InlineMetadata rename() method.
GIVEN a InlineMetadata object
@@ -388,7 +400,7 @@ def test_inline_metadata_rename_2():
assert inline.rename("key1", "no value", "new value") is False
def test_inline_metadata_rename_3():
def test_rename_3():
"""Test InlineMetadata rename() method.
GIVEN a InlineMetadata object
@@ -401,7 +413,7 @@ def test_inline_metadata_rename_3():
assert inline.dict["new key"] == ["value1", "value2", "value3"]
def test_inline_metadata_rename_4():
def test_rename_4():
"""Test InlineMetadata rename() method.
GIVEN a InlineMetadata object
@@ -414,7 +426,7 @@ def test_inline_metadata_rename_4():
assert "new value" in inline.dict["key1"]
def test_inline_metadata_rename_5():
def test_rename_5():
"""Test InlineMetadata rename() method.
GIVEN a InlineMetadata object

367
tests/metadata_tags_test.py Normal file
View File

@@ -0,0 +1,367 @@
# type: ignore
"""Test inline tags from metadata.py."""
from obsidian_metadata.models.metadata import InlineTags
CONTENT = """\
#tag1 #tag2
> #tag3
**#tag4**
I am a sentence with #tag5 and #tag6 in the middle
#tag🙈7
#tag/8
#tag/👋/9
"""
def test__grab_inline_tags_1() -> None:
"""Test _grab_inline_tags() method.
GIVEN a string with a codeblock
WHEN the method is called
THEN the codeblock is ignored
"""
content = """
some text
```python
#tag1
#tag2
```
```
#tag3
#tag4
```
"""
tags = InlineTags(content)
assert tags.list == []
assert tags.list_original == []
def test__grab_inline_tags_2() -> None:
"""Test _grab_inline_tags() method.
GIVEN a string with tags
WHEN the method is called
THEN the tags are extracted
"""
tags = InlineTags(CONTENT)
assert tags.list == [
"tag/8",
"tag/👋/9",
"tag1",
"tag2",
"tag3",
"tag4",
"tag5",
"tag6",
"tag🙈7",
]
assert tags.list_original == [
"tag/8",
"tag/👋/9",
"tag1",
"tag2",
"tag3",
"tag4",
"tag5",
"tag6",
"tag🙈7",
]
def test_add_1():
"""Test add() method.
GIVEN a InlineTag object
WHEN the add() method is called with a tag that exists in the list
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.add("tag1") is False
def test_add_2():
"""Test add() method.
GIVEN a InlineTag object
WHEN the add() method is called with a new tag
THEN return True and add the tag to the list
"""
tags = InlineTags(CONTENT)
assert tags.add("new_tag") is True
assert "new_tag" in tags.list
def test_add_3():
"""Test add() method.
GIVEN a InlineTag object
WHEN the add() method is called with a list of new tags
THEN return True and add the tags to the list
"""
tags = InlineTags(CONTENT)
new_tags = ["new_tag1", "new_tag2"]
assert tags.add(new_tags) is True
assert "new_tag1" in tags.list
assert "new_tag2" in tags.list
def test_add_4():
"""Test add() method.
GIVEN a InlineTag object
WHEN the add() method is called with a list of tags, some of which already exist
THEN return True and add only the new tags to the list
"""
tags = InlineTags(CONTENT)
new_tags = ["new_tag1", "new_tag2", "tag1", "tag2"]
assert tags.add(new_tags) is True
assert tags.list == [
"new_tag1",
"new_tag2",
"tag/8",
"tag/👋/9",
"tag1",
"tag2",
"tag3",
"tag4",
"tag5",
"tag6",
"tag🙈7",
]
def test_add_5():
"""Test add() method.
GIVEN a InlineTag object
WHEN the add() method is called with a list of tags which are already in the list
THEN return False
"""
tags = InlineTags(CONTENT)
new_tags = ["tag1", "tag2"]
assert tags.add(new_tags) is False
assert "tag1" in tags.list
assert "tag2" in tags.list
def test_add_6():
"""Test add() method.
GIVEN a InlineTag object
WHEN the add() method is called with a list of tags which have a # in the name
THEN strip the # from the tag name
"""
tags = InlineTags(CONTENT)
new_tags = ["#tag1", "#tag2", "#new_tag"]
assert tags.add(new_tags) is True
assert tags.list == [
"new_tag",
"tag/8",
"tag/👋/9",
"tag1",
"tag2",
"tag3",
"tag4",
"tag5",
"tag6",
"tag🙈7",
]
def test_add_7():
"""Test add() method.
GIVEN a InlineTag object
WHEN the add() method is called with a tag which has a # in the name
THEN strip the # from the tag name
"""
tags = InlineTags(CONTENT)
assert tags.add("#tag1") is False
assert tags.add("#new_tag") is True
assert "new_tag" in tags.list
def test_contains_1():
"""Test contains() method.
GIVEN a InlineTag object
WHEN the contains() method is called with a tag that exists in the list
THEN return True
"""
tags = InlineTags(CONTENT)
assert tags.contains("tag1") is True
def test_contains_2():
"""Test contains() method.
GIVEN a InlineTag object
WHEN the contains() method is called with a tag that does not exist in the list
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.contains("no_tag") is False
def test_contains_3():
"""Test contains() method.
GIVEN a InlineTag object
WHEN the contains() method is called with a regex that matches a tag in the list
THEN return True
"""
tags = InlineTags(CONTENT)
assert tags.contains(r"tag\d", is_regex=True) is True
def test_contains_4():
"""Test contains() method.
GIVEN a InlineTag object
WHEN the contains() method is called with a regex that does not match any tags in the list
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.contains(r"tag\d\d", is_regex=True) is False
def test_delete_1():
"""Test delete() method.
GIVEN a InlineTag object
WHEN the delete() method is called with a tag that exists in the list
THEN return True and remove the tag from the list
"""
tags = InlineTags(CONTENT)
assert tags.delete("tag1") is True
assert "tag1" not in tags.list
def test_delete_2():
"""Test delete() method.
GIVEN a InlineTag object
WHEN the delete() method is called with a tag that does not exist in the list
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.delete("no_tag") is False
def test_delete_3():
"""Test delete() method.
GIVEN a InlineTag object
WHEN the delete() method is called with a regex that matches a tag in the list
THEN return True and remove the tag from the list
"""
tags = InlineTags(CONTENT)
assert tags.delete(r"tag\d") is True
assert tags.list == ["tag/8", "tag/👋/9", "tag🙈7"]
def test_delete_4():
"""Test delete() method.
GIVEN a InlineTag object
WHEN the delete() method is called with a regex that does not match any tags in the list
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.delete(r"tag\d\d") is False
def test_has_changes_1():
"""Test has_changes() method.
GIVEN a InlineTag object
WHEN the has_changes() method is called
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.has_changes() is False
def test_has_changes_2():
"""Test has_changes() method.
GIVEN a InlineTag object
WHEN the has_changes() method after the list has been updated
THEN return True
"""
tags = InlineTags(CONTENT)
tags.list = ["new_tag"]
assert tags.has_changes() is True
def test_rename_1():
"""Test rename() method.
GIVEN a InlineTag object
WHEN the rename() method is called with a tag that exists in the list
THEN return True and rename the tag in the list
"""
tags = InlineTags(CONTENT)
assert tags.rename("tag1", "new_tag") is True
assert "tag1" not in tags.list
assert "new_tag" in tags.list
def test_rename_2():
"""Test rename() method.
GIVEN a InlineTag object
WHEN the rename() method is called with a tag that does not exist in the list
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.rename("no_tag", "new_tag") is False
assert "new_tag" not in tags.list
def test_rename_3():
"""Test rename() method.
GIVEN a InlineTag object
WHEN the rename() method is called with a tag that exists and the new tag name already exists in the list
THEN return True and ensure the new tag name is only in the list once
"""
tags = InlineTags(CONTENT)
assert tags.rename(r"tag1", "tag2") is True
assert tags.list == [
"tag/8",
"tag/👋/9",
"tag2",
"tag3",
"tag4",
"tag5",
"tag6",
"tag🙈7",
]
def test_rename_4():
"""Test rename() method.
GIVEN a InlineTag object
WHEN the rename() method is called with a new tag value that is None
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.rename("tag1", None) is False
assert "tag1" in tags.list
def test_rename_5():
"""Test rename() method.
GIVEN a InlineTag object
WHEN the rename() method is called with a new tag value that is empty
THEN return False
"""
tags = InlineTags(CONTENT)
assert tags.rename("tag1", "") is False
assert "tag1" in tags.list

View File

@@ -1,393 +0,0 @@
# type: ignore
"""Test metadata.py."""
from pathlib import Path
import pytest
from obsidian_metadata.models.enums import MetadataType
from obsidian_metadata.models.metadata import (
InlineTags,
VaultMetadata,
)
from tests.helpers import Regex, remove_ansi
FILE_CONTENT: str = Path("tests/fixtures/test_vault/test1.md").read_text()
TAG_LIST: list[str] = ["tag 1", "tag 2", "tag 3"]
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"],
}
METADATA_2: dict[str, list[str]] = {"key1": ["value1"], "key2": ["value2", "value3"]}
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_inline_tags_add() -> None:
"""Test inline tags add."""
tags = InlineTags(INLINE_CONTENT)
assert tags.add("bold_tag") is False
assert tags.add("new_tag") is True
assert tags.list == [
"bold_tag",
"in_text_tag",
"inline_tag_top1",
"inline_tag_top2",
"new_tag",
"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_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_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"]
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_vault_metadata() -> None:
"""Test VaultMetadata class."""
vm = VaultMetadata()
assert vm.dict == {}
vm.index_metadata(area=MetadataType.FRONTMATTER, metadata=METADATA)
vm.index_metadata(area=MetadataType.INLINE, metadata=METADATA_2)
vm.index_metadata(area=MetadataType.TAGS, metadata=TAG_LIST)
assert vm.dict == {
"frontmatter_Key1": ["author name"],
"frontmatter_Key2": ["article", "note"],
"intext_key": ["intext_key_value"],
"key1": ["value1"],
"key2": ["value2", "value3"],
"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.frontmatter == {
"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.inline_metadata == {"key1": ["value1"], "key2": ["value2", "value3"]}
assert vm.tags == ["tag 1", "tag 2", "tag 3"]
new_metadata = {"added_key": ["added_value"], "frontmatter_Key2": ["new_value"]}
new_tags = ["tag 4", "tag 5"]
vm.index_metadata(area=MetadataType.FRONTMATTER, metadata=new_metadata)
vm.index_metadata(area=MetadataType.TAGS, metadata=new_tags)
assert vm.dict == {
"added_key": ["added_value"],
"frontmatter_Key1": ["author name"],
"frontmatter_Key2": ["article", "new_value", "note"],
"intext_key": ["intext_key_value"],
"key1": ["value1"],
"key2": ["value2", "value3"],
"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.frontmatter == {
"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"],
}
assert vm.inline_metadata == {"key1": ["value1"], "key2": ["value2", "value3"]}
assert vm.tags == ["tag 1", "tag 2", "tag 3", "tag 4", "tag 5"]
def test_vault_metadata_print(capsys) -> None:
"""Test print_metadata method."""
vm = VaultMetadata()
vm.index_metadata(area=MetadataType.FRONTMATTER, metadata=METADATA)
vm.index_metadata(area=MetadataType.INLINE, metadata=METADATA_2)
vm.index_metadata(area=MetadataType.TAGS, metadata=TAG_LIST)
vm.print_metadata(area=MetadataType.ALL)
captured = remove_ansi(capsys.readouterr().out)
assert "All metadata" in captured
assert "All inline tags" in captured
assert "┃ Keys ┃ Values ┃" in captured
assert "│ shared_key1 │ shared_key1_value │" in captured
assert captured == Regex("#tag 1 +#tag 2")
vm.print_metadata(area=MetadataType.FRONTMATTER)
captured = remove_ansi(capsys.readouterr().out)
assert "All frontmatter" in captured
assert "┃ Keys ┃ Values ┃" in captured
assert "│ shared_key1 │ shared_key1_value │" in captured
assert "value1" not in captured
vm.print_metadata(area=MetadataType.INLINE)
captured = remove_ansi(capsys.readouterr().out)
assert "All inline" in captured
assert "┃ Keys ┃ Values ┃" in captured
assert "shared_key1" not in captured
assert "│ key1 │ value1 │" in captured
vm.print_metadata(area=MetadataType.TAGS)
captured = remove_ansi(capsys.readouterr().out)
assert "All inline tags " in captured
assert "┃ Keys ┃ Values ┃" not in captured
assert captured == Regex("#tag 1 +#tag 2")
vm.print_metadata(area=MetadataType.KEYS)
captured = remove_ansi(capsys.readouterr().out)
assert "All Keys " in captured
assert "┃ Keys ┃ Values ┃" not in captured
assert captured != Regex("#tag 1 +#tag 2")
assert captured == Regex("frontmatter_Key1 +frontmatter_Key2")
def test_vault_metadata_contains() -> None:
"""Test contains method."""
vm = VaultMetadata()
vm.index_metadata(area=MetadataType.FRONTMATTER, metadata=METADATA)
vm.index_metadata(area=MetadataType.INLINE, metadata=METADATA_2)
vm.index_metadata(area=MetadataType.TAGS, metadata=TAG_LIST)
assert vm.dict == {
"frontmatter_Key1": ["author name"],
"frontmatter_Key2": ["article", "note"],
"intext_key": ["intext_key_value"],
"key1": ["value1"],
"key2": ["value2", "value3"],
"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.frontmatter == {
"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.inline_metadata == {"key1": ["value1"], "key2": ["value2", "value3"]}
assert vm.tags == ["tag 1", "tag 2", "tag 3"]
with pytest.raises(ValueError):
vm.contains(area=MetadataType.ALL, value="key1")
assert vm.contains(area=MetadataType.ALL, key="no_key") is False
assert vm.contains(area=MetadataType.ALL, key="key1") is True
assert vm.contains(area=MetadataType.ALL, key="frontmatter_Key2", value="article") is True
assert vm.contains(area=MetadataType.ALL, key="frontmatter_Key2", value="none") is False
assert vm.contains(area=MetadataType.ALL, key="1$", is_regex=True) is True
assert vm.contains(area=MetadataType.ALL, key=r"\d\d", is_regex=True) is False
assert vm.contains(area=MetadataType.FRONTMATTER, key="no_key") is False
assert vm.contains(area=MetadataType.FRONTMATTER, key="frontmatter_Key1") is True
assert (
vm.contains(area=MetadataType.FRONTMATTER, key="frontmatter_Key2", value="article") is True
)
assert vm.contains(area=MetadataType.FRONTMATTER, key="frontmatter_Key2", value="none") is False
assert vm.contains(area=MetadataType.FRONTMATTER, key="1$", is_regex=True) is True
assert vm.contains(area=MetadataType.FRONTMATTER, key=r"\d\d", is_regex=True) is False
assert vm.contains(area=MetadataType.INLINE, key="no_key") is False
assert vm.contains(area=MetadataType.INLINE, key="key1") is True
assert vm.contains(area=MetadataType.INLINE, key="key2", value="value3") is True
assert vm.contains(area=MetadataType.INLINE, key="key2", value="none") is False
assert vm.contains(area=MetadataType.INLINE, key="1$", is_regex=True) is True
assert vm.contains(area=MetadataType.INLINE, key=r"\d\d", is_regex=True) is False
assert vm.contains(area=MetadataType.TAGS, value="no_tag") is False
assert vm.contains(area=MetadataType.TAGS, value="tag 1") is True
assert vm.contains(area=MetadataType.TAGS, value=r"\w+ \d$", is_regex=True) is True
assert vm.contains(area=MetadataType.TAGS, value=r"\w+ \d\d$", is_regex=True) is False
with pytest.raises(ValueError):
vm.contains(area=MetadataType.TAGS, key="key1")
def test_vault_metadata_delete() -> None:
"""Test delete method."""
vm = VaultMetadata()
vm.index_metadata(area=MetadataType.FRONTMATTER, 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.index_metadata(area=MetadataType.FRONTMATTER, 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

View File

@@ -0,0 +1,814 @@
# type: ignore
"""Test VaultMetadata object from metadata.py."""
import pytest
from obsidian_metadata.models.enums import MetadataType
from obsidian_metadata.models.metadata import (
VaultMetadata,
)
from tests.helpers import Regex, remove_ansi
def test_vault_metadata__init_1() -> None:
"""Test VaultMetadata class."""
vm = VaultMetadata()
assert vm.dict == {}
assert vm.frontmatter == {}
assert vm.inline_metadata == {}
assert vm.tags == []
def test_index_metadata_1():
"""Test index_metadata() method.
GIVEN a dictionary to add
WHEN the target area is FRONTMATTER and the old dictionary is empty
THEN the new dictionary is added to the target area
"""
vm = VaultMetadata()
new_dict = {"key1": ["value1"], "key2": ["value2", "value3"]}
vm.index_metadata(area=MetadataType.FRONTMATTER, metadata=new_dict)
assert vm.dict == new_dict
assert vm.frontmatter == new_dict
def test_index_metadata_2():
"""Test index_metadata() method.
GIVEN a dictionary to add
WHEN the target area is FRONTMATTER and the old dictionary is not empty
THEN the new dictionary is merged with the old dictionary
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"], "other_key": ["value1"]}
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
new_dict = {"key1": ["value1"], "key2": ["value1", "value3"], "key3": ["value1"]}
vm.index_metadata(area=MetadataType.FRONTMATTER, metadata=new_dict)
assert vm.dict == {
"key1": ["value1"],
"key2": ["value1", "value2", "value3"],
"key3": ["value1"],
"other_key": ["value1"],
}
assert vm.frontmatter == {
"key1": ["value1"],
"key2": ["value1", "value2", "value3"],
"key3": ["value1"],
}
def test_index_metadata_3():
"""Test index_metadata() method.
GIVEN a dictionary to add
WHEN the target area is INLINE and the old dictionary is empty
THEN the new dictionary is added to the target area
"""
vm = VaultMetadata()
new_dict = {"key1": ["value1"], "key2": ["value2", "value3"]}
vm.index_metadata(area=MetadataType.INLINE, metadata=new_dict)
assert vm.dict == new_dict
assert vm.inline_metadata == new_dict
def test_index_metadata_4():
"""Test index_metadata() method.
GIVEN a dictionary to add
WHEN the target area is INLINE and the old dictionary is not empty
THEN the new dictionary is merged with the old dictionary
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"], "other_key": ["value1"]}
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
new_dict = {"key1": ["value1"], "key2": ["value1", "value3"], "key3": ["value1"]}
vm.index_metadata(area=MetadataType.INLINE, metadata=new_dict)
assert vm.dict == {
"key1": ["value1"],
"key2": ["value1", "value2", "value3"],
"key3": ["value1"],
"other_key": ["value1"],
}
assert vm.inline_metadata == {
"key1": ["value1"],
"key2": ["value1", "value2", "value3"],
"key3": ["value1"],
}
def test_index_metadata_5():
"""Test index_metadata() method.
GIVEN a dictionary to add
WHEN the target area is TAGS and the old list is empty
THEN the new list is added to the target area
"""
vm = VaultMetadata()
new_list = ["tag1", "tag2", "tag3"]
vm.index_metadata(area=MetadataType.TAGS, metadata=new_list)
assert vm.dict == {}
assert vm.tags == new_list
def test_index_metadata_6():
"""Test index_metadata() method.
GIVEN a dictionary to add
WHEN the target area is TAGS and the old list is not empty
THEN the new list is merged with the old list
"""
vm = VaultMetadata()
vm.tags = ["tag1", "tag2", "tag3"]
new_list = ["tag1", "tag2", "tag4", "tag5"]
vm.index_metadata(area=MetadataType.TAGS, metadata=new_list)
assert vm.dict == {}
assert vm.tags == ["tag1", "tag2", "tag3", "tag4", "tag5"]
def test_contains_1():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key that exists
THEN True is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.FRONTMATTER, key="key1") is True
def test_contains_2():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key that does not exist
THEN False is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.FRONTMATTER, key="key3") is False
def test_contains_3():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key and value that exists
THEN True is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.FRONTMATTER, key="key2", value="value1") is True
def test_contains_4():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key and value that does not exist
THEN False is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.FRONTMATTER, key="key2", value="value3") is False
def test_contains_5():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key that exists with regex
THEN True is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.FRONTMATTER, key=r"\w+\d", is_regex=True) is True
def test_contains_6():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key that does not exist with regex
THEN False is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.FRONTMATTER, key=r"^\d", is_regex=True) is False
def test_contains_7():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key and value that exists with regex
THEN True is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert (
vm.contains(area=MetadataType.FRONTMATTER, key="key2", value=r"\w\d", is_regex=True) is True
)
def test_contains_8():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked for a key and value that does not exist with regex
THEN False is returned
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert (
vm.contains(area=MetadataType.FRONTMATTER, key="key2", value=r"^\d", is_regex=True) is False
)
def test_contains_9():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN FRONTMATTER is checked with a key is None
THEN raise a ValueError
"""
vm = VaultMetadata()
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
with pytest.raises(ValueError, match="Key must be provided"):
vm.contains(area=MetadataType.FRONTMATTER, value="value1")
def test_contains_10():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key that exists
THEN True is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key="key1") is True
def test_contains_11():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key that does not exist
THEN False is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key="key3") is False
def test_contains_12():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key and value that exists
THEN True is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key="key2", value="value1") is True
def test_contains_13():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key and value that does not exist
THEN False is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key="key2", value="value3") is False
def test_contains_14():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key that exists with regex
THEN True is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key=r"\w+\d", is_regex=True) is True
def test_contains_15():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key that does not exist with regex
THEN False is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key=r"^\d", is_regex=True) is False
def test_contains_16():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key and value that exists with regex
THEN True is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key="key2", value=r"\w\d", is_regex=True) is True
def test_contains_17():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked for a key and value that does not exist with regex
THEN False is returned
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.INLINE, key="key2", value=r"^\d", is_regex=True) is False
def test_contains_18():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN INLINE is checked with a key is None
THEN raise a ValueError
"""
vm = VaultMetadata()
vm.inline_metadata = {"key1": ["value1"], "key2": ["value1", "value2"]}
with pytest.raises(ValueError, match="Key must be provided"):
vm.contains(area=MetadataType.INLINE, value="value1")
def test_contains_19():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN TAGS is checked for a key but not a value
THEN raise a ValueError
"""
vm = VaultMetadata()
vm.tags = ["tag1", "tag2", "tag3"]
with pytest.raises(ValueError, match="Value must be provided"):
vm.contains(area=MetadataType.TAGS, key="key1")
def test_contains_20():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN TAGS is checked for a value that exists
THEN True is returned
"""
vm = VaultMetadata()
vm.tags = ["tag1", "tag2", "tag3"]
assert vm.contains(area=MetadataType.TAGS, value="tag1") is True
def test_contains_21():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN TAGS is checked for a value that does not exist
THEN False is returned
"""
vm = VaultMetadata()
vm.tags = ["tag1", "tag2", "tag3"]
assert vm.contains(area=MetadataType.TAGS, value="value1") is False
def test_contains_22():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN TAGS is checked for a key regex but no value
THEN True is returned
"""
vm = VaultMetadata()
vm.tags = ["tag1", "tag2", "tag3"]
with pytest.raises(ValueError, match="Value must be provided"):
vm.contains(area=MetadataType.TAGS, key=r"\w", is_regex=True)
def test_contains_23():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN TAGS is checked for a value that does not exist with regex
THEN False is returned
"""
vm = VaultMetadata()
vm.tags = ["tag1", "tag2", "tag3"]
assert vm.contains(area=MetadataType.TAGS, value=r"^\d", is_regex=True) is False
def test_contains_24():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN TAGS is checked for a value that exists with regex
THEN True is returned
"""
vm = VaultMetadata()
vm.tags = ["tag1", "tag2", "tag3"]
assert vm.contains(area=MetadataType.TAGS, value=r"^tag\d", is_regex=True) is True
def test_contains_25():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key that exists
THEN True is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key="key1") is True
def test_contains_26():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key that does not exist
THEN False is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key="key3") is False
def test_contains_27():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key and value that exists
THEN True is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key="key2", value="value1") is True
def test_contains_28():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key and value that does not exist
THEN False is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key="key2", value="value3") is False
def test_contains_29():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key that exists with regex
THEN True is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key=r"\w+\d", is_regex=True) is True
def test_contains_30():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key that does not exist with regex
THEN False is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key=r"^\d", is_regex=True) is False
def test_contains_31():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key and value that exists with regex
THEN True is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key="key2", value=r"\w\d", is_regex=True) is True
def test_contains_32():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked for a key and value that does not exist with regex
THEN False is returned
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.contains(area=MetadataType.ALL, key="key2", value=r"^\d", is_regex=True) is False
def test_contains_33():
"""Test contains() method.
GIVEN a VaultMetadata object
WHEN ALL is checked with a key is None
THEN raise a ValueError
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
with pytest.raises(ValueError, match="Key must be provided"):
vm.contains(area=MetadataType.ALL, value="value1")
def test_delete_1():
"""Test delete() method.
GIVEN a VaultMetadata object
WHEN a key is deleted
THEN return True and the key is removed
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.delete(key="key1") is True
assert vm.dict == {"key2": ["value1", "value2"]}
def test_delete_2():
"""Test delete() method.
GIVEN a VaultMetadata object
WHEN a key is deleted that does not exist
THEN return False and the key is not removed
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.delete(key="key3") is False
assert vm.dict == {"key1": ["value1"], "key2": ["value1", "value2"]}
def test_delete_3():
"""Test delete() method.
GIVEN a VaultMetadata object
WHEN a key and value are specified
THEN return True and remove the value
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.delete(key="key2", value_to_delete="value1") is True
assert vm.dict == {"key1": ["value1"], "key2": ["value2"]}
def test_delete_4():
"""Test delete() method.
GIVEN a VaultMetadata object
WHEN a key and nonexistent value are specified
THEN return False
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.delete(key="key2", value_to_delete="value11") is False
assert vm.dict == {"key1": ["value1"], "key2": ["value1", "value2"]}
def test_rename_1():
"""Test VaultMetadata rename() method.
GIVEN a VaultMetadata object
WHEN the rename() method is called with a key
THEN return False if the key is not found
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.rename("no key", "new key") is False
def test_rename_2():
"""Test VaultMetadata rename() method.
GIVEN a VaultMetadata object
WHEN the rename() method is called with an existing key and non-existing value
THEN return False
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.rename("key1", "no value", "new value") is False
def test_rename_3():
"""Test VaultMetadata rename() method.
GIVEN a VaultMetadata object
WHEN the rename() method is called with an existing key
THEN return True and rename the key
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.rename("key1", "new key") is True
assert vm.dict == {"key2": ["value1", "value2"], "new key": ["value1"]}
def test_rename_4():
"""Test VaultMetadata rename() method.
GIVEN a VaultMetadata object
WHEN the rename() method is called with an existing key and value
THEN return True and rename the value
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.rename("key1", "value1", "new value") is True
assert vm.dict == {"key1": ["new value"], "key2": ["value1", "value2"]}
def test_rename_5():
"""Test VaultMetadata rename() method.
GIVEN a VaultMetadata object
WHEN the rename() method is called with an existing key and value and the new value already exists
THEN return True and remove the old value leaving one instance of the new value
"""
vm = VaultMetadata()
vm.dict = {"key1": ["value1"], "key2": ["value1", "value2"]}
assert vm.rename("key2", "value1", "value2") is True
assert vm.dict == {"key1": ["value1"], "key2": ["value2"]}
def test_print_metadata_1(capsys):
"""Test print_metadata() method.
GIVEN calling print_metadata() with a VaultMetadata object
WHEN ALL is specified
THEN print all the metadata
"""
vm = VaultMetadata()
vm.dict = {
"key1": ["value1", "value2"],
"key2": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
vm.inline_metadata = {
"key1": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.tags = ["tag1", "tag2", "tag3"]
vm.print_metadata(area=MetadataType.ALL)
captured = remove_ansi(capsys.readouterr().out)
assert "All metadata" in captured
assert captured == Regex("┃ Keys +┃ Values +┃")
assert captured == Regex("│ key1 +│ value1 +│")
assert captured == Regex("│ key2 +│ value1 +│")
assert captured == Regex("│ key4 +│ value1 +│")
assert "All inline tags" in captured
assert captured == Regex("#tag1 +#tag2")
def test_print_metadata_2(capsys):
"""Test print_metadata() method.
GIVEN calling print_metadata() with a VaultMetadata object
WHEN FRONTMATTER is specified
THEN print all the metadata
"""
vm = VaultMetadata()
vm.dict = {
"key1": ["value1", "value2"],
"key2": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
vm.inline_metadata = {
"key1": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.tags = ["tag1", "tag2", "tag3"]
vm.print_metadata(area=MetadataType.FRONTMATTER)
captured = remove_ansi(capsys.readouterr().out)
assert "All frontmatter" in captured
assert captured == Regex("┃ Keys +┃ Values +┃")
assert captured == Regex("│ key1 +│ value1 +│")
assert captured == Regex("│ key2 +│ value1 +│")
assert captured != Regex("│ key4 +│ value1 +│")
assert "All inline tags" not in captured
assert captured != Regex("#tag1 +#tag2")
def test_print_metadata_3(capsys):
"""Test print_metadata() method.
GIVEN calling print_metadata() with a VaultMetadata object
WHEN INLINE is specified
THEN print all the metadata
"""
vm = VaultMetadata()
vm.dict = {
"key1": ["value1", "value2"],
"key2": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
vm.inline_metadata = {
"key1": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.tags = ["tag1", "tag2", "tag3"]
vm.print_metadata(area=MetadataType.INLINE)
captured = remove_ansi(capsys.readouterr().out)
assert "All inline" in captured
assert captured == Regex("┃ Keys +┃ Values +┃")
assert captured == Regex("│ key1 +│ value1 +│")
assert captured != Regex("│ key2 +│ value1 +│")
assert captured == Regex("│ key4 +│ value1 +│")
assert "All inline tags" not in captured
assert captured != Regex("#tag1 +#tag2")
def test_print_metadata_4(capsys):
"""Test print_metadata() method.
GIVEN calling print_metadata() with a VaultMetadata object
WHEN TAGS is specified
THEN print all the tags
"""
vm = VaultMetadata()
vm.dict = {
"key1": ["value1", "value2"],
"key2": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
vm.inline_metadata = {
"key1": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.tags = ["tag1", "tag2", "tag3"]
vm.print_metadata(area=MetadataType.TAGS)
captured = remove_ansi(capsys.readouterr().out)
assert "All inline tags" in captured
assert captured != Regex("┃ Keys +┃ Values +┃")
assert captured != Regex("│ key1 +│ value1 +│")
assert captured != Regex("│ key2 +│ value1 +│")
assert captured != Regex("│ key4 +│ value1 +│")
assert captured == Regex("#tag1 +#tag2 +#tag3")
def test_print_metadata_5(capsys):
"""Test print_metadata() method.
GIVEN calling print_metadata() with a VaultMetadata object
WHEN KEYS is specified
THEN print all the tags
"""
vm = VaultMetadata()
vm.dict = {
"key1": ["value1", "value2"],
"key2": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.frontmatter = {"key1": ["value1"], "key2": ["value1", "value2"]}
vm.inline_metadata = {
"key1": ["value1", "value2"],
"key3": ["value1"],
"key4": ["value1", "value2"],
}
vm.tags = ["tag1", "tag2", "tag3"]
vm.print_metadata(area=MetadataType.KEYS)
captured = remove_ansi(capsys.readouterr().out)
assert "All Keys" in captured
assert captured != Regex("┃ Keys +┃ Values +┃")
assert captured != Regex("│ key1 +│ value1 +│")
assert captured != Regex("│ key2 +│ value1 +│")
assert captured != Regex("│ key4 +│ value1 +│")
assert captured != Regex("#tag1 +#tag2 +#tag3")
assert captured == Regex("key1 +key2 +key3 +key4")

View File

@@ -6,15 +6,174 @@ import typer
from obsidian_metadata._utils import (
clean_dictionary,
delete_from_dict,
dict_contains,
dict_keys_to_lower,
dict_values_to_lists_strings,
remove_markdown_sections,
rename_in_dict,
validate_csv_bulk_imports,
)
from tests.helpers import Regex, remove_ansi
def test_delete_from_dict_1():
"""Test delete_from_dict() function.
GIVEN a dictionary with values
WHEN the delete_from_dict() function is called with a key that exists
THEN the key should be deleted from the dictionary and the original dictionary should not be modified
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key1") == {
"key2": ["value2", "value3"],
"key3": "value4",
}
assert test_dict == {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
def test_delete_from_dict_2():
"""Test delete_from_dict() function.
GIVEN a dictionary with values
WHEN the delete_from_dict() function is called with a key that does not exist
THEN the dictionary should not be modified
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key5") == test_dict
def test_delete_from_dict_3():
"""Test delete_from_dict() function.
GIVEN a dictionary with values in a list
WHEN the delete_from_dict() function is called with a key and value that exists
THEN the value should be deleted from the specified key in dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key2", value="value3") == {
"key1": ["value1"],
"key2": ["value2"],
"key3": "value4",
}
def test_delete_from_dict_4():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key and value that exists
THEN the value and key should be deleted from the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key3", value="value4") == {
"key1": ["value1"],
"key2": ["value2", "value3"],
}
def test_delete_from_dict_5():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key and value that does not exist
THEN the dictionary should not be modified
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key3", value="value5") == test_dict
def test_delete_from_dict_6():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key regex that matches
THEN the matching keys should be deleted from the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key[23]", is_regex=True) == {
"key1": ["value1"]
}
def test_delete_from_dict_7():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key regex that does not match
THEN no keys should be deleted from the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key=r"key\d\d", is_regex=True) == test_dict
def test_delete_from_dict_8():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key and value regex that matches
THEN the matching keys should be deleted from the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key2", value=r"\w+", is_regex=True) == {
"key1": ["value1"],
"key2": [],
"key3": "value4",
}
def test_delete_from_dict_9():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key and value regex that does not match
THEN no keys should be deleted from the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert (
delete_from_dict(dictionary=test_dict, key=r"key2", value=r"^\d", is_regex=True)
== test_dict
)
def test_delete_from_dict_10():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key and value regex that matches
THEN the matching keys should be deleted from the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(dictionary=test_dict, key="key3", value=r"\w+", is_regex=True) == {
"key1": ["value1"],
"key2": ["value2", "value3"],
}
def test_delete_from_dict_11():
"""Test delete_from_dict() function.
GIVEN a dictionary with values as strings
WHEN the delete_from_dict() function is called with a key regex that matches multiple and values that match
THEN the values matching the associated keys should be deleted from the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"], "key3": "value4"}
assert delete_from_dict(
dictionary=test_dict, key=r"key[23]", value=r"\w+[34]$", is_regex=True
) == {"key1": ["value1"], "key2": ["value2"]}
def test_dict_contains() -> None:
"""Test dict_contains."""
d = {"key1": ["value1", "value2"], "key2": ["value3", "value4"], "key3": ["value5", "value6"]}
@@ -82,6 +241,78 @@ def test_dict_values_to_lists_strings():
}
def test_rename_in_dict_1():
"""Test rename_in_dict() function.
GIVEN a dictionary with values as a list
WHEN the rename_in_dict() function is called with a key that does not exist
THEN no keys should be renamed in the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"]}
assert rename_in_dict(dictionary=test_dict, key="key4", value_1="key5") == test_dict
def test_rename_in_dict_2():
"""Test rename_in_dict() function.
GIVEN a dictionary with values as a list
WHEN the rename_in_dict() function is called with a key that exists and a new value for the key
THEN the key should be renamed in the returned dictionary and the original dictionary should not be modified
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"]}
assert rename_in_dict(dictionary=test_dict, key="key2", value_1="new_key") == {
"key1": ["value1"],
"new_key": ["value2", "value3"],
}
assert test_dict == {"key1": ["value1"], "key2": ["value2", "value3"]}
def test_rename_in_dict_3():
"""Test rename_in_dict() function.
GIVEN a dictionary with values as a list
WHEN the rename_in_dict() function is called with a key that exists value that does not exist
THEN the dictionary should not be modified
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"]}
assert (
rename_in_dict(dictionary=test_dict, key="key2", value_1="no_value", value_2="new_value")
== test_dict
)
def test_rename_in_dict_4():
"""Test rename_in_dict() function.
GIVEN a dictionary with values as a list
WHEN the rename_in_dict() function is called with a key that exists and a new value for a value
THEN update the specified value in the dictionary
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"]}
assert rename_in_dict(
dictionary=test_dict, key="key2", value_1="value2", value_2="new_value"
) == {"key1": ["value1"], "key2": ["new_value", "value3"]}
def test_rename_in_dict_5():
"""Test rename_in_dict() function.
GIVEN a dictionary with values as a list
WHEN the rename_in_dict() function is called with a key that exists and a an existing value for a renamed value
THEN only one instance of the new value should be in the key
"""
test_dict = {"key1": ["value1"], "key2": ["value2", "value3"]}
assert rename_in_dict(dictionary=test_dict, key="key2", value_1="value2", value_2="value3") == {
"key1": ["value1"],
"key2": ["value3"],
}
def test_remove_markdown_sections():
"""Test removing markdown sections."""
text: str = """