mirror of
https://github.com/natelandau/obsidian-metadata.git
synced 2025-11-08 05:03:47 -05:00
refactor: pass Ruff lint rules
This commit is contained in:
@@ -65,6 +65,7 @@ repos:
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--extend-ignore", "I001,D301,D401,PLR2004,PLR0913"]
|
||||
exclude: tests/
|
||||
|
||||
- repo: "https://github.com/jendrikseipp/vulture"
|
||||
rev: "v2.7"
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
]
|
||||
ignore-init-module-imports = true
|
||||
line-length = 100
|
||||
per-file-ignores = { "cli.py" = ["PLR0913"] }
|
||||
select = [
|
||||
"A",
|
||||
"B",
|
||||
@@ -207,7 +208,7 @@
|
||||
help = "Lint this package"
|
||||
|
||||
[[tool.poe.tasks.lint.sequence]]
|
||||
shell = "ruff --extend-ignore=I001,D301,D401,PLR2004,PLR0913 src/ tests/"
|
||||
shell = "ruff --extend-ignore=I001,D301,D401,PLR2004,PLR0913 src/"
|
||||
|
||||
[[tool.poe.tasks.lint.sequence]]
|
||||
shell = "black --check src/ tests/"
|
||||
|
||||
@@ -36,7 +36,7 @@ class ConfigQuestions:
|
||||
|
||||
@staticmethod
|
||||
def _validate_valid_dir(path: str) -> bool | str:
|
||||
"""Validates a valid directory.
|
||||
"""Validate a valid directory.
|
||||
|
||||
Returns:
|
||||
bool | str: True if the path is valid, otherwise a string with the error message.
|
||||
@@ -55,7 +55,6 @@ class Config:
|
||||
"""Representation of a configuration file."""
|
||||
|
||||
def __init__(self, config_path: Path = None, vault_path: Path = None) -> None:
|
||||
|
||||
if vault_path is None:
|
||||
self.config_path: Path = self._validate_config_path(Path(config_path))
|
||||
self.config: dict[str, Any] = self._load_config()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Logging and alerts."""
|
||||
import sys
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from textwrap import wrap
|
||||
|
||||
@@ -9,6 +10,28 @@ from loguru import logger
|
||||
from rich import print
|
||||
|
||||
|
||||
class LogLevel(Enum):
|
||||
"""Enum for log levels."""
|
||||
|
||||
TRACE = 5
|
||||
DEBUG = 10
|
||||
INFO = 20
|
||||
SUCCESS = 25
|
||||
WARNING = 30
|
||||
ERROR = 40
|
||||
CRITICAL = 50
|
||||
EXCEPTION = 60
|
||||
|
||||
|
||||
class VerboseLevel(Enum):
|
||||
"""Enum for verbose levels."""
|
||||
|
||||
WARN = 0
|
||||
INFO = 1
|
||||
DEBUG = 2
|
||||
TRACE = 3
|
||||
|
||||
|
||||
def dryrun(msg: str) -> None:
|
||||
"""Print a message if the dry run flag is set.
|
||||
|
||||
@@ -151,7 +174,7 @@ class LoggerManager:
|
||||
print("No log file specified")
|
||||
raise typer.Exit(1)
|
||||
|
||||
if self.verbosity >= 3:
|
||||
if self.verbosity >= VerboseLevel.TRACE.value:
|
||||
logger.remove()
|
||||
logger.add(
|
||||
sys.stderr,
|
||||
@@ -161,7 +184,7 @@ class LoggerManager:
|
||||
diagnose=True,
|
||||
)
|
||||
self.log_level = 5
|
||||
elif self.verbosity == 2:
|
||||
elif self.verbosity == VerboseLevel.DEBUG.value:
|
||||
logger.remove()
|
||||
logger.add(
|
||||
sys.stderr,
|
||||
@@ -171,7 +194,7 @@ class LoggerManager:
|
||||
diagnose=True,
|
||||
)
|
||||
self.log_level = 10
|
||||
elif self.verbosity == 1:
|
||||
elif self.verbosity == VerboseLevel.INFO.value:
|
||||
logger.remove()
|
||||
logger.add(
|
||||
sys.stderr,
|
||||
@@ -214,7 +237,7 @@ class LoggerManager:
|
||||
Returns:
|
||||
bool: True if the current log level is TRACE or lower, False otherwise.
|
||||
"""
|
||||
if self.log_level <= 5:
|
||||
if self.log_level <= LogLevel.TRACE.value:
|
||||
if msg:
|
||||
print(msg)
|
||||
return True
|
||||
@@ -229,7 +252,7 @@ class LoggerManager:
|
||||
Returns:
|
||||
bool: True if the current log level is DEBUG or lower, False otherwise.
|
||||
"""
|
||||
if self.log_level <= 10:
|
||||
if self.log_level <= LogLevel.DEBUG.value:
|
||||
if msg:
|
||||
print(msg)
|
||||
return True
|
||||
@@ -244,7 +267,7 @@ class LoggerManager:
|
||||
Returns:
|
||||
bool: True if the current log level is INFO or lower, False otherwise.
|
||||
"""
|
||||
if self.log_level <= 20:
|
||||
if self.log_level <= LogLevel.INFO.value:
|
||||
if msg:
|
||||
print(msg)
|
||||
return True
|
||||
@@ -259,7 +282,7 @@ class LoggerManager:
|
||||
Returns:
|
||||
bool: True if the current log level is default or lower, False otherwise.
|
||||
"""
|
||||
if self.log_level <= 30:
|
||||
if self.log_level <= LogLevel.WARNING.value:
|
||||
if msg:
|
||||
print(msg)
|
||||
return True
|
||||
|
||||
@@ -63,7 +63,7 @@ def dict_contains(
|
||||
|
||||
|
||||
def dict_values_to_lists_strings(dictionary: dict, strip_null_values: bool = False) -> dict:
|
||||
"""Converts all values in a dictionary to lists of strings.
|
||||
"""Convert all values in a dictionary to lists of strings.
|
||||
|
||||
Args:
|
||||
dictionary (dict): Dictionary to convert
|
||||
@@ -101,7 +101,7 @@ def dict_values_to_lists_strings(dictionary: dict, strip_null_values: bool = Fal
|
||||
|
||||
|
||||
def docstring_parameter(*sub: Any) -> Any:
|
||||
"""Decorator to replace variables within docstrings.
|
||||
"""Replace variables within docstrings.
|
||||
|
||||
Args:
|
||||
sub (Any): Replacement variables
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""obsidian-metadata CLI."""
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
@@ -84,7 +83,7 @@ def main(
|
||||
None, "--version", help="Print version and exit", callback=version_callback, is_eager=True
|
||||
),
|
||||
) -> None:
|
||||
r"""A script to make batch updates to metadata in an Obsidian vault. No changes are made to the Vault until they are explicitly committed.
|
||||
r"""Make batch updates to metadata in an Obsidian vault. No changes are made to the Vault until they are explicitly committed.
|
||||
|
||||
[bold] [/]
|
||||
[bold underline]It is strongly recommended that you back up your vault prior to committing changes.[/] This script makes changes directly to the markdown files in your vault. Once the changes are committed, there is no ability to recreate the original information unless you have a backup. Follow the instructions in the script to create a backup of your vault if needed. The author of this script is not responsible for any data loss that may occur. Use at your own risk.
|
||||
|
||||
@@ -113,7 +113,6 @@ class Application:
|
||||
while True:
|
||||
match self.questions.ask_selection(choices=choices, question="Select an action"):
|
||||
case "apply_path_filter":
|
||||
|
||||
path = self.questions.ask_filter_path()
|
||||
if path is None or path == "":
|
||||
return
|
||||
|
||||
@@ -213,7 +213,6 @@ class Frontmatter:
|
||||
"""Representation of frontmatter metadata."""
|
||||
|
||||
def __init__(self, file_content: str):
|
||||
|
||||
self.dict: dict[str, list[str]] = self._grab_note_frontmatter(file_content)
|
||||
self.dict_original: dict[str, list[str]] = self.dict.copy()
|
||||
|
||||
@@ -389,7 +388,6 @@ class InlineMetadata:
|
||||
"""Representation of inline metadata in the form of `key:: value`."""
|
||||
|
||||
def __init__(self, file_content: str):
|
||||
|
||||
self.dict: dict[str, list[str]] = self._grab_inline_metadata(file_content)
|
||||
self.dict_original: dict[str, list[str]] = self.dict.copy()
|
||||
|
||||
@@ -417,7 +415,7 @@ class InlineMetadata:
|
||||
stripped_null_values = [tuple(filter(None, x)) for x in all_results]
|
||||
|
||||
inline_metadata: dict[str, list[str]] = {}
|
||||
for (k, v) in stripped_null_values:
|
||||
for k, v in stripped_null_values:
|
||||
if k in inline_metadata:
|
||||
inline_metadata[k].append(str(v))
|
||||
else:
|
||||
@@ -515,7 +513,6 @@ class InlineTags:
|
||||
"""Representation of inline tags."""
|
||||
|
||||
def __init__(self, file_content: str):
|
||||
|
||||
self.metadata_key = INLINE_TAG_KEY
|
||||
self.list: list[str] = self._grab_inline_tags(file_content)
|
||||
self.list_original: list[str] = self.list.copy()
|
||||
|
||||
@@ -65,7 +65,7 @@ class Note:
|
||||
yield "inline_metadata", self.inline_metadata
|
||||
|
||||
def _delete_inline_metadata(self, key: str, value: str = None) -> None:
|
||||
"""Deletes an inline metadata key/value pair from the text of the note. This method does not remove the key/value from the metadata attribute of the note.
|
||||
"""Delete an inline metadata key/value pair from the text of the note. This method does not remove the key/value from the metadata attribute of the note.
|
||||
|
||||
Args:
|
||||
key (str): Key to delete.
|
||||
@@ -74,7 +74,7 @@ class Note:
|
||||
all_results = PATTERNS.find_inline_metadata.findall(self.file_content)
|
||||
stripped_null_values = [tuple(filter(None, x)) for x in all_results]
|
||||
|
||||
for (_k, _v) in stripped_null_values:
|
||||
for _k, _v in stripped_null_values:
|
||||
if re.search(key, _k):
|
||||
if value is None:
|
||||
_k = re.escape(_k)
|
||||
@@ -88,7 +88,7 @@ class Note:
|
||||
self.sub(rf"({_k}::) ?{_v}", r"\1", is_regex=True)
|
||||
|
||||
def _rename_inline_metadata(self, key: str, value_1: str, value_2: str = None) -> None:
|
||||
"""Replaces the inline metadata in the note with the current inline metadata object.
|
||||
"""Replace the inline metadata in the note with the current inline metadata object.
|
||||
|
||||
Args:
|
||||
key (str): Key to rename.
|
||||
@@ -99,7 +99,7 @@ class Note:
|
||||
all_results = PATTERNS.find_inline_metadata.findall(self.file_content)
|
||||
stripped_null_values = [tuple(filter(None, x)) for x in all_results]
|
||||
|
||||
for (_k, _v) in stripped_null_values:
|
||||
for _k, _v in stripped_null_values:
|
||||
if re.search(key, _k):
|
||||
if value_2 is None:
|
||||
if re.search(rf"{key}[^\w\d_-]+", _k):
|
||||
@@ -118,7 +118,7 @@ class Note:
|
||||
self.sub(f"{_k}:: ?{_v}", f"{_k}:: {value_2}", is_regex=True)
|
||||
|
||||
def add_metadata(self, area: MetadataType, key: str, value: str | list[str] = None) -> bool:
|
||||
"""Adds metadata to the note.
|
||||
"""Add metadata to the note.
|
||||
|
||||
Args:
|
||||
area (MetadataType): Area to add metadata to.
|
||||
@@ -143,7 +143,7 @@ class Note:
|
||||
return False
|
||||
|
||||
def append(self, string_to_append: str, allow_multiple: bool = False) -> None:
|
||||
"""Appends a string to the end of a note.
|
||||
"""Append a string to the end of a note.
|
||||
|
||||
Args:
|
||||
string_to_append (str): String to append to the note.
|
||||
@@ -156,7 +156,7 @@ class Note:
|
||||
self.file_content += f"\n{string_to_append}"
|
||||
|
||||
def commit_changes(self) -> None:
|
||||
"""Commits changes to the note to disk."""
|
||||
"""Commit changes to the note to disk."""
|
||||
# TODO: rewrite frontmatter if it has changed
|
||||
pass
|
||||
|
||||
@@ -198,7 +198,7 @@ class Note:
|
||||
return False
|
||||
|
||||
def delete_inline_tag(self, tag: str) -> bool:
|
||||
"""Deletes an inline tag from the `inline_tags` attribute AND removes the tag from the text of the note if it exists.
|
||||
"""Delete an inline tag from the `inline_tags` attribute AND removes the tag from the text of the note if it exists.
|
||||
|
||||
Args:
|
||||
tag (str): Tag to delete.
|
||||
@@ -220,7 +220,7 @@ class Note:
|
||||
return False
|
||||
|
||||
def delete_metadata(self, key: str, value: str = None) -> bool:
|
||||
"""Deletes a key or key-value pair from the note's metadata. Regex is supported.
|
||||
"""Delete a key or key-value pair from the note's metadata. Regex is supported.
|
||||
|
||||
If no value is provided, will delete an entire key.
|
||||
|
||||
@@ -253,7 +253,7 @@ class Note:
|
||||
return False
|
||||
|
||||
def has_changes(self) -> bool:
|
||||
"""Checks if the note has been updated.
|
||||
"""Check if the note has been updated.
|
||||
|
||||
Returns:
|
||||
bool: Whether the note has been updated.
|
||||
@@ -273,11 +273,11 @@ class Note:
|
||||
return False
|
||||
|
||||
def print_note(self) -> None:
|
||||
"""Prints the note to the console."""
|
||||
"""Print the note to the console."""
|
||||
print(self.file_content)
|
||||
|
||||
def print_diff(self) -> None:
|
||||
"""Prints a diff of the note's original state and it's new state."""
|
||||
"""Print a diff of the note's original state and it's new state."""
|
||||
a = self.original_file_content.splitlines()
|
||||
b = self.file_content.splitlines()
|
||||
|
||||
@@ -294,7 +294,7 @@ class Note:
|
||||
Console().print(table)
|
||||
|
||||
def replace_frontmatter(self, sort_keys: bool = False) -> None:
|
||||
"""Replaces the frontmatter in the note with the current frontmatter object."""
|
||||
"""Replace the frontmatter in the note with the current frontmatter object."""
|
||||
try:
|
||||
current_frontmatter = PATTERNS.frontmatt_block_with_separators.search(
|
||||
self.file_content
|
||||
@@ -316,7 +316,7 @@ class Note:
|
||||
self.sub(current_frontmatter, new_frontmatter, is_regex=True)
|
||||
|
||||
def rename_inline_tag(self, tag_1: str, tag_2: str) -> bool:
|
||||
"""Renames an inline tag from the note ONLY if it's not in the metadata as well.
|
||||
"""Rename an inline tag from the note ONLY if it's not in the metadata as well.
|
||||
|
||||
Args:
|
||||
tag_1 (str): Tag to rename.
|
||||
@@ -336,7 +336,7 @@ class Note:
|
||||
return False
|
||||
|
||||
def rename_metadata(self, key: str, value_1: str, value_2: str = None) -> bool:
|
||||
"""Renames a key or key-value pair in the note's metadata.
|
||||
"""Rename a key or key-value pair in the note's metadata.
|
||||
|
||||
If no value is provided, will rename an entire key.
|
||||
|
||||
@@ -383,7 +383,7 @@ class Note:
|
||||
self.file_content = re.sub(pattern, replacement, self.file_content, re.MULTILINE)
|
||||
|
||||
def write(self, path: Path = None) -> None:
|
||||
"""Writes the note's content to disk.
|
||||
"""Write the note's content to disk.
|
||||
|
||||
Args:
|
||||
path (Path): Path to write the note to. Defaults to the note's path.
|
||||
|
||||
@@ -50,7 +50,7 @@ class Questions:
|
||||
|
||||
@staticmethod
|
||||
def _validate_valid_dir(path: str) -> bool | str:
|
||||
"""Validates a valid directory.
|
||||
"""Validate a valid directory.
|
||||
|
||||
Returns:
|
||||
bool | str: True if the path is valid, otherwise a string with the error message.
|
||||
@@ -86,7 +86,7 @@ class Questions:
|
||||
self.key = key
|
||||
|
||||
def _validate_existing_inline_tag(self, text: str) -> bool | str:
|
||||
"""Validates an existing inline tag.
|
||||
"""Validate an existing inline tag.
|
||||
|
||||
Returns:
|
||||
bool | str: True if the tag is valid, otherwise a string with the error message.
|
||||
@@ -100,7 +100,7 @@ class Questions:
|
||||
return True
|
||||
|
||||
def _validate_key_exists(self, text: str) -> bool | str:
|
||||
"""Validates a valid key.
|
||||
"""Validate a valid key.
|
||||
|
||||
Returns:
|
||||
bool | str: True if the key is valid, otherwise a string with the error message.
|
||||
@@ -114,7 +114,7 @@ class Questions:
|
||||
return True
|
||||
|
||||
def _validate_key_exists_regex(self, text: str) -> bool | str:
|
||||
"""Validates a valid key.
|
||||
"""Validate a valid key.
|
||||
|
||||
Returns:
|
||||
bool | str: True if the key is valid, otherwise a string with the error message.
|
||||
@@ -200,7 +200,7 @@ class Questions:
|
||||
return True
|
||||
|
||||
def _validate_valid_vault_regex(self, text: str) -> bool | str:
|
||||
"""Validates a valid regex.
|
||||
"""Validate a valid regex.
|
||||
|
||||
Returns:
|
||||
bool | str: True if the regex is valid, otherwise a string with the error message.
|
||||
@@ -262,7 +262,7 @@ class Questions:
|
||||
return True
|
||||
|
||||
def ask_application_main(self) -> str: # pragma: no cover
|
||||
"""Selectable list for the main application interface.
|
||||
"""List for the main application interface.
|
||||
|
||||
Args:
|
||||
style (questionary.Style): The style to use for the question.
|
||||
|
||||
Reference in New Issue
Block a user