def iter_expr_values(parent, node, child=None):
"""
Yield each value for *node* which can be tracked. Literals are returned as
their evaluated value where as nodes which fail to evaluate to literals are
returned as is.
:param node parent: The parent node used to mark the start of the search path.
:param node node: The target ast.Name node to find literal values for.
:param node child: An optional child node to mark the end of the search path.
"""
child = child or node
success, value = eval_ast.literal_expr(node)
if success:
yield value
return
if not isinstance(node, ast.Name):
return
test_nodes = collections.deque()
def_nodes = get_definition_nodes(parent, node.id, child)
for def_node_idx, def_node in enumerate(def_nodes):
each = False
next_node = (def_nodes[def_node_idx + 1] if len(def_nodes) > def_node_idx + 1 else child)
src_node = None
test_nodes.clear()
if isinstance(def_node, ast.Assign):
test_node = get_expr_value_src_dst(def_node.value, def_node.targets[0], node)
if test_node:
test_nodes.append(test_node)
elif isinstance(def_node, ast.For):
src_node = get_expr_value_src_dst(def_node.iter, def_node.target, node)
each = node_is_child_of_parent(def_node.body, next_node)
elif isinstance(def_node, ast.ListComp):
for generator in def_node.generators:
src_node = get_expr_value_src_dst(generator.iter, generator.target, node)
if src_node:
break
if isinstance(src_node, (ast.List, ast.Tuple, ast.Set)):
test_nodes.extend(src_node.elts if each else src_node.elts[-1:])
for test_node in test_nodes:
success, value = eval_ast.literal_expr(test_node)
if success:
yield value
continue
for value in iter_expr_values(parent, test_node):
success = True
yield value
if success:
continue
for def_node in get_definition_nodes(parent, test_node):
for value in iter_expr_values(parent, def_node):
success = True
yield value
yield test_node
评论列表
文章目录