Add YAPF style + ignore, and format tracked Python files

This commit is contained in:
2025-12-29 18:42:02 -08:00
parent c019c00aed
commit 507946a3e4
108 changed files with 11664 additions and 6494 deletions

View File

@@ -23,18 +23,25 @@ class Delete_File(sh.Cmdlet):
def __init__(self) -> None:
super().__init__(
name="delete-file",
summary="Delete a file locally and/or from Hydrus, including database entries.",
usage='delete-file [-query "hash:<sha256>"] [-conserve <local|hydrus>] [-lib-root <path>] [reason]',
summary=
"Delete a file locally and/or from Hydrus, including database entries.",
usage=
'delete-file [-query "hash:<sha256>"] [-conserve <local|hydrus>] [-lib-root <path>] [reason]',
alias=["del-file"],
arg=[
sh.SharedArgs.QUERY,
sh.CmdletArg(
"conserve", description="Choose which copy to keep: 'local' or 'hydrus'."
"conserve",
description="Choose which copy to keep: 'local' or 'hydrus'."
),
sh.CmdletArg(
"lib-root", description="Path to local library root for database cleanup."
"lib-root",
description="Path to local library root for database cleanup."
),
sh.CmdletArg(
"reason",
description="Optional reason for deletion (free text)."
),
sh.CmdletArg("reason", description="Optional reason for deletion (free text)."),
],
detail=[
"Default removes both the local file and Hydrus file.",
@@ -53,8 +60,10 @@ class Delete_File(sh.Cmdlet):
conserve: str | None,
lib_root: str | None,
reason: str,
config: Dict[str, Any],
) -> List[Dict[str, Any]]:
config: Dict[str,
Any],
) -> List[Dict[str,
Any]]:
"""Process deletion for a single item.
Returns display rows (for the final Rich table). Returning an empty list
@@ -68,9 +77,11 @@ class Delete_File(sh.Cmdlet):
else:
hash_hex_raw = sh.get_field(item, "hash_hex") or sh.get_field(item, "hash")
target = (
sh.get_field(item, "target")
or sh.get_field(item, "file_path")
or sh.get_field(item, "path")
sh.get_field(item,
"target") or sh.get_field(item,
"file_path")
or sh.get_field(item,
"path")
)
title_val = sh.get_field(item, "title") or sh.get_field(item, "name")
@@ -142,11 +153,9 @@ class Delete_File(sh.Cmdlet):
is_hydrus_store = False
# Backwards-compatible fallback heuristic (older items might only carry a name).
if (
(not is_hydrus_store)
and bool(store_lower)
and ("hydrus" in store_lower or store_lower in {"home", "work"})
):
if ((not is_hydrus_store) and bool(store_lower)
and ("hydrus" in store_lower or store_lower in {"home",
"work"})):
is_hydrus_store = True
store_label = str(store) if store else "default"
hydrus_prefix = f"[hydrusnetwork:{store_label}]"
@@ -156,14 +165,16 @@ class Delete_File(sh.Cmdlet):
hash_hex_raw = target
hash_hex = (
sh.normalize_hash(override_hash) if override_hash else sh.normalize_hash(hash_hex_raw)
sh.normalize_hash(override_hash)
if override_hash else sh.normalize_hash(hash_hex_raw)
)
local_deleted = False
local_target = (
isinstance(target, str)
and target.strip()
and not str(target).lower().startswith(("http://", "https://"))
isinstance(target,
str) and target.strip()
and not str(target).lower().startswith(("http://",
"https://"))
)
deleted_rows: List[Dict[str, Any]] = []
@@ -180,7 +191,9 @@ class Delete_File(sh.Cmdlet):
if backend is not None:
# Prefer hash when available.
hash_candidate = sh.normalize_hash(hash_hex_raw) if hash_hex_raw else None
hash_candidate = sh.normalize_hash(
hash_hex_raw
) if hash_hex_raw else None
if not hash_candidate and isinstance(target, str):
hash_candidate = sh.normalize_hash(target)
@@ -189,13 +202,15 @@ class Delete_File(sh.Cmdlet):
if hash_candidate and hasattr(backend, "get_file"):
candidate_path = backend.get_file(hash_candidate)
resolved_path = (
candidate_path if isinstance(candidate_path, Path) else None
candidate_path if isinstance(candidate_path,
Path) else None
)
except Exception:
resolved_path = None
identifier = hash_candidate or (
str(target).strip() if isinstance(target, str) else ""
str(target).strip() if isinstance(target,
str) else ""
)
if identifier:
deleter = getattr(backend, "delete_file", None)
@@ -204,11 +219,10 @@ class Delete_File(sh.Cmdlet):
size_bytes: int | None = None
try:
if (
resolved_path is not None
and isinstance(resolved_path, Path)
and resolved_path.exists()
):
if (resolved_path is not None
and isinstance(resolved_path,
Path)
and resolved_path.exists()):
size_bytes = int(resolved_path.stat().st_size)
except Exception:
size_bytes = None
@@ -216,25 +230,34 @@ class Delete_File(sh.Cmdlet):
deleted_rows.append(
{
"title": (
str(title_val).strip()
if title_val
else (resolved_path.name if resolved_path else identifier)
str(title_val).strip() if title_val else (
resolved_path.name
if resolved_path else identifier
)
),
"store":
store_label,
"hash":
hash_candidate or (hash_hex or ""),
"size_bytes":
size_bytes,
"ext":
_get_ext_from_item() or (
resolved_path.suffix.lstrip(".")
if resolved_path else ""
),
"store": store_label,
"hash": hash_candidate or (hash_hex or ""),
"size_bytes": size_bytes,
"ext": _get_ext_from_item()
or (resolved_path.suffix.lstrip(".") if resolved_path else ""),
}
)
# Best-effort remove sidecars if we know the resolved path.
try:
if resolved_path is not None and isinstance(resolved_path, Path):
if resolved_path is not None and isinstance(
resolved_path,
Path):
for sidecar in (
resolved_path.with_suffix(".tag"),
resolved_path.with_suffix(".metadata"),
resolved_path.with_suffix(".notes"),
resolved_path.with_suffix(".tag"),
resolved_path.with_suffix(".metadata"),
resolved_path.with_suffix(".notes"),
):
try:
if sidecar.exists() and sidecar.is_file():
@@ -266,7 +289,8 @@ class Delete_File(sh.Cmdlet):
local_deleted = True
deleted_rows.append(
{
"title": str(title_val).strip() if title_val else path.name,
"title":
str(title_val).strip() if title_val else path.name,
"store": store_label,
"hash": hash_hex or sh.normalize_hash(path.stem) or "",
"size_bytes": size_bytes,
@@ -282,11 +306,14 @@ class Delete_File(sh.Cmdlet):
local_deleted = True
deleted_rows.append(
{
"title": str(title_val).strip() if title_val else path.name,
"title":
str(title_val).strip() if title_val else path.name,
"store": store_label,
"hash": hash_hex or sh.normalize_hash(path.stem) or "",
"hash": hash_hex or sh.normalize_hash(path.stem)
or "",
"size_bytes": size_bytes,
"ext": _get_ext_from_item() or path.suffix.lstrip("."),
"ext": _get_ext_from_item()
or path.suffix.lstrip("."),
}
)
except Exception as exc:
@@ -299,7 +326,8 @@ class Delete_File(sh.Cmdlet):
local_deleted = True
deleted_rows.append(
{
"title": str(title_val).strip() if title_val else path.name,
"title":
str(title_val).strip() if title_val else path.name,
"store": store_label,
"hash": hash_hex or sh.normalize_hash(path.stem) or "",
"size_bytes": size_bytes,
@@ -311,9 +339,9 @@ class Delete_File(sh.Cmdlet):
# Remove common sidecars regardless of file removal success
for sidecar in (
path.with_suffix(".tag"),
path.with_suffix(".metadata"),
path.with_suffix(".notes"),
path.with_suffix(".tag"),
path.with_suffix(".metadata"),
path.with_suffix(".notes"),
):
try:
if sidecar.exists() and sidecar.is_file():
@@ -370,7 +398,10 @@ class Delete_File(sh.Cmdlet):
return False
if client is None:
if not local_deleted:
log(f"Hydrus client unavailable for store '{store}'", file=sys.stderr)
log(
f"Hydrus client unavailable for store '{store}'",
file=sys.stderr
)
return False
else:
# No store context; use default Hydrus client.
@@ -385,18 +416,29 @@ class Delete_File(sh.Cmdlet):
log("Hydrus client unavailable", file=sys.stderr)
return False
payload: Dict[str, Any] = {"hashes": [hash_hex]}
payload: Dict[str,
Any] = {
"hashes": [hash_hex]
}
if reason:
payload["reason"] = reason
try:
client._post("/add_files/delete_files", data=payload) # type: ignore[attr-defined]
client._post(
"/add_files/delete_files",
data=payload
) # type: ignore[attr-defined]
# Best-effort clear deletion record if supported by this client.
try:
clearer = getattr(client, "clear_file_deletion_record", None)
if callable(clearer):
clearer([hash_hex])
else:
client._post("/add_files/clear_file_deletion_record", data={"hashes": [hash_hex]}) # type: ignore[attr-defined]
client._post(
"/add_files/clear_file_deletion_record",
data={
"hashes": [hash_hex]
}
) # type: ignore[attr-defined]
except Exception:
pass
@@ -408,7 +450,10 @@ class Delete_File(sh.Cmdlet):
file=sys.stderr,
)
else:
debug(f"{hydrus_prefix} Deleted hash:{hash_hex}", file=sys.stderr)
debug(
f"{hydrus_prefix} Deleted hash:{hash_hex}",
file=sys.stderr
)
except Exception:
# If it's not in Hydrus (e.g. 404 or similar), that's fine
if not local_deleted:
@@ -420,7 +465,10 @@ class Delete_File(sh.Cmdlet):
if isinstance(item, dict):
size_hint = item.get("size_bytes") or item.get("size")
else:
size_hint = sh.get_field(item, "size_bytes") or sh.get_field(item, "size")
size_hint = sh.get_field(item,
"size_bytes"
) or sh.get_field(item,
"size")
except Exception:
size_hint = None
deleted_rows.append(
@@ -456,24 +504,32 @@ class Delete_File(sh.Cmdlet):
while i < len(args):
token = args[i]
low = str(token).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 {"-conserve", "--conserve"} and i + 1 < len(args):
if low in {"-conserve",
"--conserve"} and i + 1 < len(args):
value = str(args[i + 1]).strip().lower()
if value in {"local", "hydrus"}:
if value in {"local",
"hydrus"}:
conserve = value
i += 2
continue
if low in {"-lib-root", "--lib-root", "lib-root"} and i + 1 < len(args):
if low in {"-lib-root",
"--lib-root",
"lib-root"} and i + 1 < len(args):
lib_root = str(args[i + 1]).strip()
i += 2
continue
reason_tokens.append(token)
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
@@ -481,8 +537,10 @@ class Delete_File(sh.Cmdlet):
# If no lib_root provided, try to get the first folder store from config
if not lib_root:
try:
storage_config = config.get("storage", {})
folder_config = storage_config.get("folder", {})
storage_config = config.get("storage",
{})
folder_config = storage_config.get("folder",
{})
if folder_config:
# Get first folder store path
for store_name, store_config in folder_config.items():
@@ -494,7 +552,8 @@ class Delete_File(sh.Cmdlet):
except Exception:
pass
reason = " ".join(token for token in reason_tokens if str(token).strip()).strip()
reason = " ".join(token for token in reason_tokens
if str(token).strip()).strip()
items = []
if isinstance(result, list):
@@ -510,7 +569,12 @@ class Delete_File(sh.Cmdlet):
deleted_rows: List[Dict[str, Any]] = []
for item in items:
rows = self._process_single_item(
item, override_hash, conserve, lib_root, reason, config
item,
override_hash,
conserve,
lib_root,
reason,
config
)
if rows:
success_count += 1
@@ -525,7 +589,9 @@ class Delete_File(sh.Cmdlet):
result_row.add_column("Store", row.get("store", ""))
result_row.add_column("Hash", row.get("hash", ""))
result_row.add_column(
"Size", _format_size(row.get("size_bytes"), integer_only=False)
"Size",
_format_size(row.get("size_bytes"),
integer_only=False)
)
result_row.add_column("Ext", row.get("ext", ""))