mirror of
https://github.com/natelandau/obsidian-metadata.git
synced 2025-11-19 02:13:39 -05:00
fix: add custom exceptions (#29)
* feat: add custom exceptions to metadata creation * refactor: utility function for finding inline metadata in content * fix: use InlineTagError for exceptions parsing inline tags * fix: improve error messages * build(deps): bump dependencies * fix: use BadParameter exception when appropriate
This commit is contained in:
17
src/obsidian_metadata/models/exceptions.py
Normal file
17
src/obsidian_metadata/models/exceptions.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""Custom exceptions for the obsidian_metadata package."""
|
||||
|
||||
|
||||
class ObsidianMetadataError(Exception):
|
||||
"""Base exception for the obsidian_metadata package."""
|
||||
|
||||
|
||||
class FrontmatterError(ObsidianMetadataError):
|
||||
"""Exception for errors in the frontmatter."""
|
||||
|
||||
|
||||
class InlineMetadataError(ObsidianMetadataError):
|
||||
"""Exception for errors in the inlined metadata."""
|
||||
|
||||
|
||||
class InlineTagError(ObsidianMetadataError):
|
||||
"""Exception for errors in the inline tags."""
|
||||
@@ -13,13 +13,20 @@ from obsidian_metadata._utils import (
|
||||
delete_from_dict,
|
||||
dict_contains,
|
||||
dict_values_to_lists_strings,
|
||||
inline_metadata_from_string,
|
||||
merge_dictionaries,
|
||||
remove_markdown_sections,
|
||||
rename_in_dict,
|
||||
)
|
||||
from obsidian_metadata._utils.alerts import logger as log
|
||||
from obsidian_metadata._utils.console import console
|
||||
from obsidian_metadata.models import Patterns # isort: ignore
|
||||
from obsidian_metadata.models.enums import MetadataType
|
||||
from obsidian_metadata.models.exceptions import (
|
||||
FrontmatterError,
|
||||
InlineMetadataError,
|
||||
InlineTagError,
|
||||
)
|
||||
|
||||
PATTERNS = Patterns()
|
||||
INLINE_TAG_KEY: str = "inline_tag"
|
||||
@@ -230,7 +237,7 @@ class Frontmatter:
|
||||
try:
|
||||
frontmatter: dict = yaml.load(frontmatter_block)
|
||||
except Exception as e: # noqa: BLE001
|
||||
raise AttributeError(e) from e
|
||||
raise FrontmatterError(e) from e
|
||||
|
||||
if frontmatter is None or frontmatter == [None]:
|
||||
return {}
|
||||
@@ -400,15 +407,26 @@ class InlineMetadata:
|
||||
strip_inlinecode=True,
|
||||
strip_frontmatter=True,
|
||||
)
|
||||
all_results = PATTERNS.find_inline_metadata.findall(content)
|
||||
stripped_null_values = [tuple(filter(None, x)) for x in all_results]
|
||||
|
||||
found_inline_metadata = inline_metadata_from_string(content)
|
||||
inline_metadata: dict[str, list[str]] = {}
|
||||
for k, v in stripped_null_values:
|
||||
if k in inline_metadata:
|
||||
inline_metadata[k].append(str(v))
|
||||
else:
|
||||
inline_metadata[k] = [str(v)]
|
||||
|
||||
try:
|
||||
for k, v in found_inline_metadata:
|
||||
if not k:
|
||||
log.trace(f"Skipping empty key associated with value: {v}")
|
||||
continue
|
||||
if k in inline_metadata:
|
||||
inline_metadata[k].append(str(v))
|
||||
else:
|
||||
inline_metadata[k] = [str(v)]
|
||||
except ValueError as e:
|
||||
raise InlineMetadataError(
|
||||
f"Error parsing inline metadata: {found_inline_metadata}"
|
||||
) from e
|
||||
except AttributeError as e:
|
||||
raise InlineMetadataError(
|
||||
f"Error parsing inline metadata: {found_inline_metadata}"
|
||||
) from e
|
||||
|
||||
return clean_dictionary(inline_metadata)
|
||||
|
||||
@@ -537,15 +555,22 @@ class InlineTags:
|
||||
Returns:
|
||||
list[str]: Inline tags from the note.
|
||||
"""
|
||||
return sorted(
|
||||
PATTERNS.find_inline_tags.findall(
|
||||
remove_markdown_sections(
|
||||
file_content,
|
||||
strip_codeblocks=True,
|
||||
strip_inlinecode=True,
|
||||
try:
|
||||
return sorted(
|
||||
PATTERNS.find_inline_tags.findall(
|
||||
remove_markdown_sections(
|
||||
file_content,
|
||||
strip_codeblocks=True,
|
||||
strip_inlinecode=True,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
except AttributeError as e:
|
||||
raise InlineTagError("Error parsing inline tags.") from e
|
||||
except TypeError as e:
|
||||
raise InlineTagError("Error parsing inline tags.") from e
|
||||
except ValueError as e:
|
||||
raise InlineTagError("Error parsing inline tags.") from e
|
||||
|
||||
def add(self, new_tag: str | list[str]) -> bool:
|
||||
"""Add a new inline tag.
|
||||
|
||||
@@ -10,7 +10,7 @@ import rich.repr
|
||||
import typer
|
||||
from rich.table import Table
|
||||
|
||||
from obsidian_metadata._utils import alerts
|
||||
from obsidian_metadata._utils import alerts, inline_metadata_from_string
|
||||
from obsidian_metadata._utils.alerts import logger as log
|
||||
from obsidian_metadata._utils.console import console
|
||||
from obsidian_metadata.models import (
|
||||
@@ -21,6 +21,11 @@ from obsidian_metadata.models import (
|
||||
MetadataType,
|
||||
Patterns,
|
||||
)
|
||||
from obsidian_metadata.models.exceptions import (
|
||||
FrontmatterError,
|
||||
InlineMetadataError,
|
||||
InlineTagError,
|
||||
)
|
||||
|
||||
PATTERNS = Patterns()
|
||||
|
||||
@@ -50,19 +55,24 @@ class Note:
|
||||
try:
|
||||
with self.note_path.open():
|
||||
self.file_content: str = self.note_path.read_text()
|
||||
self.original_file_content: str = self.file_content
|
||||
except FileNotFoundError as e:
|
||||
alerts.error(f"Note {self.note_path} not found. Exiting")
|
||||
raise typer.Exit(code=1) from e
|
||||
|
||||
try:
|
||||
self.frontmatter: Frontmatter = Frontmatter(self.file_content)
|
||||
except AttributeError as e:
|
||||
alerts.error(f"Note {self.note_path} has invalid frontmatter.\n{e}")
|
||||
self.inline_metadata: InlineMetadata = InlineMetadata(self.file_content)
|
||||
self.tags: InlineTags = InlineTags(self.file_content)
|
||||
except FrontmatterError as e:
|
||||
alerts.error(f"Invalid frontmatter: {self.note_path}\n{e}")
|
||||
raise typer.Exit(code=1) from e
|
||||
except InlineMetadataError as e:
|
||||
alerts.error(f"Error parsing inline metadata: {self.note_path}.\n{e}")
|
||||
raise typer.Exit(code=1) from e
|
||||
except InlineTagError as e:
|
||||
alerts.error(f"Error parsing inline tags: {self.note_path}\n{e}")
|
||||
raise typer.Exit(code=1) from e
|
||||
|
||||
self.tags: InlineTags = InlineTags(self.file_content)
|
||||
self.inline_metadata: InlineMetadata = InlineMetadata(self.file_content)
|
||||
self.original_file_content: str = self.file_content
|
||||
|
||||
def __rich_repr__(self) -> rich.repr.Result: # pragma: no cover
|
||||
"""Define rich representation of Vault."""
|
||||
@@ -552,10 +562,9 @@ class Note:
|
||||
value_2 (str, optional): New value.
|
||||
|
||||
"""
|
||||
all_results = PATTERNS.find_inline_metadata.findall(self.file_content)
|
||||
stripped_null_values = [tuple(filter(None, x)) for x in all_results]
|
||||
found_inline_metadata = inline_metadata_from_string(self.file_content)
|
||||
|
||||
for _k, _v in stripped_null_values:
|
||||
for _k, _v in found_inline_metadata:
|
||||
if re.search(key, _k):
|
||||
if value_2 is None:
|
||||
if re.search(rf"{key}[^\\w\\d_-]+", _k):
|
||||
|
||||
Reference in New Issue
Block a user