fdf
This commit is contained in:
132
SYS/item_accessors.py
Normal file
132
SYS/item_accessors.py
Normal file
@@ -0,0 +1,132 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Any, Iterable, Optional
|
||||
|
||||
_SHA256_RE = re.compile(r"^[0-9a-fA-F]{64}$")
|
||||
|
||||
|
||||
def get_field(obj: Any, field: str, default: Optional[Any] = None) -> Any:
|
||||
if isinstance(obj, list):
|
||||
if not obj:
|
||||
return default
|
||||
obj = obj[0]
|
||||
|
||||
if isinstance(obj, dict):
|
||||
return obj.get(field, default)
|
||||
|
||||
value = getattr(obj, field, None)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
extra_value = getattr(obj, "extra", None)
|
||||
if isinstance(extra_value, dict):
|
||||
return extra_value.get(field, default)
|
||||
|
||||
return default
|
||||
|
||||
|
||||
def first_field(obj: Any, fields: Iterable[str], default: Optional[Any] = None) -> Any:
|
||||
for field in fields:
|
||||
value = get_field(obj, str(field), None)
|
||||
if value is not None:
|
||||
return value
|
||||
return default
|
||||
|
||||
|
||||
def get_text_field(obj: Any, *fields: str, default: str = "") -> str:
|
||||
value = first_field(obj, fields, default=None)
|
||||
if value is None:
|
||||
return default
|
||||
text = str(value).strip()
|
||||
return text if text else default
|
||||
|
||||
|
||||
def get_column_text(obj: Any, *labels: str) -> Optional[str]:
|
||||
columns = get_field(obj, "columns")
|
||||
if not isinstance(columns, list):
|
||||
return None
|
||||
wanted = {str(label or "").strip().lower() for label in labels if str(label or "").strip()}
|
||||
if not wanted:
|
||||
return None
|
||||
for pair in columns:
|
||||
try:
|
||||
if not isinstance(pair, (list, tuple)) or len(pair) != 2:
|
||||
continue
|
||||
key, value = pair
|
||||
if str(key or "").strip().lower() not in wanted:
|
||||
continue
|
||||
text = str(value or "").strip()
|
||||
if text:
|
||||
return text
|
||||
except Exception:
|
||||
continue
|
||||
return None
|
||||
|
||||
|
||||
def get_int_field(obj: Any, *fields: str) -> Optional[int]:
|
||||
value = first_field(obj, fields, default=None)
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, (int, float)):
|
||||
return int(value)
|
||||
try:
|
||||
return int(value)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def get_extension_field(obj: Any, *fields: str) -> str:
|
||||
text = get_text_field(obj, *(fields or ("ext", "extension")), default="")
|
||||
return text.lstrip(".") if text else ""
|
||||
|
||||
|
||||
def get_result_title(obj: Any, *fields: str) -> Optional[str]:
|
||||
text = get_text_field(obj, *(fields or ("title", "name", "filename")), default="")
|
||||
if text:
|
||||
return text
|
||||
return get_column_text(obj, "title", "name")
|
||||
|
||||
|
||||
def extract_item_tags(obj: Any) -> list[str]:
|
||||
return get_string_list(obj, "tag")
|
||||
|
||||
|
||||
def get_string_list(obj: Any, field: str) -> list[str]:
|
||||
value = get_field(obj, field)
|
||||
if isinstance(value, list):
|
||||
return [str(item).strip() for item in value if item is not None and str(item).strip()]
|
||||
if isinstance(value, str):
|
||||
text = value.strip()
|
||||
return [text] if text else []
|
||||
return []
|
||||
|
||||
|
||||
def set_field(obj: Any, field: str, value: Any) -> bool:
|
||||
if isinstance(obj, dict):
|
||||
obj[field] = value
|
||||
return True
|
||||
try:
|
||||
setattr(obj, field, value)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def get_sha256_hex(obj: Any, *fields: str) -> Optional[str]:
|
||||
value = get_text_field(obj, *(fields or ("hash",)))
|
||||
if value and _SHA256_RE.fullmatch(value):
|
||||
return value.lower()
|
||||
return None
|
||||
|
||||
|
||||
def get_store_name(obj: Any, *fields: str) -> Optional[str]:
|
||||
value = get_text_field(obj, *(fields or ("store",)))
|
||||
return value or None
|
||||
|
||||
|
||||
def get_http_url(obj: Any, *fields: str) -> Optional[str]:
|
||||
value = get_text_field(obj, *(fields or ("url", "target")))
|
||||
if value.lower().startswith(("http://", "https://")):
|
||||
return value
|
||||
return None
|
||||
Reference in New Issue
Block a user