Skip to content

Commit

Permalink
BUG: fix issue with distutils.exec_command introduced in 1.7.0.
Browse files Browse the repository at this point in the history
Closes numpygh-2999 and numpygh-2915.

There are several packages (nose, scipy.weave.inline, Sage inline Fortran) that
replace stdout, in which case it doesn't have a fileno method.  This method was
attempted to be used (change in numpygh-2766 to fix a py3k issue).
  • Loading branch information
rgommers committed Mar 6, 2013
1 parent bbcfcf6 commit ff01555
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 16 deletions.
42 changes: 26 additions & 16 deletions numpy/distutils/exec_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ def exec_command( command,
# _exec_command_posix uses os.system and is faster
# but not on all platforms os.system will return
# a correct status.
if _with_python and sys.stdout.fileno() == -1:
if _with_python and hasattr(sys.stdout, 'fileno') and \
sys.stdout.fileno() == -1:
st = _exec_command_python(command,
exec_command_dir = exec_dir,
**env)
Expand Down Expand Up @@ -349,12 +350,17 @@ def _exec_command( command, use_shell=None, use_tee = None, **env ):
argv = [os.environ['COMSPEC'],'/C'] + argv
using_command = 1

so_fileno = sys.stdout.fileno()
se_fileno = sys.stderr.fileno()
so_flush = sys.stdout.flush
se_flush = sys.stderr.flush
so_dup = os.dup(so_fileno)
se_dup = os.dup(se_fileno)
_has_fileno = hasattr(sys.stdout, 'fileno')
if _has_fileno:
so_fileno = sys.stdout.fileno()
se_fileno = sys.stderr.fileno()
so_flush = sys.stdout.flush
se_flush = sys.stderr.flush
so_dup = os.dup(so_fileno)
se_dup = os.dup(se_fileno)
else:
so_flush = sys.stdout.flush
se_flush = sys.stderr.flush

outfile = temp_file_name()
fout = open(outfile,'w')
Expand All @@ -371,13 +377,16 @@ def _exec_command( command, use_shell=None, use_tee = None, **env ):

so_flush()
se_flush()
os.dup2(fout.fileno(),so_fileno)
if using_command:
#XXX: disabled for now as it does not work from cmd under win32.
# Tests fail on msys
os.dup2(ferr.fileno(),se_fileno)
else:
os.dup2(fout.fileno(),se_fileno)
if _has_fileno:
os.dup2(fout.fileno(),so_fileno)

if _has_fileno:
if using_command:
#XXX: disabled for now as it does not work from cmd under win32.
# Tests fail on msys
os.dup2(ferr.fileno(),se_fileno)
else:
os.dup2(fout.fileno(),se_fileno)
try:
status = spawn_command(os.P_WAIT,argv0,argv,os.environ)
except OSError:
Expand All @@ -387,8 +396,9 @@ def _exec_command( command, use_shell=None, use_tee = None, **env ):

so_flush()
se_flush()
os.dup2(so_dup,so_fileno)
os.dup2(se_dup,se_fileno)
if _has_fileno:
os.dup2(so_dup,so_fileno)
os.dup2(se_dup,se_fileno)

fout.close()
fout = open_latin1(outfile,'r')
Expand Down
29 changes: 29 additions & 0 deletions numpy/distutils/tests/test_exec_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import sys
import StringIO

from numpy.distutils import exec_command


class redirect_stdout(object):
"""Context manager to redirect stdout for exec_command test."""
def __init__(self, stdout=None):
self._stdout = stdout or sys.stdout

def __enter__(self):
self.old_stdout = sys.stdout
sys.stdout = self._stdout

def __exit__(self, exc_type, exc_value, traceback):
self._stdout.flush()
sys.stdout = self.old_stdout


def test_exec_command():
# Regression test for gh-2999 and gh-2915.
# There are several packages (nose, scipy.weave.inline, Sage inline
# Fortran) that replace stdout, in which case it doesn't have a fileno
# method. This is tested here, with a do-nothing command that fails if the
# presence of fileno() is assumed in exec_command.
with redirect_stdout(StringIO.StringIO()):
exec_command.exec_command("cd '.'")

0 comments on commit ff01555

Please sign in to comment.