Executables can optionally ignore error output.
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user