def add_parent(node, parent=None, namespace=None): """ Add a parent attribute to child nodes Add a namespace attribute to child nodes :param node: The tree to add parent and namespace properties to :type node: :class:`ast.AST` :param parent: The parent node of this node :type parent: :class:`ast.AST` :param namespace: The namespace Node that this node is in :type namespace: ast.Lambda or ast.Module or ast.FunctionDef or ast.AsyncFunctionDef or ast.ClassDef or ast.DictComp or ast.SetComp or ast.ListComp or ast.Generator """ node.parent = parent if parent is not None else node node.namespace = namespace if namespace is not None else node if is_namespace(node): node.bindings = [] node.global_names = set() node.nonlocal_names = set() if isinstance(node, ast.FunctionDef) or ( hasattr(ast, 'AsyncFunctionDef') and isinstance(node, ast.AsyncFunctionDef)): add_parent_to_functiondef(node) elif isinstance(node, ast.Lambda): add_parent_to_arguments(node.args, func=node) add_parent(node.body, parent=node, namespace=node) elif isinstance(node, ast.ClassDef): add_parent_to_classdef(node) else: for child in ast.iter_child_nodes(node): add_parent(child, parent=node, namespace=node) return if isinstance(node, ast.comprehension): add_parent(node.target, parent=node, namespace=namespace) add_parent(node.iter, parent=node, namespace=namespace) for if_ in node.ifs: add_parent(if_, parent=node, namespace=namespace) return if isinstance(node, ast.Global): namespace.global_names.update(node.names) if hasattr(ast, 'Nonlocal') and isinstance(node, ast.Nonlocal): namespace.nonlocal_names.update(node.names) for child in ast.iter_child_nodes(node): add_parent(child, parent=node, namespace=namespace)
def add_assigned(node): """ Add the assigned_names attribute to namespace nodes in a module :param node: The module to add the assigned_names attribute to :type node: :class:`ast.Module` """ if is_namespace(node): node.assigned_names = set() for child in ast.iter_child_nodes(node): add_assigned(child)
def all_bindings(node): """ All bindings in a module :param node: The module to get bindings in :type node: :class:`ast.AST` :rtype: Iterable[ast.AST, Binding] """ if is_namespace(node): for binding in node.bindings: yield node, binding for child in ast.iter_child_nodes(node): for namespace, binding in all_bindings(child): yield namespace, binding