Executables can optionally ignore error output.

This commit is contained in:
Todd Gamblin 2014-06-22 12:25:53 -07:00
parent ae31838193
commit f1bc65c132

View file

@ -22,7 +22,7 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
__all__ = ['Executable', 'when']
__all__ = ['Executable', 'which', 'ProcessError']
import os
import sys
@ -30,7 +30,7 @@
import subprocess
import llnl.util.tty as tty
from spack.error import SpackError
import spack.error
class Executable(object):
"""Class representing a program that can be run on the command line."""
@ -52,6 +52,7 @@ def __call__(self, *args, **kwargs):
"""Run the executable with subprocess.check_output, return output."""
return_output = kwargs.get("return_output", False)
fail_on_error = kwargs.get("fail_on_error", True)
error = kwargs.get("error", sys.stderr)
quoted_args = [arg for arg in args if re.search(r'^"|^\'|"$|\'$', arg)]
if quoted_args:
@ -64,22 +65,34 @@ def __call__(self, *args, **kwargs):
cmd = self.exe + list(args)
tty.debug(" ".join(cmd))
close_error = False
try:
if error is None:
error = open(os.devnull, 'w')
close_error = True
proc = subprocess.Popen(
cmd,
stderr=sys.stderr,
stderr=error,
stdout=subprocess.PIPE if return_output else sys.stdout)
out, err = proc.communicate()
self.returncode = proc.returncode
if fail_on_error and proc.returncode != 0:
raise SpackError("command '%s' returned error code %d"
% (" ".join(cmd), proc.returncode))
raise ProcessError("command '%s' returned error code %d"
% (" ".join(cmd), proc.returncode))
if return_output:
return out
except subprocess.CalledProcessError, e:
if fail_on_error: raise
if fail_on_error:
raise ProcessError(
"command '%s' failed to run." % (
" ".join(cmd), proc.returncode), str(e))
finally:
if close_error:
error.close()
def __eq__(self, other):
@ -114,3 +127,8 @@ def which(name, **kwargs):
if required:
tty.die("spack requires %s. Make sure it is in your path." % name)
return None
class ProcessError(spack.error.SpackError):
def __init__(self, msg, *long_msg):
super(ProcessError, self).__init__(msg, *long_msg)