diff --git a/comfy_cli/command/custom_nodes/cm_cli_util.py b/comfy_cli/command/custom_nodes/cm_cli_util.py index 43894a79..c5060093 100644 --- a/comfy_cli/command/custom_nodes/cm_cli_util.py +++ b/comfy_cli/command/custom_nodes/cm_cli_util.py @@ -9,9 +9,9 @@ from functools import lru_cache import typer -from rich import print from comfy_cli.config_manager import ConfigManager +from comfy_cli.output import rprint as print # noqa: A001 - context-aware: stderr in JSON mode from comfy_cli.resolve_python import resolve_workspace_python from comfy_cli.uv import DependencyCompiler from comfy_cli.workspace_manager import WorkspaceManager, check_comfy_repo diff --git a/comfy_cli/command/generate/app.py b/comfy_cli/command/generate/app.py index ab6ab7fb..5f59d6ae 100644 --- a/comfy_cli/command/generate/app.py +++ b/comfy_cli/command/generate/app.py @@ -21,6 +21,14 @@ import httpx import typer + +# NOT migrated to `comfy_cli.output.rprint` on purpose. `generate` carries its own +# `--json` flag (see `_emit_result` / `output.print_json`) and never emits a +# renderer envelope on its submit/sync/resume paths. Routing these calls through +# the shim would send the command's *primary result* (job ids, image URLs) to +# stderr whenever stdout isn't a TTY, leaving stdout empty -- so `comfy generate +# ... > out.txt` would write an empty file. Migrate only once `generate` emits +# envelopes via the renderer. from rich import print as rprint from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn diff --git a/comfy_cli/command/generate/output.py b/comfy_cli/command/generate/output.py index 66eaedae..2d5a7e2b 100644 --- a/comfy_cli/command/generate/output.py +++ b/comfy_cli/command/generate/output.py @@ -11,6 +11,10 @@ from pathlib import Path import httpx + +# NOT migrated to `comfy_cli.output.rprint` on purpose: `print_urls` / `print_saved` +# are `generate`'s primary result, and `generate` emits no renderer envelope. See +# the note in `comfy_cli/command/generate/app.py`. from rich import print as rprint from comfy_cli.command.generate import client diff --git a/comfy_cli/command/pr_command.py b/comfy_cli/command/pr_command.py index 3105ce90..f21cbdbb 100644 --- a/comfy_cli/command/pr_command.py +++ b/comfy_cli/command/pr_command.py @@ -7,6 +7,13 @@ """ import typer + +# NOT migrated to `comfy_cli.output.rprint` on purpose. `pr list` renders its +# result through the module-level `console` below (plain Rich -> stdout) and emits +# no renderer envelope. Routing only these calls through the shim would split one +# command's output across two streams in JSON mode -- table on stdout, "no cached +# PR builds found" / cache settings on stderr. Migrate `console` and these calls +# together, once `pr` emits envelopes via the renderer. from rich import print as rprint from rich.console import Console from rich.table import Table diff --git a/comfy_cli/output/__init__.py b/comfy_cli/output/__init__.py index c8b6e7fe..d78ce1d5 100644 --- a/comfy_cli/output/__init__.py +++ b/comfy_cli/output/__init__.py @@ -5,10 +5,18 @@ `Renderer.resolve(...)` and stored as a process-wide singleton via `set_renderer`. Migration policy (Phase 1): -- Every existing ``from rich import print as rprint`` becomes +- A ``from rich import print as rprint`` whose output is a *log or hint* becomes ``from comfy_cli.output import rprint``. The shim suppresses stdout in JSON mode (redirecting to stderr so logs are still visible) and is byte-identical to rprint in pretty mode. +- A call site that prints a command's *primary result* must NOT be migrated + until that command emits a ``renderer.emit(...)`` envelope. ``resolve()`` + selects JSON mode whenever stdout is not a TTY, so migrating a result path + first would route the result to stderr and leave stdout empty -- e.g. + ``comfy generate ... > out.txt`` would write an empty file. The known + un-migrated result paths are ``command/generate/app.py``, + ``command/generate/output.py`` and ``command/pr_command.py``; each carries an + in-file comment saying so. - Commands that produce a structured result emit a final envelope with ``renderer.emit(data)``. This is the *only* thing on stdout in JSON mode. - Streaming commands emit ``renderer.event(type, **fields)`` events; one diff --git a/comfy_cli/output/preview.py b/comfy_cli/output/preview.py index 80c8028b..6f6a5e72 100644 --- a/comfy_cli/output/preview.py +++ b/comfy_cli/output/preview.py @@ -141,9 +141,10 @@ def _show_video_info(path: Path) -> None: size_bytes = int(fmt.get("size", 0)) size_mb = size_bytes / 1048576 - from rich import print as rprint from rich.panel import Panel + from comfy_cli.output import rprint + rprint( Panel( f"🎬 [bold]{path.name}[/bold]\n {w}×{h} · {fps:.0f}fps · {codec} · {duration:.1f}s · {size_mb:.1f}MB", diff --git a/comfy_cli/pr_cache.py b/comfy_cli/pr_cache.py index e0b63a6e..f35e637b 100644 --- a/comfy_cli/pr_cache.py +++ b/comfy_cli/pr_cache.py @@ -11,9 +11,8 @@ from datetime import datetime, timedelta from pathlib import Path -from rich import print as rprint - from comfy_cli.config_manager import ConfigManager +from comfy_cli.output import rprint class PRCache: diff --git a/comfy_cli/resolve_python.py b/comfy_cli/resolve_python.py index 2fbe5bd1..b0affcf3 100644 --- a/comfy_cli/resolve_python.py +++ b/comfy_cli/resolve_python.py @@ -6,7 +6,7 @@ import sys import sysconfig -from rich import print as rprint +from comfy_cli.output import rprint def _get_python_binary(env_path: str) -> str: diff --git a/comfy_cli/uv.py b/comfy_cli/uv.py index f1d89ae2..cb495a5b 100644 --- a/comfy_cli/uv.py +++ b/comfy_cli/uv.py @@ -23,7 +23,7 @@ def _check_call(cmd: list[str], cwd: PathLike | None = None): subprocess.check_call(cmd, cwd=cwd) except subprocess.CalledProcessError: if len(cmd) >= 5 and cmd[1:4] == ["-m", "uv", "pip"] and cmd[4] in ("install", "sync"): - from rich import print as rprint + from comfy_cli.output import rprint rprint( "\n[bold yellow]Hint:[/bold yellow] If you are on a network filesystem "