summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Larson <kergoth@gmail.com>2011-10-27 22:37:11 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2011-11-10 11:44:28 +0000
commit48d7f5251bd5f3a44f713edfc297851258c57120 (patch)
treeaa2ede29d34d38d15f0edef2594c0332e320f10f
parent002451b3a27661517073bbe8917dcac04b3bf12a (diff)
downloadpoky-48d7f5251bd5f3a44f713edfc297851258c57120.tar.gz
codeparser: simplify how we compare the called node names
With the previous method, using the compare_name methods, we split the requested match name by '.', reversed it, then compared them piecemeal during the node traversal. The new method walks the nodes and hands back the name of what's being called, and then we check that. This also consolidates the two different implementations of traversal of the attribute/name nodes (one in compare_name, one for the execs). (Bitbake rev: 84e535b5165c7e936c5b1486bdf4626ed3649f5f) Signed-off-by: Christopher Larson <kergoth@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/codeparser.py72
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()