# Nomally we only register event handlers at the end of parsing .bb files
# We register any handlers we've found so far here...
for var in data.getVar('__BBHANDLERS', False) or []:
- bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask", True) or "").split())
+ handlerfn = data.getVarFlag(var, "filename", False)
+ handlerln = int(data.getVarFlag(var, "lineno", False))
+ bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask", True) or "").split(), handlerfn, handlerln)
if data.getVar("BB_WORKERCONTEXT", False) is None:
bb.fetch.fetcher_init(data)
fire_ui_handlers(event, d)
noop = lambda _: None
-def register(name, handler, mask=None):
+def register(name, handler, mask=None, filename=None, lineno=None):
"""Register an Event handler"""
# already registered
if isinstance(handler, basestring):
tmp = "def %s(e):\n%s" % (name, handler)
try:
- code = compile(tmp, "%s(e)" % name, "exec")
+ import ast
+ if filename is None:
+ filename = "%s(e)" % name
+ code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST)
+ if lineno is not None:
+ ast.increment_lineno(code, lineno-1)
+ code = compile(code, filename, "exec")
except SyntaxError:
logger.error("Unable to register event handler '%s':\n%s", name,
''.join(traceback.format_exc(limit=0)))
from bb.utils import better_compile, better_exec
-def insert_method(modulename, code, fn):
+def insert_method(modulename, code, fn, lineno):
"""
Add code of a module should be added. The methods
will be simply added, no checking will be done
"""
- comp = better_compile(code, modulename, fn )
+ comp = better_compile(code, modulename, fn, lineno=lineno)
better_exec(comp, None, code, fn)
def eval(self, data):
text = '\n'.join(self.body)
+ funcname = self.func_name
if self.func_name == "__anonymous":
funcname = ("__anon_%s_%s" % (self.lineno, self.filename.translate(MethodNode.tr_tbl)))
text = "def %s(d):\n" % (funcname) + text
- bb.methodpool.insert_method(funcname, text, self.filename)
+ bb.methodpool.insert_method(funcname, text, self.filename, self.lineno - len(self.body))
anonfuncs = data.getVar('__BBANONFUNCS', False) or []
anonfuncs.append(funcname)
data.setVar('__BBANONFUNCS', anonfuncs)
- data.setVar(funcname, text, parsing=True)
else:
data.setVarFlag(self.func_name, "func", 1)
- data.setVar(self.func_name, text, parsing=True)
+ data.setVar(funcname, text, parsing=True)
+ data.setVarFlag(funcname, 'filename', self.filename)
+ data.setVarFlag(funcname, 'lineno', str(self.lineno - len(self.body)))
class PythonMethodNode(AstNode):
def __init__(self, filename, lineno, function, modulename, body):
# 'this' file. This means we will not parse methods from
# bb classes twice
text = '\n'.join(self.body)
- bb.methodpool.insert_method(self.modulename, text, self.filename)
+ bb.methodpool.insert_method(self.modulename, text, self.filename, self.lineno - len(self.body) - 1)
data.setVarFlag(self.function, "func", 1)
data.setVarFlag(self.function, "python", 1)
data.setVar(self.function, text, parsing=True)
+ data.setVarFlag(self.function, 'filename', self.filename)
+ data.setVarFlag(self.function, 'lineno', str(self.lineno - len(self.body) - 1))
class MethodFlagsNode(AstNode):
def __init__(self, filename, lineno, key, m):
all_handlers = {}
for var in d.getVar('__BBHANDLERS', False) or []:
# try to add the handler
- bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask", True) or "").split())
+ handlerfn = d.getVarFlag(var, "filename", False)
+ handlerln = int(d.getVarFlag(var, "lineno", False))
+ bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask", True) or "").split(), handlerfn, handlerln)
bb.event.fire(bb.event.RecipePreFinalise(fn), d)
import traceback
import errno
import signal
+import ast
from commands import getstatusoutput
from contextlib import contextmanager
from ctypes import cdll
error.append(' %.4d:%s' % (i, body[i-1].rstrip()))
return error
-def better_compile(text, file, realfile, mode = "exec"):
+def better_compile(text, file, realfile, mode = "exec", lineno = None):
"""
A better compile method. This method
will print the offending lines.
"""
try:
- return compile(text, file, mode)
+ code = compile(text, realfile, mode, ast.PyCF_ONLY_AST)
+ if lineno is not None:
+ ast.increment_lineno(code, lineno)
+ return compile(code, realfile, mode)
except Exception as e:
error = []
# split the text into lines again
body = text.split('\n')
- error.append("Error in compiling python function in %s:\n" % realfile)
- if e.lineno:
+ error.append("Error in compiling python function in %s, line %s:\n" % (realfile, lineno))
+ if hasattr(e, "lineno"):
error.append("The code lines resulting in this error were:")
error.extend(_print_trace(body, e.lineno))
else: