diff --git a/CLI.py b/CLI.py index 38da600..089925c 100644 --- a/CLI.py +++ b/CLI.py @@ -1194,17 +1194,26 @@ class CmdletExecutor: "get_relationship", "get-file", "get_file", + "get-metadata", + "get_metadata", } self_managing_commands = { "get-tag", "get_tag", "tags", + "get-metadata", + "get_metadata", "search-file", "search_file", } if cmd_name in self_managing_commands: - table = ctx.get_last_result_table() + table = ( + ctx.get_display_table() + if hasattr(ctx, "get_display_table") else None + ) + if table is None: + table = ctx.get_last_result_table() if table is None: table = Table(table_title) for emitted in emits: @@ -1249,8 +1258,9 @@ class CmdletExecutor: progress_ui = None pipe_idx = None - stdout_console().print() - stdout_console().print(table) + if not getattr(table, "_rendered_by_cmdlet", False): + stdout_console().print() + stdout_console().print(table) # If the cmdlet produced a current-stage table without emits (e.g. format selection), # render it here for parity with REPL pipeline runner. diff --git a/cmdlet/_shared.py b/cmdlet/_shared.py index 0e3a202..c593fee 100644 --- a/cmdlet/_shared.py +++ b/cmdlet/_shared.py @@ -3520,32 +3520,6 @@ def check_url_exists_in_storage( continue if not backend_hits: - fallback_hits: List[Dict[str, Any]] = [] - try: - fallback_hits = backend.search("url:*", limit=200) or [] - except Exception: - fallback_hits = [] - - for hit in fallback_hits: - url_values = _extract_urls_from_hit(hit, backend, allow_backend_lookup=True) - - if not url_values: - continue - - matched = False - for url_value in url_values: - for needle in (needles or []): - if _match_normalized_url(str(needle or ""), str(url_value or "")): - matched = True - break - if matched: - break - - if not matched: - continue - - return _build_display_row_for_hit(hit, backend_name, original_url) - return None hit = backend_hits[0] diff --git a/cmdlet/download_file.py b/cmdlet/download_file.py index e5d0009..ae55d44 100644 --- a/cmdlet/download_file.py +++ b/cmdlet/download_file.py @@ -1019,7 +1019,8 @@ class Download_File(Cmdlet): return None try: - idx = int(str(query_format).lstrip("#").strip()) + s_val = str(query_format).strip() + idx = int(s_val.lstrip("#")) except Exception: raise ValueError(f"Invalid format index: {query_format}") @@ -1032,6 +1033,12 @@ class Download_File(Cmdlet): if not fmts: raise ValueError("Unable to list formats for the URL; cannot resolve numeric format index") + # Prioritize exact format_id match if it's a numeric string that happens to be an ID + # (e.g. YouTube's 251 for opus). + if s_val and not s_val.startswith("#"): + if any(str(f.get("format_id", "")) == s_val for f in fmts): + return s_val + candidate_formats = [f for f in fmts if self._is_browseable_format(f)] filtered_formats = candidate_formats if candidate_formats else list(fmts) @@ -1461,13 +1468,15 @@ class Download_File(Cmdlet): for url in supported_url: try: - debug(f"[download-file] Processing URL in loop (1/3 stage 1): {url}") + debug(f"[download-file] Processing URL in loop: {url}") - canonical_url = self._canonicalize_url_for_storage( - requested_url=url, - ytdlp_tool=ytdlp_tool, - playlist_items=playlist_items, - ) + canonical_url = url + if not skip_per_url_preflight or clip_ranges: + canonical_url = self._canonicalize_url_for_storage( + requested_url=url, + ytdlp_tool=ytdlp_tool, + playlist_items=playlist_items, + ) if not skip_per_url_preflight: debug(f"[download-file] Running duplicate preflight for: {canonical_url}") @@ -1963,52 +1972,27 @@ class Download_File(Cmdlet): ytdl_format = query_format playlist_selection_handled = False - if len(supported_url) == 1 and not playlist_items and not ytdl_format: + if len(supported_url) == 1 and not playlist_items: candidate_url = supported_url[0] - if query_format and not query_wants_audio: + # If query_format is provided and numeric, resolve it now. + if query_format and not query_wants_audio and not ytdl_format: try: - debug(f"[download-file] Resolving numeric format for {candidate_url}...") + debug(f"[download-file] Resolving format for {candidate_url} (query='{query_format}')...") idx_fmt = self._format_id_for_query_index(query_format, candidate_url, formats_cache, ytdlp_tool) + if idx_fmt: + debug(f"Resolved format selection '{query_format}' -> {idx_fmt}") + ytdl_format = idx_fmt except ValueError as e: - log(f"Error parsing format selection: {e}", file=sys.stderr) - return 1 - if idx_fmt: - debug(f"Resolved numeric format selection '{query_format}' -> {idx_fmt}") - ytdl_format = idx_fmt + # Fallback: Treat as literal format if resolution fails or it's not a valid row index. + debug(f"Format resolution for '{query_format}' failed ({e}); treating as literal.") + ytdl_format = query_format if not ytdl_format: debug(f"[download-file] Checking for playlist at {candidate_url}...") if self._maybe_show_playlist_table(url=candidate_url, ytdlp_tool=ytdlp_tool): playlist_selection_handled = True - try: - last_table = pipeline_context.get_last_result_table() if hasattr(pipeline_context, "get_last_result_table") else None - if hasattr(last_table, "rows") and getattr(last_table, "rows", None): - sample_index = 1 - sample_fmt_id = None - try: - sample_row = last_table.rows[0] - sample_fmt_id = sample_row._full_metadata.get("item_selector") if getattr(sample_row, "_full_metadata", None) else None - except Exception: - sample_fmt_id = None - - try: - sample_pipeline = f'download-file "{candidate_url}"' - hint = ( - "To select non-interactively, re-run with an explicit format: " - "e.g. mm \"{pipeline} -query 'format:{fmt}' | add-file -store \" or " - "mm \"{pipeline} -query 'format:{index}' | add-file -store \"" - ).format( - pipeline=sample_pipeline, - fmt=sample_fmt_id or "", - index=sample_index, - ) - log(hint, file=sys.stderr) - except Exception: - pass - except Exception: - pass - + # ... (existing logging code) ... return 0 skip_per_url_preflight = False diff --git a/cmdlet/get_tag.py b/cmdlet/get_tag.py index 739b14f..9434dbb 100644 --- a/cmdlet/get_tag.py +++ b/cmdlet/get_tag.py @@ -1829,9 +1829,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int: payload["service_name"] = service_name_override return payload - raw_result_tags = get_field(result, "tag", None) - if not isinstance(raw_result_tags, list): - raw_result_tags = get_field(result, "tags", None) + raw_result_tags = _resolve_subject_value("tag", "tags") display_tags: List[str] = [] if isinstance(raw_result_tags, list): display_tags = [str(t) for t in raw_result_tags if t is not None]