From f6d5404f45216c7290d6af60682d218b869a0432 Mon Sep 17 00:00:00 2001 From: GalaxyGamingFR <153150716+GalaxyGamingFR@users.noreply.github.com> Date: Sun, 11 Oct 2026 12:08:35 -0700 Subject: [PATCH] fix(stubgen): write LF to stdout on Windows When --out was not given, stubgen wrote the generated code and debt lines to sys.stdout, which translates LF to CRLF on Windows, so redirecting stdout produced CRLF files. stdout is now reconfigured to utf-8 with LF newlines, matching the --out path. A subprocess test checks the bytes on stdout. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01V9UU71SP1UKGR51Sowbgmq --- CMakeLists.txt | 2 ++ tools/stubgen.py | 1 + tools/tests/test_stubgen_stdout_newlines.py | 33 +++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tools/tests/test_stubgen_stdout_newlines.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dd30784f..947a79be5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,8 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_stubgen.py) add_test(NAME debt_split COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_debt_split.py) + add_test(NAME stubgen_stdout_newlines COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_stubgen_stdout_newlines.py) add_test(NAME hardware_oracle COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/hw-oracle/test_hw_oracle.py) add_test(NAME pr_overlap_exports COMMAND ${Python3_EXECUTABLE} diff --git a/tools/stubgen.py b/tools/stubgen.py index 492f485b5..444820d64 100644 --- a/tools/stubgen.py +++ b/tools/stubgen.py @@ -211,6 +211,7 @@ def main(argv=None): ap.add_argument("--td-out", required=False, default=None, help="output file for TechnicalDebt lines, which go in docs/dev/debt/MODULE.md, default stderr when code uses stdout, otherwise stdout") ap.add_argument("--td-only", action="store_true", help="print only TechnicalDebt lines, no code") args = ap.parse_args(argv) + sys.stdout.reconfigure(encoding="utf-8", newline="\n") try: if not args.td_only and args.out and args.td_out and same_file(args.out, args.td_out): ap.error("--out and --td-out must name different files") diff --git a/tools/tests/test_stubgen_stdout_newlines.py b/tools/tests/test_stubgen_stdout_newlines.py new file mode 100644 index 000000000..93b49efe1 --- /dev/null +++ b/tools/tests/test_stubgen_stdout_newlines.py @@ -0,0 +1,33 @@ +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + +tools = Path(__file__).resolve().parents[1] + + +class StubgenStdoutNewlineTests(unittest.TestCase): + def run_stubgen(self, *extra): + with tempfile.TemporaryDirectory() as d: + nids = Path(d) / "nids.txt" + nids.write_text("AC1FtjqMCL0\n", encoding="utf-8", newline="\n") + return subprocess.run( + [sys.executable, str(tools / "stubgen.py"), "--module", "libkernel", "--nids", str(nids)] + list(extra), + capture_output=True, + check=True, + ) + + def test_code_on_stdout_uses_lf(self): + result = self.run_stubgen() + self.assertIn(b"\n", result.stdout) + self.assertNotIn(b"\r\n", result.stdout) + + def test_td_only_on_stdout_uses_lf(self): + result = self.run_stubgen("--td-only") + self.assertIn(b"\n", result.stdout) + self.assertNotIn(b"\r\n", result.stdout) + + +if __name__ == "__main__": + unittest.main()