khh
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
This commit is contained in:
@@ -1328,6 +1328,38 @@ def _unique_destination_path(dest: Path) -> Path:
|
||||
return dest
|
||||
|
||||
|
||||
def _print_live_safe_stderr(message: str) -> None:
|
||||
"""Print to stderr without breaking Rich Live progress output."""
|
||||
try:
|
||||
from rich_display import stderr_console # type: ignore
|
||||
except Exception:
|
||||
return
|
||||
|
||||
cm = None
|
||||
try:
|
||||
import pipeline as _pipeline_ctx # type: ignore
|
||||
suspend = getattr(_pipeline_ctx, "suspend_live_progress", None)
|
||||
cm = suspend() if callable(suspend) else None
|
||||
except Exception:
|
||||
cm = None
|
||||
|
||||
try:
|
||||
from contextlib import nullcontext
|
||||
except Exception:
|
||||
nullcontext = None # type: ignore
|
||||
if cm is None:
|
||||
cm = nullcontext() if callable(nullcontext) else None
|
||||
|
||||
try:
|
||||
if cm is not None:
|
||||
with cm:
|
||||
stderr_console.print(str(message))
|
||||
else:
|
||||
stderr_console.print(str(message))
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
||||
def apply_output_path_from_pipeobjects(
|
||||
*,
|
||||
cmd_name: str,
|
||||
@@ -1350,6 +1382,16 @@ def apply_output_path_from_pipeobjects(
|
||||
if not dest_raw:
|
||||
return list(emits or [])
|
||||
|
||||
# Guard: users sometimes pass a URL into -path by mistake (e.g. `-path https://...`).
|
||||
# Treat that as invalid for filesystem moves and avoid breaking Rich Live output.
|
||||
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}")
|
||||
return list(emits or [])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cmd_norm = str(cmd_name or "").replace("_", "-").strip().lower()
|
||||
if not cmd_norm:
|
||||
return list(emits or [])
|
||||
@@ -1410,7 +1452,7 @@ def apply_output_path_from_pipeobjects(
|
||||
try:
|
||||
dest_dir.mkdir(parents=True, exist_ok=True)
|
||||
except Exception as exc:
|
||||
log(f"Failed to create destination directory: {dest_dir} ({exc})", file=sys.stderr)
|
||||
_print_live_safe_stderr(f"Failed to create destination directory: {dest_dir} ({exc})")
|
||||
return items
|
||||
|
||||
for idx, src in zip(artifact_indices, artifact_paths):
|
||||
@@ -1418,15 +1460,18 @@ 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))
|
||||
_print_saved_output_panel(items[idx], final)
|
||||
continue
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
shutil.move(str(src), str(final))
|
||||
except Exception as exc:
|
||||
log(f"Failed to save output to {final}: {exc}", file=sys.stderr)
|
||||
_print_live_safe_stderr(f"Failed to save output to {final}: {exc}")
|
||||
continue
|
||||
_apply_saved_path_update(items[idx], old_path=str(src), new_path=str(final))
|
||||
_print_saved_output_panel(items[idx], final)
|
||||
|
||||
return items
|
||||
|
||||
@@ -1445,7 +1490,7 @@ def apply_output_path_from_pipeobjects(
|
||||
try:
|
||||
final.parent.mkdir(parents=True, exist_ok=True)
|
||||
except Exception as exc:
|
||||
log(f"Failed to create destination directory: {final.parent} ({exc})", file=sys.stderr)
|
||||
_print_live_safe_stderr(f"Failed to create destination directory: {final.parent} ({exc})")
|
||||
return items
|
||||
|
||||
final = _unique_destination_path(final)
|
||||
@@ -1453,13 +1498,89 @@ def apply_output_path_from_pipeobjects(
|
||||
if src.resolve() != final.resolve():
|
||||
shutil.move(str(src), str(final))
|
||||
except Exception as exc:
|
||||
log(f"Failed to save output to {final}: {exc}", file=sys.stderr)
|
||||
_print_live_safe_stderr(f"Failed to save output to {final}: {exc}")
|
||||
return items
|
||||
|
||||
_apply_saved_path_update(items[idx], old_path=str(src), new_path=str(final))
|
||||
_print_saved_output_panel(items[idx], final)
|
||||
return items
|
||||
|
||||
|
||||
def _print_saved_output_panel(item: Any, final_path: Path) -> None:
|
||||
"""When -path is used, print a Rich panel summarizing the saved output.
|
||||
|
||||
Shows: Title, Location, Hash.
|
||||
Best-effort: reads existing fields first to avoid recomputing hashes.
|
||||
"""
|
||||
try:
|
||||
from rich.panel import Panel # type: ignore
|
||||
from rich.table import Table # type: ignore
|
||||
from rich_display import stderr_console # type: ignore
|
||||
except Exception:
|
||||
return
|
||||
|
||||
# If Rich Live progress is active, pause it while printing so the panel
|
||||
# doesn't get overwritten/truncated by Live's cursor control.
|
||||
try:
|
||||
import pipeline as _pipeline_ctx # type: ignore
|
||||
suspend = getattr(_pipeline_ctx, "suspend_live_progress", None)
|
||||
cm = suspend() if callable(suspend) else None
|
||||
except Exception:
|
||||
cm = None
|
||||
|
||||
try:
|
||||
from contextlib import nullcontext
|
||||
except Exception:
|
||||
nullcontext = None # type: ignore
|
||||
|
||||
if cm is None:
|
||||
cm = nullcontext() if callable(nullcontext) else None
|
||||
|
||||
try:
|
||||
location = str(final_path)
|
||||
except Exception:
|
||||
location = ""
|
||||
|
||||
title = ""
|
||||
try:
|
||||
title = str(get_field(item, "title") or get_field(item, "name") or "").strip()
|
||||
except Exception:
|
||||
title = ""
|
||||
if not title:
|
||||
try:
|
||||
title = str(final_path.stem or final_path.name)
|
||||
except Exception:
|
||||
title = ""
|
||||
|
||||
file_hash = ""
|
||||
try:
|
||||
file_hash = str(get_field(item, "hash") or get_field(item, "sha256") or "").strip()
|
||||
except Exception:
|
||||
file_hash = ""
|
||||
if not file_hash:
|
||||
try:
|
||||
from SYS.utils import sha256_file # type: ignore
|
||||
file_hash = str(sha256_file(final_path) or "").strip()
|
||||
except Exception:
|
||||
file_hash = ""
|
||||
|
||||
grid = Table.grid(padding=(0, 1))
|
||||
grid.add_column(justify="right", style="bold")
|
||||
grid.add_column()
|
||||
grid.add_row("Title", title or "(unknown)")
|
||||
grid.add_row("Location", location or "(unknown)")
|
||||
grid.add_row("Hash", file_hash or "(unknown)")
|
||||
|
||||
try:
|
||||
if cm is not None:
|
||||
with cm:
|
||||
stderr_console.print(Panel(grid, title="Saved", expand=False))
|
||||
else:
|
||||
stderr_console.print(Panel(grid, title="Saved", expand=False))
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
||||
def _apply_saved_path_update(item: Any, *, old_path: str, new_path: str) -> None:
|
||||
"""Update a PipeObject-like item after its backing file has moved."""
|
||||
old_str = str(old_path)
|
||||
@@ -1952,9 +2073,6 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
extra=extra,
|
||||
)
|
||||
|
||||
# Debug: Print formatted table
|
||||
pipe_obj.debug_table()
|
||||
|
||||
return pipe_obj
|
||||
|
||||
# Fallback: build from path argument or bare value
|
||||
@@ -2000,9 +2118,6 @@ def coerce_to_pipe_object(value: Any, default_path: Optional[str] = None) -> mod
|
||||
extra={},
|
||||
)
|
||||
|
||||
# Debug: Print formatted table
|
||||
pipe_obj.debug_table()
|
||||
|
||||
return pipe_obj
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user