Consolidate the exec/eval bits, switch anonfunc to better_exec, etc

The methodpool, ${@} expansions, anonymous python functions, event handlers
now all run with the same global context, ensuring a consistent environment
for them.  Added a bb.utils.better_eval function which does an eval() with the
same globals as better_exec.

(Bitbake rev: 424d7e267b009cc19b8503eadab782736d9597d0)

Signed-off-by: Chris Larson <chris_larson@mentor.com>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
This commit is contained in:
Chris Larson 2010-03-30 20:06:07 -07:00 committed by Richard Purdie
parent eb16773704
commit 94b60d1247
6 changed files with 36 additions and 53 deletions

View File

@ -203,16 +203,14 @@ def exec_func_python(func, d, runfile, logfile):
import re, os
bbfile = bb.data.getVar('FILE', d, 1)
tmp = "def " + func + "():\n%s" % data.getVar(func, d)
tmp += '\n' + func + '()'
tmp = "def " + func + "(d):\n%s" % data.getVar(func, d)
tmp += '\n' + func + '(d)'
f = open(runfile, "w")
f.write(tmp)
comp = utils.better_compile(tmp, func, bbfile)
g = {} # globals
g['d'] = d
try:
utils.better_exec(comp, g, tmp, bbfile)
utils.better_exec(comp, {"d": d}, tmp, bbfile)
except:
(t,value,tb) = sys.exc_info()

View File

@ -50,12 +50,6 @@ class DataSmart:
self._seen_overrides = seen
self.expand_cache = {}
self.expand_globals = {
"os": os,
"bb": bb,
"time": time,
"d": self
}
def expand(self,s, varname):
def var_sub(match):
@ -72,7 +66,7 @@ class DataSmart:
def python_sub(match):
code = match.group()[3:-1]
codeobj = compile(code.strip(), varname or "<expansion>", "eval")
s = eval(codeobj, self.expand_globals, {})
s = utils.better_eval(codeobj, {"d": self})
if type(s) == types.IntType: s = str(s)
return s

View File

@ -48,13 +48,18 @@ _handlers = {}
_ui_handlers = {}
_ui_handler_seq = 0
# For compatibility
bb.utils._context["NotHandled"] = NotHandled
bb.utils._context["Handled"] = Handled
def fire_class_handlers(event, d):
for handler in _handlers:
h = _handlers[handler]
event.data = d
if type(h).__name__ == "code":
exec(h)
tmpHandler(event)
locals = {"e": event}
exec h in bb.utils._context, locals
bb.utils.better_eval("tmpHandler(e)", locals)
else:
h(event)
del event.data

View File

@ -27,7 +27,7 @@
a method pool to do this task.
This pool will be used to compile and execute the functions. It
will be smart enough to
will be smart enough to
"""
from bb.utils import better_compile, better_exec
@ -43,8 +43,8 @@ def insert_method(modulename, code, fn):
Add code of a module should be added. The methods
will be simply added, no checking will be done
"""
comp = better_compile(code, "<bb>", fn )
better_exec(comp, __builtins__, code, fn)
comp = better_compile(code, modulename, fn )
better_exec(comp, None, code, fn)
# now some instrumentation
code = comp.co_names
@ -59,7 +59,7 @@ def insert_method(modulename, code, fn):
def check_insert_method(modulename, code, fn):
"""
Add the code if it wasnt added before. The module
name will be used for that
name will be used for that
Variables:
@modulename a short name e.g. base.bbclass
@ -81,4 +81,4 @@ def get_parsed_dict():
"""
shortcut
"""
return _parsed_methods
return _parsed_methods

View File

@ -122,12 +122,8 @@ class MethodNode:
def eval(self, data):
if self.func_name == "__anonymous":
funcname = ("__anon_%s_%s" % (self.lineno, self.fn.translate(string.maketrans('/.+-', '____'))))
if not funcname in bb.methodpool._parsed_fns:
text = "def %s(d):\n" % (funcname) + '\n'.join(self.body)
bb.methodpool.insert_method(funcname, text, self.fn)
anonfuncs = bb.data.getVar('__BBANONFUNCS', data) or []
anonfuncs.append(funcname)
anonfuncs.append((self.fn, "\n".join(self.body)))
bb.data.setVar('__BBANONFUNCS', anonfuncs, data)
else:
bb.data.setVarFlag(self.func_name, "func", 1, data)
@ -143,7 +139,7 @@ class PythonMethodNode(AstNode):
# Note we will add root to parsedmethods after having parse
# 'this' file. This means we will not parse methods from
# bb classes twice
if not self.root in __parsed_methods__:
if not bb.methodpool.parsed_module(self.root):
text = '\n'.join(self.body)
bb.methodpool.insert_method(self.root, text, self.fn)
@ -301,32 +297,12 @@ def finalise(fn, d):
bb.data.expandKeys(d)
bb.data.update_data(d)
anonqueue = bb.data.getVar("__anonqueue", d, 1) or []
body = [x['content'] for x in anonqueue]
flag = { 'python' : 1, 'func' : 1 }
bb.data.setVar("__anonfunc", "\n".join(body), d)
bb.data.setVarFlags("__anonfunc", flag, d)
from bb import build
try:
t = bb.data.getVar('T', d)
bb.data.setVar('T', '${TMPDIR}/anonfunc/', d)
anonfuncs = bb.data.getVar('__BBANONFUNCS', d) or []
code = ""
for f in anonfuncs:
code = code + " %s(d)\n" % f
bb.data.setVar("__anonfunc", code, d)
build.exec_func("__anonfunc", d)
bb.data.delVar('T', d)
if t:
bb.data.setVar('T', t, d)
except Exception, e:
bb.msg.debug(1, bb.msg.domain.Parsing, "Exception when executing anonymous function: %s" % e)
raise
bb.data.delVar("__anonqueue", d)
bb.data.delVar("__anonfunc", d)
for fn, func in bb.data.getVar("__BBANONFUNCS", d) or []:
funcdef = "def __anonfunc(d):\n%s\n__anonfunc(d)" % func.rstrip()
bb.utils.better_exec(funcdef, {"d": d}, funcdef, fn)
bb.data.update_data(d)
all_handlers = {}
all_handlers = {}
for var in bb.data.getVar('__BBHANDLERS', d) or []:
# try to add the handler
handler = bb.data.getVar(var,d)

View File

@ -21,9 +21,16 @@ BitBake Utility Functions
separators = ".-"
import re, fcntl, os, types, bb, string, stat, shutil
import re, fcntl, os, types, bb, string, stat, shutil, time
from commands import getstatusoutput
# Context used in better_exec, eval
_context = {
"os": os,
"bb": bb,
"time": time,
}
def explode_version(s):
r = []
alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
@ -164,13 +171,13 @@ def _print_trace(body, line):
bb.msg.error(bb.msg.domain.Util, "\t%.4d:%s" % (i, body[i-1]) )
def better_compile(text, file, realfile):
def better_compile(text, file, realfile, mode = "exec"):
"""
A better compile method. This method
will print the offending lines.
"""
try:
return compile(text, file, "exec")
return compile(text, file, mode)
except Exception, e:
import bb,sys
@ -193,7 +200,7 @@ def better_exec(code, context, text, realfile):
"""
import bb,sys
try:
exec code in context
exec code in _context, context
except:
(t,value,tb) = sys.exc_info()
@ -215,6 +222,9 @@ def better_exec(code, context, text, realfile):
raise
def better_eval(source, locals):
return eval(source, _context, locals)
def Enum(*names):
"""
A simple class to give Enum support