Author: svn-role Date: Wed Dec 16 04:00:27 2020 New Revision: 1884484 URL: http://svn.apache.org/viewvc?rev=1884484&view=rev Log: Merge r1883337 from trunk:
* r1883337 Remove uses of os.dup2() from run_tests.py in order to adapt the new console reader and writer on Windows since Python 3.6. Justification: PYTHONLEGACYWINDOWSSTDIO is no longer needed to run unit tests on Windows. Votes: +1: jun66j5, jcorvel Modified: subversion/branches/1.14.x/ (props changed) subversion/branches/1.14.x/STATUS subversion/branches/1.14.x/build/run_tests.py subversion/branches/1.14.x/subversion/tests/cmdline/svntest/main.py Propchange: subversion/branches/1.14.x/ ------------------------------------------------------------------------------ Merged /subversion/trunk:r1883337 Modified: subversion/branches/1.14.x/STATUS URL: http://svn.apache.org/viewvc/subversion/branches/1.14.x/STATUS?rev=1884484&r1=1884483&r2=1884484&view=diff ============================================================================== --- subversion/branches/1.14.x/STATUS (original) +++ subversion/branches/1.14.x/STATUS Wed Dec 16 04:00:27 2020 @@ -110,11 +110,3 @@ Veto-blocked changes: Approved changes: ================= - - * r1883337 - Remove uses of os.dup2() from run_tests.py in order to adapt the new - console reader and writer on Windows since Python 3.6. - Justification: - PYTHONLEGACYWINDOWSSTDIO is no longer needed to run unit tests on Windows. - Votes: - +1: jun66j5, jcorvel Modified: subversion/branches/1.14.x/build/run_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.14.x/build/run_tests.py?rev=1884484&r1=1884483&r2=1884484&view=diff ============================================================================== --- subversion/branches/1.14.x/build/run_tests.py (original) +++ subversion/branches/1.14.x/build/run_tests.py Wed Dec 16 04:00:27 2020 @@ -47,7 +47,7 @@ and filename of a test program, optional separated list of test numbers; the default is to run all the tests in it. ''' -import os, sys, shutil, codecs +import os, sys, shutil import re import logging import optparse, subprocess, threading, traceback @@ -141,6 +141,18 @@ def ensure_str(s): else: return s.decode("latin-1") +def open_logfile(filename, mode, encoding='utf-8'): + if sys.version_info[0] != 2: + return open(filename, mode, encoding=encoding, errors='surrogateescape') + else: + class Wrapper(object): + def __init__(self, stream, encoding): + self._stream = stream + self.encoding = encoding + def __getattr__(self, name): + return getattr(self._stream, name) + return Wrapper(open(filename, mode), encoding) + class TestHarness: '''Test harness for Subversion tests. ''' @@ -700,7 +712,7 @@ class TestHarness: # Copy the truly interesting verbose logs to a separate file, for easier # viewing. if xpassed or failed_list: - faillog = codecs.open(self.faillogfile, 'w', encoding="latin-1") + faillog = open_logfile(self.faillogfile, 'w') last_start_lineno = None last_start_re = re.compile('^(FAIL|SKIP|XFAIL|PASS|START|CLEANUP|END):') for lineno, line in enumerate(log_lines): @@ -733,7 +745,7 @@ class TestHarness: 'Open the log file with the required MODE.' if self.logfile: self._close_log() - self.log = codecs.open(self.logfile, mode, encoding="latin-1") + self.log = open_logfile(self.logfile, mode) def _close_log(self): 'Close the log file.' @@ -843,14 +855,13 @@ class TestHarness: sys.exit(1) # setup the output pipes + old_stdout = sys.stdout.fileno() if self.log: sys.stdout.flush() sys.stderr.flush() self.log.flush() - old_stdout = os.dup(sys.stdout.fileno()) - old_stderr = os.dup(sys.stderr.fileno()) - os.dup2(self.log.fileno(), sys.stdout.fileno()) - os.dup2(self.log.fileno(), sys.stderr.fileno()) + saved_stds = sys.stdout, sys.stderr + sys.stdout = sys.stderr = self.log # These have to be class-scoped for use in the progress_func() self.dots_written = 0 @@ -891,12 +902,8 @@ class TestHarness: # restore some values if self.log: - sys.stdout.flush() - sys.stderr.flush() - os.dup2(old_stdout, sys.stdout.fileno()) - os.dup2(old_stderr, sys.stderr.fileno()) - os.close(old_stdout) - os.close(old_stderr) + self.log.flush() + sys.stdout, sys.stderr = saved_stds return failed Modified: subversion/branches/1.14.x/subversion/tests/cmdline/svntest/main.py URL: http://svn.apache.org/viewvc/subversion/branches/1.14.x/subversion/tests/cmdline/svntest/main.py?rev=1884484&r1=1884483&r2=1884484&view=diff ============================================================================== --- subversion/branches/1.14.x/subversion/tests/cmdline/svntest/main.py (original) +++ subversion/branches/1.14.x/subversion/tests/cmdline/svntest/main.py Wed Dec 16 04:00:27 2020 @@ -2080,6 +2080,23 @@ class AbbreviatedFormatter(logging.Forma record.levelshort = self._level_short[record.levelno] return logging.Formatter.format(self, record) + +class LoggingStdoutHandler(logging.StreamHandler): + """ + The handler is always writing using sys.stdout at call time rather than the + value of sys.stdout at construction time. + + Inspired by logging._StderrHandler on Python 3. + """ + + def __init__(self, level=logging.NOTSET): + logging.Handler.__init__(self, level) + + @property + def stream(self): + return sys.stdout + + def _create_parser(usage=None): """Return a parser for our test suite.""" @@ -2272,7 +2289,7 @@ def parse_options(arglist=sys.argv[1:], datefmt='%Y-%m-%d %H:%M:%S') else: formatter = AbbreviatedFormatter('%(levelshort)s: %(message)s') - handler = logging.StreamHandler(sys.stdout) + handler = LoggingStdoutHandler() handler.setFormatter(formatter) logger.addHandler(handler)