On 2020/04/20 9:13, Branko Čibej wrote: > On 19.04.2020 23:58, Yasuhito FUTATSUKI wrote:
<snip> >> On 2020/04/19 22:53, Branko Čibej wrote: >>> On 19.04.2020 14:47, Johan Corveleyn wrote: >>>> Would you also have an idea on how to fix the PYTHONLEGACYWINDOWSSTDIO >>>> issue? >>>> I mean: would it ever be possible to run the testsuite without >>>> defining that envvar? Or will that remain necessary? <snip> >> If reconstruction of _io._WindowsConsoleIO from stored old descripor is >> allowed (i.e. documented in the specification), it seems to be possible >> to write work around. > > > Given that these are private symbols, at least according to their names, > they could change in any minor Python version. :( Yes, indeed. However, at least on Python 3.6.6, if given file descptor 1 is pointing to tty, the result of open(1, 'w', encoding='utf-8', closefd=False).buffer.raw is _io._WindowsConsoleIO object, and it seems to be able to used for console output. So I wrote a patch for testing (not for commit. it is need to brush up even if it can work). At least it should work (no regression) on Python 2.7, Python 3 with and without PYTHONLEGACYWINDOWSSTDIO on Windows. (I confirmed on Python 2.7 and Python 3.7 on FreeBSD). Thanks, -- Yasuhito FUTATSUKI <futat...@poem.co.jp>
Index: build/run_tests.py =================================================================== --- build/run_tests.py (revision 1876712) +++ build/run_tests.py (working copy) @@ -48,6 +48,7 @@ ''' import os, sys, shutil, codecs +import io import re import logging import optparse, subprocess, threading, traceback @@ -844,6 +845,12 @@ # setup the output pipes if self.log: + need_stdout_reconstruct = ( isinstance(sys.stdout, io.IOBase) + and not isinstance(sys.stdout.buffer.raw, + io.FileIO)) + need_stderr_reconstruct = ( isinstance(sys.stderr, io.IOBase) + and not isinstance(sys.stderr.buffer.raw, + io.FileIO)) sys.stdout.flush() sys.stderr.flush() self.log.flush() @@ -851,6 +858,12 @@ old_stderr = os.dup(sys.stderr.fileno()) os.dup2(self.log.fileno(), sys.stdout.fileno()) os.dup2(self.log.fileno(), sys.stderr.fileno()) + if need_stdout_reconstruct: + sys.stdout = open(sys.stdout.fileno(), 'w', encoding='utf-8', + errors='replace', closefd=False) + if need_stderr_reconstruct: + sys.stderr = open(sys.stderr.fileno(), 'w', encoding='utf-8', + errors='replace', closefd=False) # These have to be class-scoped for use in the progress_func() self.dots_written = 0 @@ -897,6 +910,12 @@ os.dup2(old_stderr, sys.stderr.fileno()) os.close(old_stdout) os.close(old_stderr) + if need_stdout_reconstruct: + sys.stdout = open(sys.stdout.fileno(), 'w', encoding='utf-8', + errors='replace', closefd=False) + if need_stderr_reconstruct: + sys.stderr = open(sys.stderr.fileno(), 'w', encoding='utf-8', + errors='replace', closefd=False) return failed