refactored and updated tags cmdlet and hydrusnetwork interaction plugin features

This commit is contained in:
2026-05-04 15:08:18 -07:00
parent 5534812426
commit bca85defa4
17 changed files with 380 additions and 175 deletions
+99 -24
View File
@@ -13,6 +13,7 @@ from SYS.result_publication import publish_result_table
from SYS import models
from SYS import pipeline as ctx
from . import _shared as sh
from Store import Store # retained for test monkeypatch compatibility
normalize_result_input = sh.normalize_result_input
filter_results_by_temp = sh.filter_results_by_temp
@@ -28,7 +29,6 @@ parse_cmdlet_args = sh.parse_cmdlet_args
collapse_namespace_tag = sh.collapse_namespace_tag
should_show_help = sh.should_show_help
get_field = sh.get_field
from Store import Store
_FIELD_NAME_RE = re.compile(r"^[A-Za-z0-9_]+$")
@@ -663,8 +663,40 @@ class Add_Tag(Cmdlet):
total_added = 0
total_modified = 0
unresolved_template_count = 0
store_registry: Any = None
store_registry = Store(config, suppress_debug=True)
def _resolve_backend(name: Optional[str]) -> tuple[Any | None, Any, Exception | None]:
nonlocal store_registry
backend_name = str(name or "").strip()
if not backend_name:
return None, store_registry, KeyError("Missing store name")
if backend_name in _backend_instance_cache:
return _backend_instance_cache[backend_name], store_registry, None
try:
backend, registry, exc = sh.get_preferred_store_backend(
config,
backend_name,
store_registry=store_registry,
suppress_debug=True,
)
except TypeError as exc2:
# Tests may monkeypatch get_store_backend with a reduced signature.
if "store_registry" in str(exc2):
backend, registry, exc = sh.get_store_backend(
config,
backend_name,
suppress_debug=True,
)
else:
raise
if registry is not None:
store_registry = registry
if backend is not None:
_backend_instance_cache[backend_name] = backend
return backend, store_registry, exc
pending_bulk_add: Dict[tuple[int, tuple[str, ...], tuple[str, ...]], Dict[str, Any]] = {}
_backend_instance_cache: Dict[str, Any] = {}
extract_matched_items = 0
extract_no_match_items = 0
@@ -697,9 +729,8 @@ class Add_Tag(Cmdlet):
is_known_backend = False
try:
is_known_backend = bool(store_name_str) and store_registry.is_available(
store_name_str
)
backend_probe, store_registry, _probe_exc = _resolve_backend(store_name_str)
is_known_backend = backend_probe is not None
except Exception:
pass
@@ -864,7 +895,7 @@ class Add_Tag(Cmdlet):
# If it's not a known backend and we didn't handle it above as a local/pipeline
# metadata edit, then it's an error.
log(
f"[add_tag] Error: Unknown store '{store_name_str}'. Available: {store_registry.list_backends()}",
f"[add_tag] Error: Unknown store '{store_name_str}'",
file=sys.stderr,
)
return 1
@@ -883,12 +914,7 @@ class Add_Tag(Cmdlet):
ctx.emit(res)
continue
backend, store_registry, exc = sh.get_store_backend(
config,
str(store_name),
store_registry=store_registry,
suppress_debug=True,
)
backend, store_registry, exc = _resolve_backend(str(store_name))
if backend is None:
log(
f"[add_tag] Error: Unknown store '{store_name}': {exc}",
@@ -1027,18 +1053,40 @@ class Add_Tag(Cmdlet):
tags_to_add = []
merged_tags = list(existing_tag_list)
try:
ok_add = backend.add_tag(
resolved_hash,
item_tag_to_add,
config=config,
existing_tags=existing_tag_list,
)
if not ok_add:
log("[add_tag] Warning: Store rejected tag update", file=sys.stderr)
except Exception as exc:
log(f"[add_tag] Warning: Failed adding tag: {exc}", file=sys.stderr)
ok_add = False
queued_bulk = False
ok_add = False
add_tags_bulk_fn = getattr(backend, "add_tags_bulk", None)
if tags_to_add and callable(add_tags_bulk_fn):
add_key = tuple(sorted({str(t).strip().lower() for t in tags_to_add if str(t).strip()}))
remove_key = tuple(sorted({str(t).strip().lower() for t in tags_to_remove if str(t).strip()}))
if add_key:
batch_key = (id(backend), add_key, remove_key)
bucket = pending_bulk_add.get(batch_key)
if bucket is None:
bucket = {
"backend": backend,
"add_tags": list(add_key),
"remove_tags": list(remove_key),
"hashes": [],
}
pending_bulk_add[batch_key] = bucket
bucket["hashes"].append(resolved_hash)
queued_bulk = True
ok_add = True
if not queued_bulk:
try:
ok_add = backend.add_tag(
resolved_hash,
item_tag_to_add,
config=config,
existing_tags=existing_tag_list,
)
if not ok_add:
log("[add_tag] Warning: Store rejected tag update", file=sys.stderr)
except Exception as exc:
log(f"[add_tag] Warning: Failed adding tag: {exc}", file=sys.stderr)
ok_add = False
if ok_add and merged_tags:
refreshed_list = list(merged_tags)
@@ -1075,6 +1123,33 @@ class Add_Tag(Cmdlet):
ctx.emit(res)
for bucket in pending_bulk_add.values():
backend = bucket.get("backend")
add_tags_for_batch = list(bucket.get("add_tags") or [])
remove_tags_for_batch = list(bucket.get("remove_tags") or [])
hashes_for_batch = [str(h).strip().lower() for h in (bucket.get("hashes") or []) if str(h).strip()]
if backend is None or not hashes_for_batch:
continue
batch_items = [(h, list(add_tags_for_batch), list(remove_tags_for_batch)) for h in hashes_for_batch]
add_tags_bulk_fn = getattr(backend, "add_tags_bulk", None)
applied = False
if callable(add_tags_bulk_fn):
try:
applied = bool(add_tags_bulk_fn(batch_items))
except Exception:
applied = False
if applied:
continue
# Fallback path: retain correctness if backend bulk call fails.
for h in hashes_for_batch:
try:
backend.add_tag(h, list(add_tags_for_batch), config=config)
except Exception as exc:
log(f"[add_tag] Warning: Failed fallback add_tag for {h}: {exc}", file=sys.stderr)
log(
f"[add_tag] Added {total_added} new tag(s) across {len(results)} item(s); modified {total_modified} item(s)",
file=sys.stderr,