From 055c6bbd2e2b7985eae39acaed1a64e78c94aa8c Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Tue, 6 Oct 2026 06:51:01 +0000 Subject: [PATCH] Replace unencodable characters in stdout On Windows, a piped stdout uses the cp1252 encoding. Emoji in `spin python` output then raise UnicodeEncodeError. Assisted-by: Claude Code:claude-opus-5-5 --- spin/__main__.py | 5 +++++ spin/tests/test_build_cmds.py | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/spin/__main__.py b/spin/__main__.py index 6f665f8..6388346 100644 --- a/spin/__main__.py +++ b/spin/__main__.py @@ -1,6 +1,7 @@ import collections import importlib import importlib.util +import io import os import pathlib import sys @@ -42,6 +43,10 @@ def _detect_config_dir(path: pathlib.Path) -> pathlib.Path | None: def main(): + # Replace characters, such as emoji, that the stdout encoding cannot represent + if isinstance(sys.stdout, io.TextIOWrapper): + sys.stdout.reconfigure(errors="replace") + # Alias `spin help` to `spin --help` if (len(sys.argv) == 2) and (sys.argv[1] == "help"): sys.argv[1] = "--help" diff --git a/spin/tests/test_build_cmds.py b/spin/tests/test_build_cmds.py index 2091c80..5742acc 100644 --- a/spin/tests/test_build_cmds.py +++ b/spin/tests/test_build_cmds.py @@ -201,3 +201,12 @@ def test_parallel_builds(example_pkg): assert "build-install" in example_pkg_path assert "parallel/build-install" in example_pkg_parallel_path assert "parallel/build-install" not in example_pkg_path + + +@skip_py_lt_311 # python command does not run on older pythons +def test_unencodable_output(example_pkg): + # `spin python` prints an emoji, which ASCII cannot encode + p = spin( + "python", "--", "-c", "pass", env={**os.environ, "PYTHONIOENCODING": "ascii"} + ) + assert p.returncode == 0