]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/commitdiff
data_smart: track variable references
authorRichard Purdie <rpurdie@linux.intel.com>
Wed, 25 Aug 2010 13:26:37 +0000 (14:26 +0100)
committerChris Larson <chris_larson@mentor.com>
Thu, 30 Dec 2010 06:51:07 +0000 (23:51 -0700)
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
lib/bb/data_smart.py

index 9b89c5f5a4c9d3bbdd9cfd038711f6dd947413b8..83e6f70cd7f44ca4902cdaa0e3705b4da96aefd3 100644 (file)
@@ -31,7 +31,7 @@ BitBake build tools.
 import copy, re
 from collections import MutableMapping
 import logging
-import bb
+import bb, bb.codeparser
 from bb   import utils
 from bb.COW  import COWDictBase
 
@@ -43,6 +43,40 @@ __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
 __expand_python_regexp__ = re.compile(r"\${@.+?}")
 
 
+class VariableParse:
+    def __init__(self, varname, d, val = None):
+        self.varname = varname
+        self.d = d
+        self.value = val
+
+        self.references = set()
+        self.execs = set()
+
+    def var_sub(self, match):
+            key = match.group()[2:-1]
+            if self.varname and key:
+                if self.varname == key:
+                    raise Exception("variable %s references itself!" % self.varname)
+            var = self.d.getVar(key, 1)
+            if var is not None:
+                self.references.add(key)
+                return var
+            else:
+                return match.group()
+
+    def python_sub(self, match):
+            code = match.group()[3:-1]
+            codeobj = compile(code.strip(), self.varname or "<expansion>", "eval")
+
+            parser = bb.codeparser.PythonParser()
+            parser.parse_python(code)
+            self.references |= parser.references
+            self.execs |= parser.execs
+
+            value = utils.better_eval(codeobj, DataContext(self.d))
+            return str(value)
+
+
 class DataContext(dict):
     def __init__(self, metadata, **kwargs):
         self.metadata = metadata
@@ -66,45 +100,37 @@ class DataSmart(MutableMapping):
 
         self.expand_cache = {}
 
-    def expand(self, s, varname):
-        def var_sub(match):
-            key = match.group()[2:-1]
-            if varname and key:
-                if varname == key:
-                    raise Exception("variable %s references itself!" % varname)
-            var = self.getVar(key, 1)
-            if var is not None:
-                return var
-            else:
-                return match.group()
-
-        def python_sub(match):
-            code = match.group()[3:-1]
-            codeobj = compile(code.strip(), varname or "<expansion>", "eval")
-            value = utils.better_eval(codeobj, DataContext(self))
-            return str(value)
+    def expandWithRefs(self, s, varname):
 
         if not isinstance(s, basestring): # sanity check
-            return s
+            return VariableParse(varname, self, s)
 
         if varname and varname in self.expand_cache:
             return self.expand_cache[varname]
 
+        varparse = VariableParse(varname, self)
+
         while s.find('${') != -1:
             olds = s
             try:
-                s = __expand_var_regexp__.sub(var_sub, s)
-                s = __expand_python_regexp__.sub(python_sub, s)
+                s = __expand_var_regexp__.sub(varparse.var_sub, s)
+                s = __expand_python_regexp__.sub(varparse.python_sub, s)
                 if s == olds:
                     break
             except Exception:
                 logger.exception("Error evaluating '%s'", s)
                 raise
 
+        varparse.value = s
+
         if varname:
-            self.expand_cache[varname] = s
+            self.expand_cache[varname] = varparse
+
+        return varparse
+
+    def expand(self, s, varname):
+        return self.expandWithRefs(s, varname).value
 
-        return s
 
     def finalize(self):
         """Performs final steps upon the datastore, including application of overrides"""