diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index d671f56b50..9d7a32fb25 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py @@ -236,14 +236,16 @@ def _print_trace(body, line): """ Print the Environment of a Text Body """ + error = [] # print the environment of the method min_line = max(1, line-4) max_line = min(line + 4, len(body)) - for i in xrange(min_line, max_line + 1): + for i in range(min_line, max_line + 1): if line == i: - logger.error(' *** %.4d:%s', i, body[i-1]) + error.append(' *** %.4d:%s' % (i, body[i-1].rstrip())) else: - logger.error(' %.4d:%s', i, body[i-1]) + error.append(' %.4d:%s' % (i, body[i-1].rstrip())) + return error def better_compile(text, file, realfile, mode = "exec"): """ @@ -260,7 +262,7 @@ def better_compile(text, file, realfile, mode = "exec"): if e.lineno: logger.error("The lines leading to this error were:") logger.error("\t%d:%s:'%s'", e.lineno, e.__class__.__name__, body[e.lineno-1]) - _print_trace(body, e.lineno) + logger.error("\n".join(_print_trace(body, e.lineno))) else: logger.error("The function causing this error was:") for line in body: @@ -269,6 +271,61 @@ def better_compile(text, file, realfile, mode = "exec"): e = bb.BBHandledException(e) raise e +def _print_exception(t, value, tb, realfile, text, context): + error = [] + try: + import traceback + exception = traceback.format_exception_only(t, value) + error.append('Error executing a python function in %s:\n' % realfile) + + # Strip 'us' from the stack (better_exec call) + tb = tb.tb_next + + textarray = text.split('\n') + + linefailed = tb.tb_lineno + + tbextract = traceback.extract_tb(tb) + tbformat = traceback.format_list(tbextract) + error.append("The stack trace of python calls that resulted in this exception/failure was:") + error.append("File: '%s', lineno: %s, function: %s" % (tbextract[0][0], tbextract[0][1], tbextract[0][2])) + error.extend(_print_trace(textarray, linefailed)) + + # See if this is a function we constructed and has calls back into other functions in + # "text". If so, try and improve the context of the error by diving down the trace + level = 0 + nexttb = tb.tb_next + while nexttb is not None and (level+1) < len(tbextract): + error.append("File: '%s', lineno: %s, function: %s" % (tbextract[level+1][0], tbextract[level+1][1], tbextract[level+1][2])) + if tbextract[level][0] == tbextract[level+1][0] and tbextract[level+1][2] == tbextract[level][0]: + # The code was possibly in the string we compiled ourselves + error.extend(_print_trace(textarray, tbextract[level+1][1])) + elif tbextract[level+1][0].startswith("/"): + # The code looks like it might be in a file, try and load it + try: + with open(tbextract[level+1][0], "r") as f: + text = f.readlines() + error.extend(_print_trace(text, tbextract[level+1][1])) + except: + error.append(tbformat[level+1]) + elif "d" in context and tbextract[level+1][2]: + # Try and find the code in the datastore based on the functionname + d = context["d"] + functionname = tbextract[level+1][2] + text = d.getVar(functionname, True) + if text: + error.extend(_print_trace(text.split('\n'), tbextract[level+1][1])) + else: + error.append(tbformat[level+1]) + else: + error.append(tbformat[level+1]) + nexttb = tb.tb_next + level = level + 1 + + error.append("Exception: %s" % ''.join(exception)) + finally: + logger.error("\n".join(error)) + def better_exec(code, context, text = None, realfile = ""): """ Similiar to better_compile, better_exec will @@ -287,49 +344,10 @@ def better_exec(code, context, text = None, realfile = ""): if t in [bb.parse.SkipPackage, bb.build.FuncFailed]: raise - - import traceback - exception = traceback.format_exception_only(t, value) - logger.error('Error executing a python function in %s:\n%s', - realfile, ''.join(exception)) - - # Strip 'us' from the stack (better_exec call) - tb = tb.tb_next - - textarray = text.split('\n') - linefailed = traceback.tb_lineno(tb) - - tbextract = traceback.extract_tb(tb) - tbformat = "\n".join(traceback.format_list(tbextract)) - logger.error("The stack trace of python calls that resulted in this exception/failure was:") - for line in tbformat.split('\n'): - logger.error(line) - - logger.error("The code that was being executed was:") - _print_trace(textarray, linefailed) - logger.error("[From file: '%s', lineno: %s, function: %s]", tbextract[0][0], tbextract[0][1], tbextract[0][2]) - - # See if this is a function we constructed and has calls back into other functions in - # "text". If so, try and improve the context of the error by diving down the trace - level = 0 - nexttb = tb.tb_next - while nexttb is not None and (level+1) < len(tbextract): - if tbextract[level][0] == tbextract[level+1][0] and tbextract[level+1][2] == tbextract[level][0]: - _print_trace(textarray, tbextract[level+1][1]) - logger.error("[From file: '%s', lineno: %s, function: %s]", tbextract[level+1][0], tbextract[level+1][1], tbextract[level+1][2]) - elif "d" in context and tbextract[level+1][2]: - d = context["d"] - functionname = tbextract[level+1][2] - text = d.getVar(functionname, True) - if text: - _print_trace(text.split('\n'), tbextract[level+1][1]) - logger.error("[From file: '%s', lineno: %s, function: %s]", tbextract[level+1][0], tbextract[level+1][1], tbextract[level+1][2]) - else: - break - else: - break - nexttb = tb.tb_next - level = level + 1 + try: + _print_exception(t, value, tb, realfile, text, context) + except Exception as e: + logger.error("Exception handler error: %s" % str(e)) e = bb.BBHandledException(e) raise e