diff options
Diffstat (limited to 'bitbake/lib/bb/data_smart.py')
-rw-r--r-- | bitbake/lib/bb/data_smart.py | 117 |
1 files changed, 64 insertions, 53 deletions
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py index 0128a5bb17..8e7dd98384 100644 --- a/bitbake/lib/bb/data_smart.py +++ b/bitbake/lib/bb/data_smart.py | |||
@@ -31,7 +31,7 @@ logger = logging.getLogger("BitBake.Data") | |||
31 | 31 | ||
32 | __setvar_keyword__ = [":append", ":prepend", ":remove"] | 32 | __setvar_keyword__ = [":append", ":prepend", ":remove"] |
33 | __setvar_regexp__ = re.compile(r'(?P<base>.*?)(?P<keyword>:append|:prepend|:remove)(:(?P<add>[^A-Z]*))?$') | 33 | __setvar_regexp__ = re.compile(r'(?P<base>.*?)(?P<keyword>:append|:prepend|:remove)(:(?P<add>[^A-Z]*))?$') |
34 | __expand_var_regexp__ = re.compile(r"\${[a-zA-Z0-9\-_+./~:]+?}") | 34 | __expand_var_regexp__ = re.compile(r"\${[a-zA-Z0-9\-_+./~:]+}") |
35 | __expand_python_regexp__ = re.compile(r"\${@(?:{.*?}|.)+?}") | 35 | __expand_python_regexp__ = re.compile(r"\${@(?:{.*?}|.)+?}") |
36 | __whitespace_split__ = re.compile(r'(\s)') | 36 | __whitespace_split__ = re.compile(r'(\s)') |
37 | __override_regexp__ = re.compile(r'[a-z0-9]+') | 37 | __override_regexp__ = re.compile(r'[a-z0-9]+') |
@@ -106,52 +106,52 @@ class VariableParse: | |||
106 | self.contains = {} | 106 | self.contains = {} |
107 | 107 | ||
108 | def var_sub(self, match): | 108 | def var_sub(self, match): |
109 | key = match.group()[2:-1] | 109 | key = match.group()[2:-1] |
110 | if self.varname and key: | 110 | if self.varname and key: |
111 | if self.varname == key: | 111 | if self.varname == key: |
112 | raise Exception("variable %s references itself!" % self.varname) | 112 | raise Exception("variable %s references itself!" % self.varname) |
113 | var = self.d.getVarFlag(key, "_content") | 113 | var = self.d.getVarFlag(key, "_content") |
114 | self.references.add(key) | 114 | self.references.add(key) |
115 | if var is not None: | 115 | if var is not None: |
116 | return var | 116 | return var |
117 | else: | 117 | else: |
118 | return match.group() | 118 | return match.group() |
119 | 119 | ||
120 | def python_sub(self, match): | 120 | def python_sub(self, match): |
121 | if isinstance(match, str): | 121 | if isinstance(match, str): |
122 | code = match | 122 | code = match |
123 | else: | 123 | else: |
124 | code = match.group()[3:-1] | 124 | code = match.group()[3:-1] |
125 | 125 | ||
126 | # Do not run code that contains one or more unexpanded variables | 126 | # Do not run code that contains one or more unexpanded variables |
127 | # instead return the code with the characters we removed put back | 127 | # instead return the code with the characters we removed put back |
128 | if __expand_var_regexp__.findall(code): | 128 | if __expand_var_regexp__.findall(code): |
129 | return "${@" + code + "}" | 129 | return "${@" + code + "}" |
130 | 130 | ||
131 | if self.varname: | 131 | if self.varname: |
132 | varname = 'Var <%s>' % self.varname | 132 | varname = 'Var <%s>' % self.varname |
133 | else: | 133 | else: |
134 | varname = '<expansion>' | 134 | varname = '<expansion>' |
135 | codeobj = compile(code.strip(), varname, "eval") | 135 | codeobj = compile(code.strip(), varname, "eval") |
136 | 136 | ||
137 | parser = bb.codeparser.PythonParser(self.varname, logger) | 137 | parser = bb.codeparser.PythonParser(self.varname, logger) |
138 | parser.parse_python(code) | 138 | parser.parse_python(code) |
139 | if self.varname: | 139 | if self.varname: |
140 | vardeps = self.d.getVarFlag(self.varname, "vardeps") | 140 | vardeps = self.d.getVarFlag(self.varname, "vardeps") |
141 | if vardeps is None: | 141 | if vardeps is None: |
142 | parser.log.flush() | ||
143 | else: | ||
144 | parser.log.flush() | 142 | parser.log.flush() |
145 | self.references |= parser.references | 143 | else: |
146 | self.execs |= parser.execs | 144 | parser.log.flush() |
145 | self.references |= parser.references | ||
146 | self.execs |= parser.execs | ||
147 | 147 | ||
148 | for k in parser.contains: | 148 | for k in parser.contains: |
149 | if k not in self.contains: | 149 | if k not in self.contains: |
150 | self.contains[k] = parser.contains[k].copy() | 150 | self.contains[k] = parser.contains[k].copy() |
151 | else: | 151 | else: |
152 | self.contains[k].update(parser.contains[k]) | 152 | self.contains[k].update(parser.contains[k]) |
153 | value = utils.better_eval(codeobj, DataContext(self.d), {'d' : self.d}) | 153 | value = utils.better_eval(codeobj, DataContext(self.d), {'d' : self.d}) |
154 | return str(value) | 154 | return str(value) |
155 | 155 | ||
156 | class DataContext(dict): | 156 | class DataContext(dict): |
157 | excluded = set([i for i in dir(builtins) if not i.startswith('_')] + ['oe']) | 157 | excluded = set([i for i in dir(builtins) if not i.startswith('_')] + ['oe']) |
@@ -272,12 +272,9 @@ class VariableHistory(object): | |||
272 | return | 272 | return |
273 | if 'op' not in loginfo or not loginfo['op']: | 273 | if 'op' not in loginfo or not loginfo['op']: |
274 | loginfo['op'] = 'set' | 274 | loginfo['op'] = 'set' |
275 | if 'detail' in loginfo: | ||
276 | loginfo['detail'] = str(loginfo['detail']) | ||
277 | if 'variable' not in loginfo or 'file' not in loginfo: | 275 | if 'variable' not in loginfo or 'file' not in loginfo: |
278 | raise ValueError("record() missing variable or file.") | 276 | raise ValueError("record() missing variable or file.") |
279 | var = loginfo['variable'] | 277 | var = loginfo['variable'] |
280 | |||
281 | if var not in self.variables: | 278 | if var not in self.variables: |
282 | self.variables[var] = [] | 279 | self.variables[var] = [] |
283 | if not isinstance(self.variables[var], list): | 280 | if not isinstance(self.variables[var], list): |
@@ -336,7 +333,8 @@ class VariableHistory(object): | |||
336 | flag = '[%s] ' % (event['flag']) | 333 | flag = '[%s] ' % (event['flag']) |
337 | else: | 334 | else: |
338 | flag = '' | 335 | flag = '' |
339 | o.write("# %s %s:%s%s\n# %s\"%s\"\n" % (event['op'], event['file'], event['line'], display_func, flag, re.sub('\n', '\n# ', event['detail']))) | 336 | o.write("# %s %s:%s%s\n# %s\"%s\"\n" % \ |
337 | (event['op'], event['file'], event['line'], display_func, flag, re.sub('\n', '\n# ', str(event['detail'])))) | ||
340 | if len(history) > 1: | 338 | if len(history) > 1: |
341 | o.write("# pre-expansion value:\n") | 339 | o.write("# pre-expansion value:\n") |
342 | o.write('# "%s"\n' % (commentVal)) | 340 | o.write('# "%s"\n' % (commentVal)) |
@@ -390,7 +388,7 @@ class VariableHistory(object): | |||
390 | if isset and event['op'] == 'set?': | 388 | if isset and event['op'] == 'set?': |
391 | continue | 389 | continue |
392 | isset = True | 390 | isset = True |
393 | items = d.expand(event['detail']).split() | 391 | items = d.expand(str(event['detail'])).split() |
394 | for item in items: | 392 | for item in items: |
395 | # This is a little crude but is belt-and-braces to avoid us | 393 | # This is a little crude but is belt-and-braces to avoid us |
396 | # having to handle every possible operation type specifically | 394 | # having to handle every possible operation type specifically |
@@ -582,12 +580,10 @@ class DataSmart(MutableMapping): | |||
582 | else: | 580 | else: |
583 | loginfo['op'] = keyword | 581 | loginfo['op'] = keyword |
584 | self.varhistory.record(**loginfo) | 582 | self.varhistory.record(**loginfo) |
585 | # todo make sure keyword is not __doc__ or __module__ | ||
586 | # pay the cookie monster | 583 | # pay the cookie monster |
587 | 584 | ||
588 | # more cookies for the cookie monster | 585 | # more cookies for the cookie monster |
589 | if ':' in var: | 586 | self._setvar_update_overrides(base, **loginfo) |
590 | self._setvar_update_overrides(base, **loginfo) | ||
591 | 587 | ||
592 | if base in self.overridevars: | 588 | if base in self.overridevars: |
593 | self._setvar_update_overridevars(var, value) | 589 | self._setvar_update_overridevars(var, value) |
@@ -640,6 +636,7 @@ class DataSmart(MutableMapping): | |||
640 | nextnew.update(vardata.contains.keys()) | 636 | nextnew.update(vardata.contains.keys()) |
641 | new = nextnew | 637 | new = nextnew |
642 | self.overrides = None | 638 | self.overrides = None |
639 | self.expand_cache = {} | ||
643 | 640 | ||
644 | def _setvar_update_overrides(self, var, **loginfo): | 641 | def _setvar_update_overrides(self, var, **loginfo): |
645 | # aka pay the cookie monster | 642 | # aka pay the cookie monster |
@@ -829,6 +826,8 @@ class DataSmart(MutableMapping): | |||
829 | value = copy.copy(local_var[flag]) | 826 | value = copy.copy(local_var[flag]) |
830 | elif flag == "_content" and "_defaultval" in local_var and not noweakdefault: | 827 | elif flag == "_content" and "_defaultval" in local_var and not noweakdefault: |
831 | value = copy.copy(local_var["_defaultval"]) | 828 | value = copy.copy(local_var["_defaultval"]) |
829 | elif "_defaultval_flag_"+flag in local_var and not noweakdefault: | ||
830 | value = copy.copy(local_var["_defaultval_flag_"+flag]) | ||
832 | 831 | ||
833 | 832 | ||
834 | if flag == "_content" and local_var is not None and ":append" in local_var and not parsing: | 833 | if flag == "_content" and local_var is not None and ":append" in local_var and not parsing: |
@@ -920,6 +919,8 @@ class DataSmart(MutableMapping): | |||
920 | self.varhistory.record(**loginfo) | 919 | self.varhistory.record(**loginfo) |
921 | 920 | ||
922 | del self.dict[var][flag] | 921 | del self.dict[var][flag] |
922 | if ("_defaultval_flag_" + flag) in self.dict[var]: | ||
923 | del self.dict[var]["_defaultval_flag_" + flag] | ||
923 | 924 | ||
924 | def appendVarFlag(self, var, flag, value, **loginfo): | 925 | def appendVarFlag(self, var, flag, value, **loginfo): |
925 | loginfo['op'] = 'append' | 926 | loginfo['op'] = 'append' |
@@ -954,17 +955,22 @@ class DataSmart(MutableMapping): | |||
954 | flags = {} | 955 | flags = {} |
955 | 956 | ||
956 | if local_var: | 957 | if local_var: |
957 | for i in local_var: | 958 | for i, val in local_var.items(): |
958 | if i.startswith(("_", ":")) and not internalflags: | 959 | if i.startswith("_defaultval_flag_") and not internalflags: |
960 | i = i[len("_defaultval_flag_"):] | ||
961 | if i not in local_var: | ||
962 | flags[i] = val | ||
963 | elif i.startswith(("_", ":")) and not internalflags: | ||
959 | continue | 964 | continue |
960 | flags[i] = local_var[i] | 965 | else: |
966 | flags[i] = val | ||
967 | |||
961 | if expand and i in expand: | 968 | if expand and i in expand: |
962 | flags[i] = self.expand(flags[i], var + "[" + i + "]") | 969 | flags[i] = self.expand(flags[i], var + "[" + i + "]") |
963 | if len(flags) == 0: | 970 | if len(flags) == 0: |
964 | return None | 971 | return None |
965 | return flags | 972 | return flags |
966 | 973 | ||
967 | |||
968 | def delVarFlags(self, var, **loginfo): | 974 | def delVarFlags(self, var, **loginfo): |
969 | self.expand_cache = {} | 975 | self.expand_cache = {} |
970 | if not var in self.dict: | 976 | if not var in self.dict: |
@@ -1114,5 +1120,10 @@ class DataSmart(MutableMapping): | |||
1114 | value = d.getVar(i, False) or "" | 1120 | value = d.getVar(i, False) or "" |
1115 | data.update({i:value}) | 1121 | data.update({i:value}) |
1116 | 1122 | ||
1123 | moddeps = bb.codeparser.modulecode_deps | ||
1124 | for dep in sorted(moddeps): | ||
1125 | # Ignore visitor code, sort sets | ||
1126 | data.update({'moddep[%s]' % dep : [sorted(moddeps[dep][0]), sorted(moddeps[dep][1]), sorted(moddeps[dep][2]), sorted(moddeps[dep][3]), moddeps[dep][4]]}) | ||
1127 | |||
1117 | data_str = str([(k, data[k]) for k in sorted(data.keys())]) | 1128 | data_str = str([(k, data[k]) for k in sorted(data.keys())]) |
1118 | return hashlib.sha256(data_str.encode("utf-8")).hexdigest() | 1129 | return hashlib.sha256(data_str.encode("utf-8")).hexdigest() |