Add YAPF style + ignore, and format tracked Python files
This commit is contained in:
@@ -89,7 +89,10 @@ class CmdletArg:
|
||||
storage_flags = SharedArgs.STORAGE.to_flags()
|
||||
# Returns: ('--storage', '-storage', '-s')
|
||||
"""
|
||||
flags = [f"--{self.name}", f"-{self.name}"] # Both double-dash and single-dash variants
|
||||
flags = [
|
||||
f"--{self.name}",
|
||||
f"-{self.name}"
|
||||
] # Both double-dash and single-dash variants
|
||||
|
||||
# Add short form if alias exists
|
||||
if self.alias:
|
||||
@@ -130,8 +133,11 @@ def QueryArg(
|
||||
description=str(description or ""),
|
||||
choices=list(choices or []),
|
||||
handler=handler,
|
||||
query_key=str(key or name).strip().lower() if str(key or name).strip() else None,
|
||||
query_aliases=[str(a).strip().lower() for a in (aliases or []) if str(a).strip()],
|
||||
query_key=str(key or name).strip().lower()
|
||||
if str(key or name).strip() else None,
|
||||
query_aliases=[
|
||||
str(a).strip().lower() for a in (aliases or []) if str(a).strip()
|
||||
],
|
||||
query_only=bool(query_only),
|
||||
)
|
||||
|
||||
@@ -208,9 +214,7 @@ class SharedArgs:
|
||||
# If no config provided, try to load it
|
||||
if config is None:
|
||||
try:
|
||||
from config import load_config
|
||||
|
||||
config = load_config()
|
||||
from SYS.config import load_config
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
@@ -223,7 +227,9 @@ class SharedArgs:
|
||||
LOCATION = CmdletArg(
|
||||
"location",
|
||||
type="enum",
|
||||
choices=["hydrus", "0x0", "local"],
|
||||
choices=["hydrus",
|
||||
"0x0",
|
||||
"local"],
|
||||
required=True,
|
||||
description="Destination location",
|
||||
)
|
||||
@@ -257,15 +263,25 @@ class SharedArgs:
|
||||
LIBRARY = CmdletArg(
|
||||
"library",
|
||||
type="string",
|
||||
choices=["hydrus", "local", "soulseek", "libgen", "ftp"],
|
||||
choices=["hydrus",
|
||||
"local",
|
||||
"soulseek",
|
||||
"libgen",
|
||||
"ftp"],
|
||||
description="Search library or source location.",
|
||||
)
|
||||
|
||||
TIMEOUT = CmdletArg(
|
||||
"timeout", type="integer", description="Search or operation timeout in seconds."
|
||||
"timeout",
|
||||
type="integer",
|
||||
description="Search or operation timeout in seconds."
|
||||
)
|
||||
|
||||
LIMIT = CmdletArg("limit", type="integer", description="Maximum number of results to return.")
|
||||
LIMIT = CmdletArg(
|
||||
"limit",
|
||||
type="integer",
|
||||
description="Maximum number of results to return."
|
||||
)
|
||||
|
||||
# Path/File arguments
|
||||
PATH = CmdletArg("path", type="string", description="File or directory path.")
|
||||
@@ -280,18 +296,24 @@ class SharedArgs:
|
||||
)
|
||||
|
||||
REASON = CmdletArg(
|
||||
"reason", type="string", description="Reason or explanation for the operation."
|
||||
"reason",
|
||||
type="string",
|
||||
description="Reason or explanation for the operation."
|
||||
)
|
||||
|
||||
ARCHIVE = CmdletArg(
|
||||
"archive",
|
||||
type="flag",
|
||||
description="Archive the URL to Wayback Machine, Archive.today, and Archive.ph (requires URL argument in cmdlet).",
|
||||
description=
|
||||
"Archive the URL to Wayback Machine, Archive.today, and Archive.ph (requires URL argument in cmdlet).",
|
||||
alias="arch",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def resolve_storage(storage_value: Optional[str], default: Optional[Path] = None) -> Path:
|
||||
def resolve_storage(
|
||||
storage_value: Optional[str],
|
||||
default: Optional[Path] = None
|
||||
) -> Path:
|
||||
"""Resolve a storage location name to a filesystem Path.
|
||||
|
||||
Maps storage identifiers (hydrus, local, ftp) to their actual
|
||||
@@ -394,7 +416,11 @@ class Cmdlet:
|
||||
detail: List[str] = field(default_factory=list)
|
||||
"""Detailed explanation lines (for help text)"""
|
||||
# Execution function: func(result, args, config) -> int
|
||||
exec: Optional[Callable[[Any, Sequence[str], Dict[str, Any]], int]] = field(default=None)
|
||||
exec: Optional[Callable[[Any,
|
||||
Sequence[str],
|
||||
Dict[str,
|
||||
Any]],
|
||||
int]] = field(default=None)
|
||||
|
||||
def _collect_names(self) -> List[str]:
|
||||
"""Collect primary name plus aliases, de-duplicated and normalized."""
|
||||
@@ -450,7 +476,8 @@ class Cmdlet:
|
||||
if low in cmdlet.get_flags('library'):
|
||||
# handle library flag
|
||||
"""
|
||||
return {f"-{arg_name}", f"--{arg_name}"}
|
||||
return {f"-{arg_name}",
|
||||
f"--{arg_name}"}
|
||||
|
||||
def build_flag_registry(self) -> Dict[str, set[str]]:
|
||||
"""Build a registry of all flag variants for this cmdlet's arguments.
|
||||
@@ -470,7 +497,10 @@ class Cmdlet:
|
||||
elif low in flags.get('tag', set()):
|
||||
# handle tag
|
||||
"""
|
||||
return {arg.name: self.get_flags(arg.name) for arg in self.arg}
|
||||
return {
|
||||
arg.name: self.get_flags(arg.name)
|
||||
for arg in self.arg
|
||||
}
|
||||
|
||||
|
||||
# Tag groups cache (loaded from JSON config file)
|
||||
@@ -487,7 +517,10 @@ def set_tag_groups_path(path: Path) -> None:
|
||||
TAG_GROUPS_PATH = path
|
||||
|
||||
|
||||
def parse_cmdlet_args(args: Sequence[str], cmdlet_spec: Dict[str, Any] | Cmdlet) -> Dict[str, Any]:
|
||||
def parse_cmdlet_args(args: Sequence[str],
|
||||
cmdlet_spec: Dict[str,
|
||||
Any] | Cmdlet) -> Dict[str,
|
||||
Any]:
|
||||
"""Parse command-line arguments based on cmdlet specification.
|
||||
|
||||
Extracts argument values from command-line tokens using the argument names
|
||||
@@ -515,7 +548,8 @@ def parse_cmdlet_args(args: Sequence[str], cmdlet_spec: Dict[str, Any] | Cmdlet)
|
||||
result = parse_cmdlet_args(["value1", "-count", "5"], cmdlet)
|
||||
# result = {"path": "value1", "count": "5"}
|
||||
"""
|
||||
result: Dict[str, Any] = {}
|
||||
result: Dict[str,
|
||||
Any] = {}
|
||||
|
||||
# Only accept Cmdlet objects
|
||||
if not isinstance(cmdlet_spec, Cmdlet):
|
||||
@@ -527,7 +561,8 @@ def parse_cmdlet_args(args: Sequence[str], cmdlet_spec: Dict[str, Any] | Cmdlet)
|
||||
flagged_args: List[CmdletArg] = [] # args with prefix in definition
|
||||
query_mapped_args: List[CmdletArg] = []
|
||||
|
||||
arg_spec_map: Dict[str, str] = {} # prefix variant -> canonical name (without prefix)
|
||||
arg_spec_map: Dict[str,
|
||||
str] = {} # prefix variant -> canonical name (without prefix)
|
||||
|
||||
for spec in arg_specs:
|
||||
name = spec.name
|
||||
@@ -572,7 +607,8 @@ def parse_cmdlet_args(args: Sequence[str], cmdlet_spec: Dict[str, Any] | Cmdlet)
|
||||
|
||||
# Legacy guidance: -hash/--hash was removed in favor of -query "hash:...".
|
||||
# However, some cmdlets may explicitly re-introduce a -hash flag.
|
||||
if token_lower in {"-hash", "--hash"} and token_lower not in arg_spec_map:
|
||||
if token_lower in {"-hash",
|
||||
"--hash"} and token_lower not in arg_spec_map:
|
||||
try:
|
||||
log(
|
||||
'Legacy flag -hash is no longer supported. Use: -query "hash:<sha256>"',
|
||||
@@ -587,7 +623,10 @@ def parse_cmdlet_args(args: Sequence[str], cmdlet_spec: Dict[str, Any] | Cmdlet)
|
||||
if token_lower in arg_spec_map:
|
||||
canonical_name = arg_spec_map[token_lower]
|
||||
spec = next(
|
||||
(s for s in arg_specs if str(s.name).lstrip("-").lower() == canonical_name.lower()),
|
||||
(
|
||||
s for s in arg_specs
|
||||
if str(s.name).lstrip("-").lower() == canonical_name.lower()
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -650,14 +689,18 @@ def parse_cmdlet_args(args: Sequence[str], cmdlet_spec: Dict[str, Any] | Cmdlet)
|
||||
|
||||
if query_mapped_args and raw_query is not None:
|
||||
try:
|
||||
from cli_syntax import parse_query as _parse_query
|
||||
from SYS.cli_syntax import parse_query as _parse_query
|
||||
|
||||
parsed_query = _parse_query(str(raw_query))
|
||||
fields = parsed_query.get("fields", {}) if isinstance(parsed_query, dict) else {}
|
||||
fields = parsed_query.get("fields",
|
||||
{}) if isinstance(parsed_query,
|
||||
dict) else {}
|
||||
norm_fields = (
|
||||
{str(k).strip().lower(): v for k, v in fields.items()}
|
||||
if isinstance(fields, dict)
|
||||
else {}
|
||||
{
|
||||
str(k).strip().lower(): v
|
||||
for k, v in fields.items()
|
||||
} if isinstance(fields,
|
||||
dict) else {}
|
||||
)
|
||||
except Exception:
|
||||
norm_fields = {}
|
||||
@@ -667,12 +710,15 @@ def parse_cmdlet_args(args: Sequence[str], cmdlet_spec: Dict[str, Any] | Cmdlet)
|
||||
if not canonical_name:
|
||||
continue
|
||||
# Do not override explicit flags.
|
||||
if canonical_name in result and result.get(canonical_name) not in (None, ""):
|
||||
if canonical_name in result and result.get(canonical_name) not in (None,
|
||||
""):
|
||||
continue
|
||||
try:
|
||||
key = str(getattr(spec, "query_key", "") or "").strip().lower()
|
||||
aliases = getattr(spec, "query_aliases", None)
|
||||
alias_list = [str(a).strip().lower() for a in (aliases or []) if str(a).strip()]
|
||||
alias_list = [
|
||||
str(a).strip().lower() for a in (aliases or []) if str(a).strip()
|
||||
]
|
||||
except Exception:
|
||||
key = ""
|
||||
alias_list = []
|
||||
@@ -761,7 +807,9 @@ def parse_single_hash_query(query: Optional[str]) -> Optional[str]:
|
||||
|
||||
|
||||
def get_hash_for_operation(
|
||||
override_hash: Optional[str], result: Any, field_name: str = "hash"
|
||||
override_hash: Optional[str],
|
||||
result: Any,
|
||||
field_name: str = "hash"
|
||||
) -> Optional[str]:
|
||||
"""Get normalized hash from override or result object, consolidating common pattern.
|
||||
|
||||
@@ -778,9 +826,12 @@ def get_hash_for_operation(
|
||||
if override_hash:
|
||||
return normalize_hash(override_hash)
|
||||
hash_value = (
|
||||
get_field(result, field_name)
|
||||
or getattr(result, field_name, None)
|
||||
or getattr(result, "hash", None)
|
||||
get_field(result,
|
||||
field_name) or getattr(result,
|
||||
field_name,
|
||||
None) or getattr(result,
|
||||
"hash",
|
||||
None)
|
||||
)
|
||||
return normalize_hash(hash_value)
|
||||
|
||||
@@ -792,7 +843,9 @@ def fetch_hydrus_metadata(
|
||||
store_name: Optional[str] = None,
|
||||
hydrus_client: Any = None,
|
||||
**kwargs,
|
||||
) -> tuple[Optional[Dict[str, Any]], Optional[int]]:
|
||||
) -> tuple[Optional[Dict[str,
|
||||
Any]],
|
||||
Optional[int]]:
|
||||
"""Fetch metadata from Hydrus for a given hash, consolidating common fetch pattern.
|
||||
|
||||
Eliminates repeated boilerplate: client initialization, error handling, metadata extraction.
|
||||
@@ -850,7 +903,11 @@ def fetch_hydrus_metadata(
|
||||
return None, 1
|
||||
|
||||
items = payload.get("metadata") if isinstance(payload, dict) else None
|
||||
meta = items[0] if (isinstance(items, list) and items and isinstance(items[0], dict)) else None
|
||||
meta = items[0] if (
|
||||
isinstance(items,
|
||||
list) and items and isinstance(items[0],
|
||||
dict)
|
||||
) else None
|
||||
|
||||
return meta, 0
|
||||
|
||||
@@ -914,7 +971,14 @@ def should_show_help(args: Sequence[str]) -> bool:
|
||||
return 0
|
||||
"""
|
||||
try:
|
||||
return any(str(a).lower() in {"-?", "/?", "--help", "-h", "help", "--cmdlet"} for a in args)
|
||||
return any(
|
||||
str(a).lower() in {"-?",
|
||||
"/?",
|
||||
"--help",
|
||||
"-h",
|
||||
"help",
|
||||
"--cmdlet"} for a in args
|
||||
)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@@ -963,8 +1027,12 @@ def pipeline_item_local_path(item: Any) -> Optional[str]:
|
||||
|
||||
|
||||
def collect_relationship_labels(
|
||||
payload: Any, label_stack: List[str] | None = None, mapping: Dict[str, str] | None = None
|
||||
) -> Dict[str, str]:
|
||||
payload: Any,
|
||||
label_stack: List[str] | None = None,
|
||||
mapping: Dict[str,
|
||||
str] | None = None
|
||||
) -> Dict[str,
|
||||
str]:
|
||||
"""Recursively extract hash-to-label mappings from nested relationship data.
|
||||
|
||||
Walks through nested dicts/lists looking for sha256-like strings (64 hex chars)
|
||||
@@ -1149,7 +1217,8 @@ def _load_tag_groups() -> Dict[str, List[str]]:
|
||||
_TAG_GROUPS_MTIME = mtime
|
||||
return {}
|
||||
|
||||
groups: Dict[str, List[str]] = {}
|
||||
groups: Dict[str,
|
||||
List[str]] = {}
|
||||
if isinstance(payload, dict):
|
||||
for key, value in payload.items():
|
||||
if not isinstance(key, str):
|
||||
@@ -1167,7 +1236,8 @@ def _load_tag_groups() -> Dict[str, List[str]]:
|
||||
normalised = _normalise_tag_group_entry(value)
|
||||
if normalised:
|
||||
members.extend(
|
||||
token.strip() for token in normalised.split(",") if token.strip()
|
||||
token.strip() for token in normalised.split(",")
|
||||
if token.strip()
|
||||
)
|
||||
if members:
|
||||
groups[name] = members
|
||||
@@ -1201,19 +1271,24 @@ def expand_tag_groups(raw_tags: Iterable[str]) -> List[str]:
|
||||
candidate = token.strip()
|
||||
if not candidate:
|
||||
continue
|
||||
if candidate.startswith("{") and candidate.endswith("}") and len(candidate) > 2:
|
||||
if candidate.startswith("{") and candidate.endswith("}") and len(candidate
|
||||
) > 2:
|
||||
name = candidate[1:-1].strip().lower()
|
||||
if not name:
|
||||
continue
|
||||
if name in seen:
|
||||
log(f"Tag group recursion detected for {{{name}}}; skipping", file=sys.stderr)
|
||||
log(
|
||||
f"Tag group recursion detected for {{{name}}}; skipping",
|
||||
file=sys.stderr
|
||||
)
|
||||
continue
|
||||
members = groups.get(name)
|
||||
if not members:
|
||||
log(f"Unknown tag group {{{name}}}", file=sys.stderr)
|
||||
result.append(candidate)
|
||||
continue
|
||||
result.extend(_expand(members, seen | {name}))
|
||||
result.extend(_expand(members,
|
||||
seen | {name}))
|
||||
else:
|
||||
result.append(candidate)
|
||||
return result
|
||||
@@ -1291,7 +1366,8 @@ def create_pipe_object_result(
|
||||
parent_hash: Optional[str] = None,
|
||||
tag: Optional[List[str]] = None,
|
||||
**extra: Any,
|
||||
) -> Dict[str, Any]:
|
||||
) -> Dict[str,
|
||||
Any]:
|
||||
"""Create a PipeObject-compatible result dict for pipeline chaining.
|
||||
|
||||
This is a helper to emit results in the standard format that downstream
|
||||
@@ -1395,7 +1471,8 @@ def _extract_flag_value(args: Sequence[str], *flags: str) -> Optional[str]:
|
||||
"""
|
||||
if not args:
|
||||
return None
|
||||
want = {str(f).strip().lower() for f in flags if str(f).strip()}
|
||||
want = {str(f).strip().lower()
|
||||
for f in flags if str(f).strip()}
|
||||
if not want:
|
||||
return None
|
||||
try:
|
||||
@@ -1499,7 +1576,9 @@ def apply_output_path_from_pipeobjects(
|
||||
try:
|
||||
dest_str = str(dest_raw).strip()
|
||||
if "://" in dest_str:
|
||||
_print_live_safe_stderr(f"Ignoring -path value that looks like a URL: {dest_str}")
|
||||
_print_live_safe_stderr(
|
||||
f"Ignoring -path value that looks like a URL: {dest_str}"
|
||||
)
|
||||
return list(emits or [])
|
||||
except Exception:
|
||||
pass
|
||||
@@ -1564,7 +1643,9 @@ def apply_output_path_from_pipeobjects(
|
||||
try:
|
||||
dest_dir.mkdir(parents=True, exist_ok=True)
|
||||
except Exception as exc:
|
||||
_print_live_safe_stderr(f"Failed to create destination directory: {dest_dir} ({exc})")
|
||||
_print_live_safe_stderr(
|
||||
f"Failed to create destination directory: {dest_dir} ({exc})"
|
||||
)
|
||||
return items
|
||||
|
||||
for idx, src in zip(artifact_indices, artifact_paths):
|
||||
@@ -1572,7 +1653,11 @@ def apply_output_path_from_pipeobjects(
|
||||
final = _unique_destination_path(final)
|
||||
try:
|
||||
if src.resolve() == final.resolve():
|
||||
_apply_saved_path_update(items[idx], old_path=str(src), new_path=str(final))
|
||||
_apply_saved_path_update(
|
||||
items[idx],
|
||||
old_path=str(src),
|
||||
new_path=str(final)
|
||||
)
|
||||
_print_saved_output_panel(items[idx], final)
|
||||
continue
|
||||
except Exception:
|
||||
@@ -1602,7 +1687,9 @@ def apply_output_path_from_pipeobjects(
|
||||
try:
|
||||
final.parent.mkdir(parents=True, exist_ok=True)
|
||||
except Exception as exc:
|
||||
_print_live_safe_stderr(f"Failed to create destination directory: {final.parent} ({exc})")
|
||||
_print_live_safe_stderr(
|
||||
f"Failed to create destination directory: {final.parent} ({exc})"
|
||||
)
|
||||
return items
|
||||
|
||||
final = _unique_destination_path(final)
|
||||
@@ -1667,7 +1754,9 @@ def _print_saved_output_panel(item: Any, final_path: Path) -> None:
|
||||
|
||||
file_hash = ""
|
||||
try:
|
||||
file_hash = str(get_field(item, "hash") or get_field(item, "sha256") or "").strip()
|
||||
file_hash = str(get_field(item,
|
||||
"hash") or get_field(item,
|
||||
"sha256") or "").strip()
|
||||
except Exception:
|
||||
file_hash = ""
|
||||
if not file_hash:
|
||||
@@ -1742,13 +1831,15 @@ def get_pipe_object_hash(pipe_object: Any) -> Optional[str]:
|
||||
"""Extract file hash from PipeObject, dict, or pipeline-friendly object."""
|
||||
if pipe_object is None:
|
||||
return None
|
||||
for attr in ("hash",):
|
||||
for attr in ("hash",
|
||||
):
|
||||
if hasattr(pipe_object, attr):
|
||||
value = getattr(pipe_object, attr)
|
||||
if value:
|
||||
return value
|
||||
if isinstance(pipe_object, dict):
|
||||
for key in ("hash",):
|
||||
for key in ("hash",
|
||||
):
|
||||
value = pipe_object.get(key)
|
||||
if value:
|
||||
return value
|
||||
@@ -1832,7 +1923,8 @@ def filter_results_by_temp(results: List[Any], include_temp: bool = False) -> Li
|
||||
return filtered
|
||||
|
||||
|
||||
def merge_sequences(*sources: Optional[Iterable[Any]], case_sensitive: bool = True) -> list[str]:
|
||||
def merge_sequences(*sources: Optional[Iterable[Any]],
|
||||
case_sensitive: bool = True) -> list[str]:
|
||||
"""Merge iterable sources while preserving order and removing duplicates."""
|
||||
seen: set[str] = set()
|
||||
merged: list[str] = []
|
||||
@@ -1858,7 +1950,9 @@ def merge_sequences(*sources: Optional[Iterable[Any]], case_sensitive: bool = Tr
|
||||
|
||||
|
||||
def collapse_namespace_tags(
|
||||
tags: Optional[Iterable[Any]], namespace: str, prefer: str = "last"
|
||||
tags: Optional[Iterable[Any]],
|
||||
namespace: str,
|
||||
prefer: str = "last"
|
||||
) -> list[str]:
|
||||
"""Reduce tags so only one entry for a given namespace remains.
|
||||
|
||||
@@ -1901,7 +1995,9 @@ def collapse_namespace_tags(
|
||||
|
||||
|
||||
def collapse_namespace_tag(
|
||||
tags: Optional[Iterable[Any]], namespace: str, prefer: str = "last"
|
||||
tags: Optional[Iterable[Any]],
|
||||
namespace: str,
|
||||
prefer: str = "last"
|
||||
) -> list[str]:
|
||||
"""Singular alias for collapse_namespace_tags.
|
||||
|
||||
@@ -2020,7 +2116,10 @@ def extract_duration(result: Any) -> Optional[float]:
|
||||
return None
|
||||
|
||||
|
||||
def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> models.PipeObject:
|
||||
def coerce_to_pipe_object(
|
||||
value: Any,
|
||||
default_path: Optional[str] = None
|
||||
) -> models.PipeObject:
|
||||
"""Normalize any incoming result to a PipeObject for single-source-of-truth state.
|
||||
|
||||
Uses hash+store canonical pattern.
|
||||
@@ -2029,11 +2128,9 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
try:
|
||||
from SYS.logger import is_debug_enabled, debug
|
||||
|
||||
if (
|
||||
is_debug_enabled()
|
||||
and hasattr(value, "__class__")
|
||||
and value.__class__.__name__ == "ResultItem"
|
||||
):
|
||||
if (is_debug_enabled() and hasattr(value,
|
||||
"__class__")
|
||||
and value.__class__.__name__ == "ResultItem"):
|
||||
debug("[ResultItem -> PipeObject conversion]")
|
||||
debug(f" title={getattr(value, 'title', None)}")
|
||||
debug(f" target={getattr(value, 'target', None)}")
|
||||
@@ -2081,29 +2178,30 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
value = value.to_dict()
|
||||
elif not isinstance(value, dict):
|
||||
try:
|
||||
obj_map: Dict[str, Any] = {}
|
||||
obj_map: Dict[str,
|
||||
Any] = {}
|
||||
for k in (
|
||||
"hash",
|
||||
"store",
|
||||
"provider",
|
||||
"prov",
|
||||
"tag",
|
||||
"title",
|
||||
"url",
|
||||
"source_url",
|
||||
"duration",
|
||||
"duration_seconds",
|
||||
"metadata",
|
||||
"full_metadata",
|
||||
"warnings",
|
||||
"path",
|
||||
"target",
|
||||
"relationships",
|
||||
"is_temp",
|
||||
"action",
|
||||
"parent_hash",
|
||||
"extra",
|
||||
"media_kind",
|
||||
"hash",
|
||||
"store",
|
||||
"provider",
|
||||
"prov",
|
||||
"tag",
|
||||
"title",
|
||||
"url",
|
||||
"source_url",
|
||||
"duration",
|
||||
"duration_seconds",
|
||||
"metadata",
|
||||
"full_metadata",
|
||||
"warnings",
|
||||
"path",
|
||||
"target",
|
||||
"relationships",
|
||||
"is_temp",
|
||||
"action",
|
||||
"parent_hash",
|
||||
"extra",
|
||||
"media_kind",
|
||||
):
|
||||
if hasattr(value, k):
|
||||
obj_map[k] = getattr(value, k)
|
||||
@@ -2118,7 +2216,8 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
store_val = value.get("store") or "PATH"
|
||||
if not store_val or store_val == "PATH":
|
||||
try:
|
||||
extra_store = value.get("extra", {}).get("store")
|
||||
extra_store = value.get("extra",
|
||||
{}).get("store")
|
||||
except Exception:
|
||||
extra_store = None
|
||||
if extra_store:
|
||||
@@ -2150,7 +2249,10 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
extra = {k: v for k, v in value.items() if k not in known_keys}
|
||||
extra = {
|
||||
k: v
|
||||
for k, v in value.items() if k not in known_keys
|
||||
}
|
||||
|
||||
# Extract URL: prefer direct url field, then url list
|
||||
from metadata import normalize_urls
|
||||
@@ -2177,17 +2279,16 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
# Only use target as path if it's not a URL (url should stay in url field)
|
||||
if not path_val and "target" in value:
|
||||
target = value["target"]
|
||||
if target and not (
|
||||
isinstance(target, str)
|
||||
and (target.startswith("http://") or target.startswith("https://"))
|
||||
):
|
||||
if target and not (isinstance(target,
|
||||
str) and (target.startswith("http://")
|
||||
or target.startswith("https://"))):
|
||||
path_val = target
|
||||
|
||||
# If the path value is actually a URL, move it to url_val and clear path_val
|
||||
try:
|
||||
if isinstance(path_val, str) and (
|
||||
path_val.startswith("http://") or path_val.startswith("https://")
|
||||
):
|
||||
if isinstance(path_val,
|
||||
str) and (path_val.startswith("http://")
|
||||
or path_val.startswith("https://")):
|
||||
# Prefer existing url_val if present, otherwise move path_val into url_val
|
||||
if not url_val:
|
||||
url_val = path_val
|
||||
@@ -2203,9 +2304,9 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
hash=hash_val,
|
||||
store=store_val,
|
||||
provider=str(
|
||||
value.get("provider") or value.get("prov") or extra.get("provider") or ""
|
||||
).strip()
|
||||
or None,
|
||||
value.get("provider") or value.get("prov") or extra.get("provider")
|
||||
or ""
|
||||
).strip() or None,
|
||||
tag=tag_val,
|
||||
title=title_val,
|
||||
url=url_val,
|
||||
@@ -2215,7 +2316,8 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
warnings=list(value.get("warnings") or []),
|
||||
path=path_val,
|
||||
relationships=rels,
|
||||
is_temp=bool(value.get("is_temp", False)),
|
||||
is_temp=bool(value.get("is_temp",
|
||||
False)),
|
||||
action=value.get("action"),
|
||||
parent_hash=value.get("parent_hash"),
|
||||
extra=extra,
|
||||
@@ -2270,7 +2372,11 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
return pipe_obj
|
||||
|
||||
|
||||
def register_url_with_local_library(pipe_obj: models.PipeObject, config: Dict[str, Any]) -> bool:
|
||||
def register_url_with_local_library(
|
||||
pipe_obj: models.PipeObject,
|
||||
config: Dict[str,
|
||||
Any]
|
||||
) -> bool:
|
||||
"""Register url with a file in the local library database.
|
||||
|
||||
This is called automatically by download cmdlet to ensure url are persisted
|
||||
@@ -2285,7 +2391,7 @@ def register_url_with_local_library(pipe_obj: models.PipeObject, config: Dict[st
|
||||
"""
|
||||
|
||||
try:
|
||||
from config import get_local_storage_path
|
||||
from SYS.config import get_local_storage_path
|
||||
from API.folder import API_folder_store
|
||||
|
||||
file_path = get_field(pipe_obj, "path")
|
||||
|
||||
Reference in New Issue
Block a user