From 5c04b3c4800ae4ffb71f20bcd86fb42b2ba40183 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Tue, 14 Apr 2015 15:11:41 -0700 Subject: Fix for GitHub #30 and SPACK-70. --- lib/spack/spack/util/executable.py | 49 ++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/util/executable.py b/lib/spack/spack/util/executable.py index 923c7c19a5..81759d3053 100644 --- a/lib/spack/spack/util/executable.py +++ b/lib/spack/spack/util/executable.py @@ -28,8 +28,10 @@ import os import sys import re import subprocess +import inspect import llnl.util.tty as tty +import spack import spack.error class Executable(object): @@ -38,6 +40,9 @@ class Executable(object): self.exe = name.split(' ') self.returncode = None + if not self.exe: + raise ProcessError("Cannot construct executable for '%s'" % name) + def add_default_arg(self, arg): self.exe.append(arg) @@ -63,7 +68,9 @@ class Executable(object): "Consider removing them") cmd = self.exe + list(args) - tty.debug(" ".join(cmd)) + + cmd_line = ' '.join(cmd) + tty.debug(cmd_line) close_error = False try: @@ -79,16 +86,22 @@ class Executable(object): self.returncode = proc.returncode if fail_on_error and proc.returncode != 0: - raise ProcessError("command '%s' returned error code %d" - % (" ".join(cmd), proc.returncode)) + raise ProcessError("Command exited with status %d:" + % proc.returncode, cmd_line) if return_output: return out + except OSError, e: + raise ProcessError( + "%s: %s" % (self.exe[0], e.strerror), + "Command: " + cmd_line) + except subprocess.CalledProcessError, e: if fail_on_error: raise ProcessError( - "command '%s' failed to run." % ( - " ".join(cmd), proc.returncode), str(e)) + str(e), + "\nExit status %d when invoking command: %s" + % (proc.returncode, cmd_line)) finally: if close_error: @@ -130,5 +143,27 @@ def which(name, **kwargs): class ProcessError(spack.error.SpackError): - def __init__(self, msg, *long_msg): - super(ProcessError, self).__init__(msg, *long_msg) + def __init__(self, msg, long_msg=None): + # Friendlier exception trace info for failed executables + long_msg = long_msg + "\n" if long_msg else "" + for f in inspect.stack(): + frame = f[0] + loc = frame.f_locals + if 'self' in loc: + obj = loc['self'] + if isinstance(obj, spack.Package): + long_msg += "---\n" + long_msg += "Context:\n" + long_msg += " %s:%d, in %s:\n" % ( + inspect.getfile(frame.f_code), + frame.f_lineno, + frame.f_code.co_name) + + lines, start = inspect.getsourcelines(frame) + for i, line in enumerate(lines): + mark = ">> " if start + i == frame.f_lineno else " " + long_msg += " %s%-5d%s\n" % ( + mark, start + i, line.rstrip()) + break + + super(ProcessError, self).__init__(msg, long_msg) -- cgit v1.2.3-70-g09d2