Log: a console that cannot print a file name no longer fails the run that mentioned it

A clip called in Japanese on a machine with an ASCII console raised UnicodeEncodeError out of log.info, inside Load Media.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BzJLJWVu7RZnbRqm3nYAnX
This commit is contained in:
Claude
2026-10-27 09:12:39 +00:00
parent 3a2d64c792
commit d277ebc76c
3 changed files with 36 additions and 1 deletions
+14 -1
View File
@@ -120,6 +120,19 @@ def _paint(level: str, text: str) -> str:
return f"{code}{text}\x1b[0m" if code and _colour_wanted() else text
def _say(text: str) -> None:
"""Print to the console, never raising. A console that is not UTF-8 (a rental's ASCII locale, a redirected pipe)
cannot print a Japanese file name; that must cost the characters, not the generation that was only mentioning it."""
try:
print(text, file=sys.stderr, flush=True)
except UnicodeEncodeError:
enc = getattr(sys.stderr, "encoding", None) or "ascii"
try:
print(text.encode(enc, errors="replace").decode(enc, errors="replace"), file=sys.stderr, flush=True)
except Exception: # noqa: BLE001 -- the Log window still has the record
pass
def record(level: str, source: str, message: str) -> dict:
# Imported here rather than at module level: `run` starts a run by clearing
# what this module holds, so a top-level import would be circular.
@@ -128,7 +141,7 @@ def record(level: str, source: str, message: str) -> dict:
"message": message, "run": run_mod.current()}
_records.append(entry)
_keep(entry)
print(_paint(level, line(level, source, message)), file=sys.stderr, flush=True)
_say(_paint(level, line(level, source, message)))
return entry
+9
View File
@@ -227,3 +227,12 @@ def test_colour_codes_never_reach_the_panel(monkeypatch):
monkeypatch.setattr(backend_log, "_memory", lambda: deque([{"m": painted + "\n"}]))
answer = backend_log.recent()
assert answer["lines"] == ["[Log] Warning: x | y"] and answer["tones"] == ["warn"]
def test_a_console_that_cannot_encode_a_name_does_not_raise(monkeypatch):
import io
import sys
from core import log
monkeypatch.setattr(sys, "stderr", io.TextIOWrapper(io.BytesIO(), encoding="ascii"))
entry = log.info("FunUI Load Media", "loaded 日本語.mp4")
assert "日本語" in entry["message"] # the Log window keeps the real characters
@@ -164,3 +164,16 @@ def test_a_cut_that_leaves_nothing_is_explained_and_a_picture_input_reads_one_fr
FunUILoadMedia.execute(mid, full=True, prepare=json.dumps({"skip_first": 100})).result
image, _, _ = FunUILoadMedia.execute(mid).result
assert image.shape == (1, 48, 64, 3)
def test_a_japanese_file_name_loads_even_when_the_console_cannot_print_it(store, monkeypatch):
"""A rental whose console is ASCII must not fail a generation because a clip is called 日本語.mp4."""
import io
import sys
from modules.media.load.nodes import FunUILoadMedia
mid = _long_clip(store)
media.rename(mid, "日本語の動画 カタカナ.mp4")
console = io.TextIOWrapper(io.BytesIO(), encoding="ascii")
monkeypatch.setattr(sys, "stderr", console)
image, frames, _ = FunUILoadMedia.execute(mid, full=True, prepare='{"frame_cap": 3}').result
assert frames.shape[0] == 3 and image.shape[0] == 1