diff options
Diffstat (limited to 'bitbake/lib')
-rw-r--r-- | bitbake/lib/bb/codeparser.py | 72 |
1 files changed, 20 insertions, 52 deletions
diff --git a/bitbake/lib/bb/codeparser.py b/bitbake/lib/bb/codeparser.py index 0f3d646cc4..77156136f8 100644 --- a/bitbake/lib/bb/codeparser.py +++ b/bitbake/lib/bb/codeparser.py | |||
@@ -156,40 +156,6 @@ class PythonParser(): | |||
156 | execfuncs = ("bb.build.exec_func", "bb.build.exec_task") | 156 | execfuncs = ("bb.build.exec_func", "bb.build.exec_task") |
157 | 157 | ||
158 | @classmethod | 158 | @classmethod |
159 | def _compare_name(cls, strparts, node): | ||
160 | """Given a sequence of strings representing a python name, | ||
161 | where the last component is the actual Name and the prior | ||
162 | elements are Attribute nodes, determine if the supplied node | ||
163 | matches. | ||
164 | """ | ||
165 | |||
166 | if not strparts: | ||
167 | return True | ||
168 | |||
169 | current, rest = strparts[0], strparts[1:] | ||
170 | if isinstance(node, ast.Attribute): | ||
171 | if current == node.attr: | ||
172 | return cls._compare_name(rest, node.value) | ||
173 | elif isinstance(node, ast.Name): | ||
174 | if current == node.id: | ||
175 | return True | ||
176 | return False | ||
177 | |||
178 | @classmethod | ||
179 | def compare_name(cls, value, node): | ||
180 | """Convenience function for the _compare_node method, which | ||
181 | can accept a string (which is split by '.' for you), or an | ||
182 | iterable of strings, in which case it checks to see if any of | ||
183 | them match, similar to isinstance. | ||
184 | """ | ||
185 | |||
186 | if isinstance(value, basestring): | ||
187 | return cls._compare_name(tuple(reversed(value.split("."))), | ||
188 | node) | ||
189 | else: | ||
190 | return any(cls.compare_name(item, node) for item in value) | ||
191 | |||
192 | @classmethod | ||
193 | def warn(cls, func, arg): | 159 | def warn(cls, func, arg): |
194 | """Warn about calls of bitbake APIs which pass a non-literal | 160 | """Warn about calls of bitbake APIs which pass a non-literal |
195 | argument for the variable name, as we're not able to track such | 161 | argument for the variable name, as we're not able to track such |
@@ -206,39 +172,41 @@ class PythonParser(): | |||
206 | "not a literal", funcstr, argstr) | 172 | "not a literal", funcstr, argstr) |
207 | 173 | ||
208 | def visit_Call(self, node): | 174 | def visit_Call(self, node): |
209 | if self.compare_name(self.getvars, node.func): | 175 | name = self.called_node_name(node.func) |
176 | if name in self.getvars: | ||
210 | if isinstance(node.args[0], ast.Str): | 177 | if isinstance(node.args[0], ast.Str): |
211 | self.var_references.add(node.args[0].s) | 178 | self.var_references.add(node.args[0].s) |
212 | else: | 179 | else: |
213 | self.warn(node.func, node.args[0]) | 180 | self.warn(node.func, node.args[0]) |
214 | elif self.compare_name(self.expands, node.func): | 181 | elif name in self.expands: |
215 | if isinstance(node.args[0], ast.Str): | 182 | if isinstance(node.args[0], ast.Str): |
216 | self.warn(node.func, node.args[0]) | 183 | self.warn(node.func, node.args[0]) |
217 | self.var_expands.add(node.args[0].s) | 184 | self.var_expands.add(node.args[0].s) |
218 | elif isinstance(node.args[0], ast.Call) and \ | 185 | elif isinstance(node.args[0], ast.Call) and \ |
219 | self.compare_name(self.getvars, node.args[0].func): | 186 | self.called_node_name(node.args[0].func) in self.getvars: |
220 | pass | 187 | pass |
221 | else: | 188 | else: |
222 | self.warn(node.func, node.args[0]) | 189 | self.warn(node.func, node.args[0]) |
223 | elif self.compare_name(self.execfuncs, node.func): | 190 | elif name in self.execfuncs: |
224 | if isinstance(node.args[0], ast.Str): | 191 | if isinstance(node.args[0], ast.Str): |
225 | self.var_execs.add(node.args[0].s) | 192 | self.var_execs.add(node.args[0].s) |
226 | else: | 193 | else: |
227 | self.warn(node.func, node.args[0]) | 194 | self.warn(node.func, node.args[0]) |
228 | elif isinstance(node.func, ast.Name): | 195 | elif name and isinstance(node.func, (ast.Name, ast.Attribute)): |
229 | self.execs.add(node.func.id) | 196 | self.execs.add(name) |
230 | elif isinstance(node.func, ast.Attribute): | 197 | |
231 | # We must have a qualified name. Therefore we need | 198 | def called_node_name(self, node): |
232 | # to walk the chain of 'Attribute' nodes to determine | 199 | """Given a called node, return its original string form""" |
233 | # the qualification. | 200 | components = [] |
234 | attr_node = node.func.value | 201 | while node: |
235 | identifier = node.func.attr | 202 | if isinstance(node, ast.Attribute): |
236 | while isinstance(attr_node, ast.Attribute): | 203 | components.append(node.attr) |
237 | identifier = attr_node.attr + "." + identifier | 204 | node = node.value |
238 | attr_node = attr_node.value | 205 | elif isinstance(node, ast.Name): |
239 | if isinstance(attr_node, ast.Name): | 206 | components.append(node.id) |
240 | identifier = attr_node.id + "." + identifier | 207 | return '.'.join(reversed(components)) |
241 | self.execs.add(identifier) | 208 | else: |
209 | break | ||
242 | 210 | ||
243 | def __init__(self): | 211 | def __init__(self): |
244 | self.var_references = set() | 212 | self.var_references = set() |