fix(windows): add ensure_utf8_streams() for Windows GBK encoding + ConPTY docs
- Add ensure_utf8_streams() in output.py: reconfigures stdout/stderr to UTF-8 on Windows at CLI startup, fixing emoji UnicodeEncodeError on GBK locales - Call ensure_utf8_streams() in cli() entry point — one-line fix for all output paths (click.echo, rich Console, print) - Add Windows ConPTY troubleshooting to README (English + Chinese): document Git Bash workaround, ConPTY pipe capture issue, and encoding notes Ref: #29 (issuecomment-4065690862)
This commit is contained in:
@@ -61,6 +61,7 @@ from .output import (
|
||||
default_structured_format,
|
||||
emit_error,
|
||||
emit_structured,
|
||||
ensure_utf8_streams,
|
||||
error_payload,
|
||||
structured_output_options,
|
||||
success_payload,
|
||||
@@ -303,6 +304,7 @@ def _run_write_command(
|
||||
def cli(ctx, verbose, compact):
|
||||
# type: (Any, bool, bool) -> None
|
||||
"""twitter — Twitter/X CLI tool 🐦"""
|
||||
ensure_utf8_streams()
|
||||
_setup_logging(verbose)
|
||||
ctx.ensure_object(dict)
|
||||
ctx.obj["compact"] = compact
|
||||
|
||||
@@ -14,6 +14,27 @@ _OUTPUT_ENV = "OUTPUT"
|
||||
_SCHEMA_VERSION = "1"
|
||||
|
||||
|
||||
def ensure_utf8_streams() -> None:
|
||||
"""Reconfigure stdout/stderr to use UTF-8 encoding on Windows.
|
||||
|
||||
On Windows with ConPTY disabled (e.g. winpty fallback + PowerShell),
|
||||
the default encoding may be GBK/cp936 which cannot encode emoji.
|
||||
Calling reconfigure(encoding='utf-8') once at startup fixes ALL
|
||||
output paths — click.echo, rich Console, and plain print — without
|
||||
needing per-call wrappers.
|
||||
|
||||
This is a no-op on Unix (already UTF-8) and safe to call multiple times.
|
||||
"""
|
||||
if sys.platform != "win32":
|
||||
return
|
||||
for stream in (sys.stdout, sys.stderr):
|
||||
if hasattr(stream, "reconfigure"):
|
||||
try:
|
||||
stream.reconfigure(encoding="utf-8")
|
||||
except Exception:
|
||||
pass # frozen or non-standard stream, skip
|
||||
|
||||
|
||||
def default_structured_format(*, as_json: bool, as_yaml: bool) -> str | None:
|
||||
"""Resolve explicit flags first, then env override, then TTY default."""
|
||||
if as_json and as_yaml:
|
||||
@@ -126,3 +147,4 @@ def emit_error(
|
||||
else:
|
||||
click.echo(yaml.safe_dump(payload, allow_unicode=True, sort_keys=False, default_flow_style=False))
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user