Last active
May 8, 2020 09:39
-
-
Save jun66j5/b0b0f97d9b7a4cbf13d8efcfbde5466d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* build/run_tests.py | |
(open_logfile): New function returning file-like object which is reassignable | |
sys.stdout and sys.stderr. | |
(TestHarness.run): Use open_logfile() instead of codecs.open(). | |
(TestHarness._open_log): Ditto. | |
(TestHarness._run_py_test): Reassign sys.stdout and sys.stderr instead of | |
uses of os.dup2(). | |
* subversion/tests/cmdline/svntest/main.py | |
(LoggingStdoutHandler): New function to use the value of sys.stdout at call | |
time. | |
(parse_options): Use LoggingStdoutHandler() instead of | |
StreamHandler(sys.stdout). | |
Index: build/run_tests.py | |
=================================================================== | |
--- build/run_tests.py (revision 1877480) | |
+++ build/run_tests.py (working copy) | |
@@ -47,7 +47,7 @@ | |
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 @@ | |
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 @@ | |
# 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 @@ | |
'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 @@ | |
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 @@ | |
# 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 | |
Index: subversion/tests/cmdline/svntest/main.py | |
=================================================================== | |
--- subversion/tests/cmdline/svntest/main.py (revision 1877480) | |
+++ subversion/tests/cmdline/svntest/main.py (working copy) | |
@@ -2084,6 +2084,23 @@ | |
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.""" | |
@@ -2276,7 +2293,7 @@ | |
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) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment