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
 

Reply via email to