Skip to content

Instantly share code, notes, and snippets.

@jun66j5
Last active May 8, 2020 09:39
Show Gist options
  • Save jun66j5/b0b0f97d9b7a4cbf13d8efcfbde5466d to your computer and use it in GitHub Desktop.
Save jun66j5/b0b0f97d9b7a4cbf13d8efcfbde5466d to your computer and use it in GitHub Desktop.
* 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