Commit 047a1d83 authored by Stefan Behnel's avatar Stefan Behnel

move file descriptor redirecting to Cython.Utils package and use it as context...

move file descriptor redirecting to Cython.Utils package and use it as context manager in test runner
parent bde66547
...@@ -8,6 +8,7 @@ import sys ...@@ -8,6 +8,7 @@ import sys
import re import re
import io import io
import codecs import codecs
from contextlib import contextmanager
modification_time = os.path.getmtime modification_time = os.path.getmtime
...@@ -344,3 +345,38 @@ def get_cython_cache_dir(): ...@@ -344,3 +345,38 @@ def get_cython_cache_dir():
# last fallback: ~/.cython # last fallback: ~/.cython
return os.path.expanduser(os.path.join('~', '.cython')) return os.path.expanduser(os.path.join('~', '.cython'))
@contextmanager
def captured_fd(stream=2):
pipe_in = t = None
orig_stream = os.dup(stream) # keep copy of original stream
try:
pipe_in, pipe_out = os.pipe()
os.dup2(pipe_out, stream) # replace stream by copy of pipe
try:
os.close(pipe_out) # close original pipe-out stream
data = []
def copy():
try:
while True:
d = os.read(pipe_in, 1000)
if d:
data.append(d)
else:
break
finally:
os.close(pipe_in)
from threading import Thread
t = Thread(target=copy)
t.daemon = True # just in case
t.start()
yield data
finally:
os.dup2(orig_stream, stream) # restore original stream
if t is not None:
t.join()
finally:
os.close(orig_stream)
...@@ -867,33 +867,24 @@ class CythonCompileTestCase(unittest.TestCase): ...@@ -867,33 +867,24 @@ class CythonCompileTestCase(unittest.TestCase):
so_path = None so_path = None
if not self.cython_only: if not self.cython_only:
c_compiler_output = None from Cython.Utils import captured_fd
orig_stderr = os.dup(2) # remember original stderr c_compiler_stderr = None
try:
with tempfile.TemporaryFile() as temp_stderr:
os.dup2(temp_stderr.fileno(), 2) # replace stderr by temp file
try:
try: try:
with captured_fd(2) as c_compiler_stderr:
so_path = self.run_distutils(test_directory, module, workdir, incdir) so_path = self.run_distutils(test_directory, module, workdir, incdir)
finally:
temp_stderr.seek(0)
c_compiler_output = temp_stderr.read().strip()
except Exception: except Exception:
if expected_errors == '_FAIL_C_COMPILE': if expected_errors == '_FAIL_C_COMPILE':
assert c_compiler_output assert c_compiler_stderr
else: else:
raise raise
else: else:
if c_compiler_output: c_compiler_stderr = ''.join(c_compiler_stderr).strip()
if c_compiler_stderr:
print("\n=== C/C++ compiler output: ===") print("\n=== C/C++ compiler output: ===")
print(c_compiler_output) print(c_compiler_stderr)
if expected_errors == '_FAIL_C_COMPILE': if expected_errors == '_FAIL_C_COMPILE':
# must raise this outside the try block # must raise this outside the try block
raise RuntimeError('should have failed C compile') raise RuntimeError('should have failed C compile')
finally:
os.dup2(orig_stderr, 2) # restore stderr
finally:
os.close(orig_stderr)
return so_path return so_path
class CythonRunTestCase(CythonCompileTestCase): class CythonRunTestCase(CythonCompileTestCase):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment