huge refactor of plugin system

This commit is contained in:
2026-04-30 18:56:22 -07:00
parent ea3ead248b
commit be5a11da97
99 changed files with 7603 additions and 11320 deletions
+34 -3
View File
@@ -11,6 +11,9 @@ CmdletArg = sh.CmdletArg
SharedArgs = sh.SharedArgs
normalize_hash = sh.normalize_hash
parse_tag_arguments = sh.parse_tag_arguments
render_tag_value_templates = sh.render_tag_value_templates
merge_sequences = sh.merge_sequences
extract_tag_from_result = sh.extract_tag_from_result
should_show_help = sh.should_show_help
get_field = sh.get_field
from SYS.logger import debug, log
@@ -133,6 +136,11 @@ CMDLET = Cmdlet(
detail=[
"- Requires a Hydrus file (hash present) or explicit -query override.",
"- Multiple tags can be comma-separated or space-separated.",
"- Use #(namespace) inside a tag value to remove a derived tag, e.g. delete-tag \"title:#(track) - #(series)\".",
"- Angle-bracket transforms match add-tag syntax, e.g. delete-tag \"code:e<padding(00,#(episode))>\".",
"- Current documented transforms include padding, default, replace, and increment.",
"- Template examples assume lowercase tag text; case transforms are intentionally not part of the documented syntax.",
"- See docs/tag_template_syntax.md for recipe-style examples and the current shared template syntax.",
],
)
@@ -225,7 +233,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
store_name = override_store or get_field(result, "store")
path = get_field(result, "path") or get_field(result, "target")
tags = [str(t) for t in grouped_tags if t]
return 0 if _process_deletion(tags, file_hash, path, store_name, config) else 1
return 0 if _process_deletion(tags, file_hash, path, store_name, config, result=result) else 1
if not tags_arg and not has_piped_tag and not has_piped_tag_list:
log("Requires at least one tag argument")
@@ -316,7 +324,8 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
item_hash,
item_path,
item_store,
config):
config,
result=item):
success_count += 1
if success_count > 0:
@@ -331,6 +340,7 @@ def _process_deletion(
store_name: str | None,
config: Dict[str,
Any],
result: Any = None,
) -> bool:
"""Helper to execute the deletion logic for a single target."""
@@ -367,12 +377,33 @@ def _process_deletion(
except Exception:
return []
existing_tag_list = merge_sequences(
extract_tag_from_result(result),
_fetch_existing_tags(),
case_sensitive=True,
)
resolved_tags, unresolved_templates = render_tag_value_templates(
tags,
existing_tags=existing_tag_list,
result=result,
)
if unresolved_templates:
log(
f"[delete_tag] skipped {len(unresolved_templates)} tag template(s) with unresolved #(namespace) placeholders",
file=sys.stderr,
)
tags = list(resolved_tags)
if not tags:
return False
# Safety: only block if this deletion would remove the final title tag
title_tags = [
t for t in tags if isinstance(t, str) and t.lower().startswith("title:")
]
if title_tags:
existing_tags = _fetch_existing_tags()
existing_tags = existing_tag_list
current_titles = [
t for t in existing_tags
if isinstance(t, str) and t.lower().startswith("title:")