What
conductor doctor's default table output dies on a cp1252 console, part-written.
doctor.py hardcodes three glyphs that cp1252 cannot encode:
_CHECK = "[green]✓[/green]" # U+2713
_CROSS = "[red]✗[/red]" # U+2717
_OPTIONAL_MARK = "○" # U+25CB
Verified — all three raise UnicodeEncodeError under cp1252. (_DASH, U+2014, is encodable at 0x97 and is fine.)
Why it is worse than one bad line
_render_env and _render_providers are separate console.print() calls, so stdout is left truncated mid-report rather than failing cleanly. And it lands on precisely the person least able to absorb it: someone who ran doctor because they hit #342.
Scope
#381 fixes the JSON sinks (--json is safe via ensure_ascii=True) and deliberately leaves the table path alone, because every glyph consumer would need the console threaded through it — roughly 18 call sites across _render_env, _render_providers and six _*_cell helpers, none of which currently take a console.
Suggested shape
Select glyphs once from the console's stream encoding and pass them down, falling back to ASCII (OK / X / o) when the stream cannot represent them:
def _encodable(text: str, console: Console) -> bool:
encoding = getattr(getattr(console, "file", None), "encoding", None)
if not encoding:
return True
try:
text.encode(encoding)
except (UnicodeEncodeError, LookupError):
return False
return True
Rich does not check this itself — it hands the string to the underlying file, so the error surfaces from the write, after part of the report is already out.
Repro
PYTHONIOENCODING=cp1252 conductor doctor
# exit 1, stdout ends after the Environment table
What
conductor doctor's default table output dies on acp1252console, part-written.doctor.pyhardcodes three glyphs that cp1252 cannot encode:Verified — all three raise
UnicodeEncodeErrorundercp1252. (_DASH, U+2014, is encodable at0x97and is fine.)Why it is worse than one bad line
_render_envand_render_providersare separateconsole.print()calls, so stdout is left truncated mid-report rather than failing cleanly. And it lands on precisely the person least able to absorb it: someone who randoctorbecause they hit #342.Scope
#381 fixes the JSON sinks (
--jsonis safe viaensure_ascii=True) and deliberately leaves the table path alone, because every glyph consumer would need the console threaded through it — roughly 18 call sites across_render_env,_render_providersand six_*_cellhelpers, none of which currently take a console.Suggested shape
Select glyphs once from the console's stream encoding and pass them down, falling back to ASCII (
OK/X/o) when the stream cannot represent them:Rich does not check this itself — it hands the string to the underlying file, so the error surfaces from the write, after part of the report is already out.
Repro
PYTHONIOENCODING=cp1252 conductor doctor # exit 1, stdout ends after the Environment table