Skip to content

v0.0.190

Choose a tag to compare

@aallan aallan released this 01 Jul 13:24
25a86df

[0.0.190] - 2026-07-01

Changed

  • Text I/O is UTF-8 regardless of the host locale, enforced by a gate (#645). Python's text-mode open() / Path.read_text() / Path.write_text() — and subprocess.run/Popen/check_output(..., text=True) captures — fall back to locale.getpreferredencoding() (cp1252 on en-US Windows) when no encoding= is given, so a Vera source / doc / fixture / program output containing , , or any non-ASCII byte failed on a locale-default Windows shell. #641 papered over CI with a PYTHONUTF8=1 backstop; this is the durable fix. A new scripts/check_explicit_encoding.py AST-audits every text-mode open() / read_text() / write_text() and every subprocess(..., text=True) capture under vera/, scripts/, tests/, requiring an explicit encoding="utf-8" literal (binary / bytes mode skipped; a deliberate exception opts out with # encoding-exempt: <reason>), wired into pre-commit and the CI lint job. It found and fixed 160 bare file-I/O sites across 16 files plus 97 subprocess text captures across 18 files (far more than the ~30 the issue estimated — the suite has grown ~5× since #641). The audit's scope also covers tempfile.NamedTemporaryFile / TemporaryFile / SpooledTemporaryFile opened in text mode (they default to binary, but a text one is a locale-encoded write just like open(..., "w") — the idiom test helpers use to stage .vera source containing / ; 29 such sites across 9 files fixed). The vera CLI reconfigures stdin as well as stdout/stderr to UTF-8 at startup, so a Vera program's non-ASCII output and input (e.g. IO.read_char on piped UTF-8) round-trip on any locale. Together these made text I/O locale-independent and the PYTHONUTF8=1 CI backstop (#641) was removed — verified by a clean Windows matrix with the backstop gone (the tempfile and stdin gaps were surfaced by that matrix, not the audit, which is why removing the backstop is its own acceptance test). Pinned by tests/test_check_explicit_encoding.py (checker logic, scope-discovery coverage, and a repo-clean assertion). (Folds in the stdio / subprocess work that had briefly been split to #832.)