Add YAPF style + ignore, and format tracked Python files
This commit is contained in:
@@ -21,7 +21,11 @@ from Store import Store
|
||||
|
||||
|
||||
def _refresh_tag_view_if_current(
|
||||
file_hash: str | None, store_name: str | None, path: str | None, config: Dict[str, Any]
|
||||
file_hash: str | None,
|
||||
store_name: str | None,
|
||||
path: str | None,
|
||||
config: Dict[str,
|
||||
Any]
|
||||
) -> None:
|
||||
"""If the current subject matches the target, refresh tags via get-tag."""
|
||||
try:
|
||||
@@ -52,11 +56,17 @@ def _refresh_tag_view_if_current(
|
||||
subj_paths: list[str] = []
|
||||
if isinstance(subject, dict):
|
||||
subj_hashes = [norm(v) for v in [subject.get("hash")] if v]
|
||||
subj_paths = [norm(v) for v in [subject.get("path"), subject.get("target")] if v]
|
||||
else:
|
||||
subj_hashes = [norm(get_field(subject, f)) for f in ("hash",) if get_field(subject, f)]
|
||||
subj_paths = [
|
||||
norm(get_field(subject, f)) for f in ("path", "target") if get_field(subject, f)
|
||||
norm(v) for v in [subject.get("path"), subject.get("target")] if v
|
||||
]
|
||||
else:
|
||||
subj_hashes = [
|
||||
norm(get_field(subject,
|
||||
f)) for f in ("hash", ) if get_field(subject, f)
|
||||
]
|
||||
subj_paths = [
|
||||
norm(get_field(subject,
|
||||
f)) for f in ("path", "target") if get_field(subject, f)
|
||||
]
|
||||
|
||||
is_match = False
|
||||
@@ -108,11 +118,10 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
return False
|
||||
# TagItem (direct) or PipeObject/dict emitted from get-tag table rows.
|
||||
try:
|
||||
if (
|
||||
hasattr(obj, "__class__")
|
||||
and obj.__class__.__name__ == "TagItem"
|
||||
and hasattr(obj, "tag_name")
|
||||
):
|
||||
if (hasattr(obj,
|
||||
"__class__") and obj.__class__.__name__ == "TagItem"
|
||||
and hasattr(obj,
|
||||
"tag_name")):
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
@@ -123,7 +132,8 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
|
||||
has_piped_tag = _looks_like_tag_row(result)
|
||||
has_piped_tag_list = (
|
||||
isinstance(result, list) and bool(result) and _looks_like_tag_row(result[0])
|
||||
isinstance(result,
|
||||
list) and bool(result) and _looks_like_tag_row(result[0])
|
||||
)
|
||||
|
||||
# Parse -query/-store overrides and collect remaining args.
|
||||
@@ -135,25 +145,32 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
while i < len(args):
|
||||
a = args[i]
|
||||
low = str(a).lower()
|
||||
if low in {"-query", "--query", "query"} and i + 1 < len(args):
|
||||
if low in {"-query",
|
||||
"--query",
|
||||
"query"} and i + 1 < len(args):
|
||||
override_query = str(args[i + 1]).strip()
|
||||
i += 2
|
||||
continue
|
||||
if low in {"-store", "--store", "store"} and i + 1 < len(args):
|
||||
if low in {"-store",
|
||||
"--store",
|
||||
"store"} and i + 1 < len(args):
|
||||
override_store = str(args[i + 1]).strip()
|
||||
i += 2
|
||||
continue
|
||||
rest.append(a)
|
||||
i += 1
|
||||
|
||||
override_hash = sh.parse_single_hash_query(override_query) if override_query else None
|
||||
override_hash = sh.parse_single_hash_query(
|
||||
override_query
|
||||
) if override_query else None
|
||||
if override_query and not override_hash:
|
||||
log("Invalid -query value (expected hash:<sha256>)", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
# Selection syntax (@...) is handled by the pipeline runner, not by this cmdlet.
|
||||
# If @ reaches here as a literal argument, it's almost certainly user error.
|
||||
if rest and str(rest[0]).startswith("@") and not (has_piped_tag or has_piped_tag_list):
|
||||
if rest and str(rest[0]
|
||||
).startswith("@") and not (has_piped_tag or has_piped_tag_list):
|
||||
log("Selection syntax is only supported via piping. Use: @N | delete-tag")
|
||||
return 1
|
||||
|
||||
@@ -166,16 +183,13 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
grouped_table = ""
|
||||
grouped_tags = get_field(result, "tag") if result is not None else None
|
||||
tags_arg = parse_tag_arguments(rest)
|
||||
if (
|
||||
grouped_table == "tag.selection"
|
||||
and isinstance(grouped_tags, list)
|
||||
and grouped_tags
|
||||
and not tags_arg
|
||||
):
|
||||
if (grouped_table == "tag.selection" and isinstance(grouped_tags,
|
||||
list) and grouped_tags
|
||||
and not tags_arg):
|
||||
file_hash = (
|
||||
normalize_hash(override_hash)
|
||||
if override_hash
|
||||
else normalize_hash(get_field(result, "hash"))
|
||||
if override_hash else normalize_hash(get_field(result,
|
||||
"hash"))
|
||||
)
|
||||
store_name = override_store or get_field(result, "store")
|
||||
path = get_field(result, "path") or get_field(result, "target")
|
||||
@@ -200,20 +214,25 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
# If we have Files (or other objects) and args, we are deleting tags FROM those files
|
||||
|
||||
# Check if we are in "delete selected tags" mode (tag rows)
|
||||
is_tag_item_mode = bool(items_to_process) and _looks_like_tag_row(items_to_process[0])
|
||||
is_tag_item_mode = bool(items_to_process) and _looks_like_tag_row(
|
||||
items_to_process[0]
|
||||
)
|
||||
|
||||
if is_tag_item_mode:
|
||||
# Collect all tags to delete from the TagItems and batch per file.
|
||||
# This keeps delete-tag efficient (one backend call per file).
|
||||
groups: Dict[tuple[str, str, str], list[str]] = {}
|
||||
groups: Dict[tuple[str,
|
||||
str,
|
||||
str],
|
||||
list[str]] = {}
|
||||
for item in items_to_process:
|
||||
tag_name = get_field(item, "tag_name")
|
||||
if not tag_name:
|
||||
continue
|
||||
item_hash = (
|
||||
normalize_hash(override_hash)
|
||||
if override_hash
|
||||
else normalize_hash(get_field(item, "hash"))
|
||||
if override_hash else normalize_hash(get_field(item,
|
||||
"hash"))
|
||||
)
|
||||
item_store = override_store or get_field(item, "store")
|
||||
item_path = get_field(item, "path") or get_field(item, "target")
|
||||
@@ -246,8 +265,8 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
tags_to_delete: list[str] = []
|
||||
item_hash = (
|
||||
normalize_hash(override_hash)
|
||||
if override_hash
|
||||
else normalize_hash(get_field(item, "hash"))
|
||||
if override_hash else normalize_hash(get_field(item,
|
||||
"hash"))
|
||||
)
|
||||
item_path = get_field(item, "path") or get_field(item, "target")
|
||||
item_store = override_store or get_field(item, "store")
|
||||
@@ -266,7 +285,11 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
continue
|
||||
|
||||
if tags_to_delete:
|
||||
if _process_deletion(tags_to_delete, item_hash, item_path, item_store, config):
|
||||
if _process_deletion(tags_to_delete,
|
||||
item_hash,
|
||||
item_path,
|
||||
item_store,
|
||||
config):
|
||||
success_count += 1
|
||||
|
||||
if success_count > 0:
|
||||
@@ -279,7 +302,8 @@ def _process_deletion(
|
||||
file_hash: str | None,
|
||||
path: str | None,
|
||||
store_name: str | None,
|
||||
config: Dict[str, Any],
|
||||
config: Dict[str,
|
||||
Any],
|
||||
) -> bool:
|
||||
"""Helper to execute the deletion logic for a single target."""
|
||||
|
||||
@@ -287,7 +311,10 @@ def _process_deletion(
|
||||
return False
|
||||
|
||||
if not store_name:
|
||||
log("Store is required (use -store or pipe a result with store)", file=sys.stderr)
|
||||
log(
|
||||
"Store is required (use -store or pipe a result with store)",
|
||||
file=sys.stderr
|
||||
)
|
||||
return False
|
||||
|
||||
resolved_hash = normalize_hash(file_hash) if file_hash else None
|
||||
@@ -315,13 +342,17 @@ def _process_deletion(
|
||||
return []
|
||||
|
||||
# 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:")]
|
||||
title_tags = [
|
||||
t for t in tags if isinstance(t, str) and t.lower().startswith("title:")
|
||||
]
|
||||
if title_tags:
|
||||
existing_tags = _fetch_existing_tags()
|
||||
current_titles = [
|
||||
t for t in existing_tags if isinstance(t, str) and t.lower().startswith("title:")
|
||||
t for t in existing_tags
|
||||
if isinstance(t, str) and t.lower().startswith("title:")
|
||||
]
|
||||
del_title_set = {t.lower() for t in title_tags}
|
||||
del_title_set = {t.lower()
|
||||
for t in title_tags}
|
||||
remaining_titles = [t for t in current_titles if t.lower() not in del_title_set]
|
||||
if current_titles and not remaining_titles:
|
||||
log(
|
||||
@@ -335,7 +366,9 @@ def _process_deletion(
|
||||
ok = backend.delete_tag(resolved_hash, list(tags), config=config)
|
||||
if ok:
|
||||
preview = resolved_hash[:12] + ("…" if len(resolved_hash) > 12 else "")
|
||||
debug(f"Removed {len(tags)} tag(s) from {preview} via store '{store_name}'.")
|
||||
debug(
|
||||
f"Removed {len(tags)} tag(s) from {preview} via store '{store_name}'."
|
||||
)
|
||||
_refresh_tag_view_if_current(resolved_hash, store_name, path, config)
|
||||
return True
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user