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