fix(test-runner): native Windows venv probe + glyph-safe stdio

Two Windows fixes for the canonical test runner, salvaged from #66496:

- scripts/run_tests.sh: probe the native Windows venv layout
  (Scripts/activate → Scripts/python.exe) alongside bin/activate,
  adapted to main's pytest-import-guarded loop with SKIPPED_VENVS
  reporting. Without it a python -m venv / uv venv on Git Bash/MSYS is
  never found and the runner refuses to start.
- scripts/run_tests_parallel.py: _make_stdio_glyph_safe() reconfigures
  stdout/stderr to UTF-8 (errors=replace fallback) so the ✓/✗ progress
  glyphs cannot crash a cp1252 console when the runner is invoked
  directly (run_tests.sh's PYTHONUTF8=1 only covers the wrapped path).
  No-op on UTF-8 stdio. Ships 3 OS-independent cp1252 tests plus
  encoding=utf-8 in the runner-subprocess assertions.

Dropped from the original PR: the USERPROFILE/HOMEDRIVE/HOMEPATH/
SYSTEMROOT env-forwarding hunk — main's WIN_ENV loop already forwards
a superset (#67385/#70813).
This commit is contained in:
SmokeDev 2026-07-29 20:15:43 -07:00 committed by Teknium
parent 0860b9804f
commit 3e7a11ca2e
5 changed files with 122 additions and 3 deletions

View file

@ -648,7 +648,33 @@ def _slice_files(
return target
def _make_stdio_glyph_safe() -> None:
"""Keep status glyphs from killing the runner on narrow console encodings.
On native Windows, piped or legacy-console stdio defaults to a locale
codec (usually cp1252) that cannot encode the / progress glyphs the
first per-file status line then dies with UnicodeEncodeError before a
single test result is reported. Declare the runner's own output UTF-8
(what CI and every modern terminal already are), with errors="replace"
as the can't-crash backstop; where the encoding can't be changed, fall
back to errors="replace" alone so glyphs degrade to "?" instead of
killing the run. On already-UTF-8 stdio this is a no-op.
"""
for stream in (sys.stdout, sys.stderr):
reconfigure = getattr(stream, "reconfigure", None)
if reconfigure is None:
continue
try:
reconfigure(encoding="utf-8", errors="replace")
except Exception:
try:
reconfigure(errors="replace")
except Exception:
pass
def main() -> int:
_make_stdio_glyph_safe()
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,