def iter_child_expr_nodes(node):
for cursor_node in ast.iter_child_nodes(node):
yield cursor_node
for subcursor_node in iter_child_expr_nodes(cursor_node):
yield subcursor_node
python类iter_child_nodes()的实例源码
def node_is_child_of_parent_expr(parent, child):
for cursor_node in ast.iter_child_nodes(parent):
if cursor_node == child or (isinstance(cursor_node, ast.expr) and node_is_child_of_parent_expr(cursor_node, child)):
return True
return False
def set_parents(node):
for child in ast.iter_child_nodes(node):
setattr(child, 'parent', node)
set_parents(child)
def test_iter_child_nodes(self):
node = ast.parse("spam(23, 42, eggs='leek')", mode='eval')
self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4)
iterator = ast.iter_child_nodes(node.body)
self.assertEqual(next(iterator).id, 'spam')
self.assertEqual(next(iterator).n, 23)
self.assertEqual(next(iterator).n, 42)
self.assertEqual(ast.dump(next(iterator)),
"keyword(arg='eggs', value=Str(s='leek'))"
)
def set_location(node, lineno, col_offset):
"""Set node location information recursively."""
def _fix(node, lineno, col_offset):
if "lineno" in node._attributes:
node.lineno = lineno
if "col_offset" in node._attributes:
node.col_offset = col_offset
for child in ast.iter_child_nodes(node):
_fix(child, lineno, col_offset)
_fix(node, lineno, col_offset)
return node
def set_location(node, lineno, col_offset):
"""Set node location information recursively."""
def _fix(node, lineno, col_offset):
if "lineno" in node._attributes:
node.lineno = lineno
if "col_offset" in node._attributes:
node.col_offset = col_offset
for child in ast.iter_child_nodes(node):
_fix(child, lineno, col_offset)
_fix(node, lineno, col_offset)
return node
def _set_lineno(node, lineno, col_offset):
if 'lineno' in node._attributes:
if not hasattr(node, 'lineno'):
node.lineno = lineno
if 'col_offset' in node._attributes:
if not hasattr(node, 'col_offset'):
node.col_offset = col_offset
for child in ast.iter_child_nodes(node):
_set_lineno(child, lineno, col_offset)
def add_parent_info(root_node):
"""
Add parent attribute for all nodes at and under root_node, recursively.
"""
class AddParents(TopDownVisitor):
def generic_visit(self, node):
if not hasattr(node, 'parent'):
node.parent = None
for child in ast.iter_child_nodes(node):
child.parent = node
AddParents().visit(root_node)
def default(self, node, *args):
for child in iter_child_nodes(node):
self.dispatch(child, *args)
def generic_visit(self, node):
if hasattr(node, 'lineno'):
self._filldown(node.lineno + 1)
for _ in map(self.visit, iter_child_nodes(node)):
pass
def _extract_loads(self, bzl_file):
"""Walks the AST and extracts information on loaded symbols."""
load_symbols = []
try:
tree = ast.parse(open(bzl_file).read(), bzl_file)
key = None
for node in ast.iter_child_nodes(tree):
if not isinstance(node, ast.Expr):
continue
call = node.value
if (not isinstance(call, ast.Call) or
not isinstance(call.func, ast.Name) or
call.func.id != 'load'):
continue
args = []
for arg in call.args:
if not isinstance(arg, ast.Str):
raise LoadExtractorError(
'Only string literals in load statments are supported.')
args.append(arg.s)
kwargs = {}
for keyword in call.keywords:
if not isinstance(keyword.value, ast.Str):
raise LoadExtractorError(
'Only string literals in load statments are supported.')
kwargs[keyword.arg] = keyword.value.s
label = args[0]
for arg in args[1:]:
load_symbol = LoadSymbol(label, arg, None)
load_symbols.append(load_symbol)
for alias, symbol in kwargs.iteritems():
load_symbol = LoadSymbol(label, symbol, alias)
load_symbols.append(load_symbol)
except IOError:
print("Failed to parse {0}: {1}".format(bzl_file, e.strerror))
pass
return load_symbols
def _extract_docstrings(self, bzl_file):
"""Extracts the docstrings for all public rules in the .bzl file.
This function parses the .bzl file and extracts the docstrings for all
public rules in the file that were extracted in _process_skylark. It calls
_add_rule_doc for to parse the attribute documentation in each docstring
and associate them with the extracted rules and attributes.
Args:
bzl_file: The .bzl file to extract docstrings from.
"""
try:
tree = ast.parse(open(bzl_file).read(), bzl_file)
key = None
for node in ast.iter_child_nodes(tree):
if isinstance(node, ast.Assign):
name = node.targets[0].id
if not name.startswith("_"):
key = name
continue
elif isinstance(node, ast.Expr) and key:
# Python itself does not treat strings defined immediately after a
# global variable definition as a docstring. Only extract string and
# parse as docstring if it is defined.
if hasattr(node.value, 's'):
self._add_rule_doc(key, node.value.s.strip())
key = None
except IOError:
print("Failed to parse {0}: {1}".format(bzl_file, e.strerror))
pass
def descendants_of_type(root, nodetype):
result = []
if isinstance(root, nodetype):
result.append(root)
for ch in ast.iter_child_nodes(root):
ch_result = descendants_of_type(ch, nodetype)
result.extend(ch_result)
return result
def test_iter_child_nodes(self):
node = ast.parse("spam(23, 42, eggs='leek')", mode='eval')
self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4)
iterator = ast.iter_child_nodes(node.body)
self.assertEqual(next(iterator).id, 'spam')
self.assertEqual(next(iterator).n, 23)
self.assertEqual(next(iterator).n, 42)
self.assertEqual(ast.dump(next(iterator)),
"keyword(arg='eggs', value=Str(s='leek'))"
)
def generic_visit(self, node):
for child in ast.iter_child_nodes(node):
for t in self.visit(child):
yield t
def test_iter_child_nodes(self):
node = ast.parse("spam(23, 42, eggs='leek')", mode='eval')
self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4)
iterator = ast.iter_child_nodes(node.body)
self.assertEqual(next(iterator).id, 'spam')
self.assertEqual(next(iterator).n, 23)
self.assertEqual(next(iterator).n, 42)
self.assertEqual(ast.dump(next(iterator)),
"keyword(arg='eggs', value=Str(s='leek'))"
)
def test_iter_child_nodes(self):
node = ast.parse("spam(23, 42, eggs='leek')", mode='eval')
self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4)
iterator = ast.iter_child_nodes(node.body)
self.assertEqual(next(iterator).id, 'spam')
self.assertEqual(next(iterator).n, 23)
self.assertEqual(next(iterator).n, 42)
self.assertEqual(ast.dump(next(iterator)),
"keyword(arg='eggs', value=Str(s='leek'))"
)
def _get_ordered_child_nodes(node):
if isinstance(node, ast.Dict):
children = []
for i in range(len(node.keys)):
children.append(node.keys[i])
children.append(node.values[i])
return children
elif isinstance(node, ast.Call):
children = [node.func] + node.args
for kw in node.keywords:
children.append(kw.value)
# TODO: take care of Python 3.5 updates (eg. args=[Starred] and keywords)
if hasattr(node, "starargs") and node.starargs is not None:
children.append(node.starargs)
if hasattr(node, "kwargs") and node.kwargs is not None:
children.append(node.kwargs)
children.sort(key=lambda x: (x.lineno, x.col_offset))
return children
elif isinstance(node, ast.arguments):
children = node.args + node.kwonlyargs + node.kw_defaults + node.defaults
if node.vararg is not None:
children.append(node.vararg)
if node.kwarg is not None:
children.append(node.kwarg)
children.sort(key=lambda x: (x.lineno, x.col_offset))
return children
else:
return ast.iter_child_nodes(node)
def default(self, node, *args):
for child in iter_child_nodes(node):
self.dispatch(child, *args)
def test_iter_child_nodes(self):
node = ast.parse("spam(23, 42, eggs='leek')", mode='eval')
self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4)
iterator = ast.iter_child_nodes(node.body)
self.assertEqual(next(iterator).id, 'spam')
self.assertEqual(next(iterator).n, 23)
self.assertEqual(next(iterator).n, 42)
self.assertEqual(ast.dump(next(iterator)),
"keyword(arg='eggs', value=Str(s='leek'))"
)