def _testlist(self, test): if is_ast_node(test, (ast.Yield, 'YieldFrom')): self.code += '(' self._yield_expr(test) self.code += ')' elif is_ast_node(test, 'NamedExpr'): self.code += '(' self.visit_NamedExpr(test) self.code += ')' else: self.visit(test)
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 is_ast_node(node, (ast.FunctionDef, '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 is_ast_node(node, 'Nonlocal'): namespace.nonlocal_names.update(node.names) for child in ast.iter_child_nodes(node): add_parent(child, parent=node, namespace=namespace)
def _expression(self, expression): if is_ast_node(expression, (ast.Yield, 'YieldFrom')): self.code += '(' self._yield_expr(expression) self.code += ')' elif isinstance(expression, ast.Tuple) and len(expression.elts) > 0: self.code += '(' self.visit_Tuple(expression) self.code += ')' elif is_ast_node(expression, 'NamedExpr'): self.code += '(' self.visit_NamedExpr(expression) self.code += ')' else: self.visit(expression)
def candidates(self): actual_candidates = [] for quote in self.allowed_quotes: candidates = [''] nested_allowed = copy.copy(self.allowed_quotes) nested_allowed.remove(quote) for v in self.node.values: if is_ast_node(v, ast.Str): try: candidates = [x + self.str_for(v.s, quote) for x in candidates] except Exception as e: continue elif isinstance(v, ast.FormattedValue): try: candidates = [ x + y for x in candidates for y in FormattedValue(v, nested_allowed).get_candidates() ] except Exception as e: continue else: raise RuntimeError('Unexpected JoinedStr value') actual_candidates += ['f' + quote + x + quote for x in candidates] actual_candidates = filter(self.is_correct_ast, actual_candidates) return actual_candidates
def visit_JoinedStr(self, node): for v in node.values: if is_ast_node(v, ast.Str): # Can't hoist this! continue else: self.visit(v)
def namespace(self, node): if hasattr(node, 'namespace'): if is_ast_node( node.namespace, (ast.FunctionDef, ast.ClassDef, 'AsyncFunctionDef')): return self.namespace( node.namespace) + '.' + node.namespace.name elif isinstance(node.namespace, ast.Module): return '' else: return repr(node.namespace.__class__) return None
def candidates(self): candidates = [''] for v in self.node.values: if is_ast_node(v, ast.Str): candidates = [x + self.str_for(v.s) for x in candidates] elif isinstance(v, ast.FormattedValue): candidates = [ x + y for x in candidates for y in FormattedValue(v, self.allowed_quotes).get_candidates() ] else: raise RuntimeError('Unexpected JoinedStr value') return candidates
def suite(self, node_list, parent): without_pass = [ self.visit(a) for a in filter(lambda n: not is_ast_node(n, ast.Pass), node_list) ] if len(without_pass) == 0: if isinstance(parent, ast.Module): return [] else: return [ self.add_child(ast.Expr(value=ast.Num(0)), parent=parent) ] return without_pass
def nearest_function_namespace(node): """ Return the namespace node for the nearest function scope. This could be itself. :param node: The node to get the function namespace of :type node: ast.Node :rtype: ast.Node """ if is_ast_node(node, (ast.FunctionDef, ast.Module, 'AsyncFunctionDef')): return node return nearest_function_namespace(node.parent)
def resolve_names(node): """ Resolve unbound names to a NameBinding :param node: The module to resolve names in :type node: :class:`ast.Module` """ if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load): get_binding(node.id, node.namespace).add_reference(node) elif is_ast_node(node, 'Exec'): get_global_namespace(node).tainted = True for child in ast.iter_child_nodes(node): resolve_names(child)
def additional_byte_cost(self): """ How many additional bytes would be used, if this was renamed """ arg_rename = False additional_bytes = 0 for node in self._references: if isinstance(node, ast.Name): if isinstance(node.ctx, (ast.Load, ast.Store, ast.Del)): pass else: # Python 2 Param context if not arg_rename_in_place(node): arg_rename = True elif is_ast_node( node, (ast.ClassDef, ast.FunctionDef, 'AsyncFunctionDef')): pass elif isinstance(node, ast.ExceptHandler): pass elif is_ast_node(node, (ast.Global, 'Nonlocal')): pass elif isinstance(node, ast.alias): if node.asname is None: additional_bytes += 4 # ' as ' elif isinstance(node, ast.arguments): if node.vararg == self._name: pass if node.kwarg == self._name: pass elif is_ast_node(node, 'arg'): if not arg_rename_in_place(node): arg_rename = True elif is_ast_node(node, 'MatchAs'): if node.name is None: additional_bytes += 4 # ' as ' elif is_ast_node(node, 'MatchStar'): pass elif is_ast_node(node, 'MatchMapping'): pass else: raise AssertionError('Unknown reference node') return additional_bytes + (2 if arg_rename else 0)
def old_mention_count(self): """ The number of times the old name would be mentioned in the source code, if this binding was renamed """ arg_rename = False mentions = 0 for node in self._references: if isinstance(node, ast.Name): if isinstance(node.ctx, (ast.Load, ast.Store, ast.Del)): pass else: # Python 2 Param context if not arg_rename_in_place(node): mentions += 1 arg_rename = True elif is_ast_node( node, (ast.ClassDef, ast.FunctionDef, 'AsyncFunctionDef')): pass elif isinstance(node, ast.ExceptHandler): pass elif is_ast_node(node, (ast.Global, 'Nonlocal')): pass elif isinstance(node, ast.alias): if node.asname is None: # import foo -> import foo as bar mentions += 1 elif isinstance(node, ast.arguments): pass elif is_ast_node(node, 'arg'): if not arg_rename_in_place(node): mentions += 1 arg_rename = True elif is_ast_node(node, 'MatchAs'): pass elif is_ast_node(node, 'MatchStar'): pass elif is_ast_node(node, 'MatchMapping'): pass else: raise AssertionError('Unknown reference node') return mentions + (1 if arg_rename else 0)
def new_mention_count(self): """ The number of times a new name would be mentioned in the source code """ arg_rename = False mentions = 0 for node in self._references: if isinstance(node, ast.Name): if isinstance(node.ctx, (ast.Load, ast.Store, ast.Del)): mentions += 1 else: # Python 2 Param context arg_rename = True elif is_ast_node( node, (ast.ClassDef, ast.FunctionDef, 'AsyncFunctionDef')): mentions += 1 elif isinstance(node, ast.ExceptHandler): mentions += 1 elif is_ast_node(node, (ast.Global, 'Nonlocal')): mentions += len([n for n in node.names if n == self._name]) elif isinstance(node, ast.alias): mentions += 1 elif isinstance(node, ast.arguments): if node.vararg == self._name: mentions += 1 if node.kwarg == self._name: mentions += 1 elif is_ast_node(node, 'arg'): arg_rename = True elif is_ast_node(node, 'MatchAs'): mentions += 1 elif is_ast_node(node, 'MatchStar'): mentions += 1 elif is_ast_node(node, 'MatchMapping'): mentions += 1 else: raise AssertionError('Unknown reference node') return mentions + (1 if arg_rename else 0)
def rename(self, new_name): """ Rename this binding and all nodes that reference it :param str new_name: The new name to use """ func_namespace_binding = None for node in self.references: if isinstance(node, ast.Name): if isinstance(node.ctx, (ast.Load, ast.Store, ast.Del)): node.id = new_name else: # Python 2 Param context if arg_rename_in_place(node): node.id = new_name else: if func_namespace_binding is None: func_namespace_binding = node.namespace else: assert func_namespace_binding is node.namespace elif is_ast_node(node, (ast.FunctionDef, 'AsyncFunctionDef')): node.name = new_name elif isinstance(node, ast.ClassDef): node.name = new_name elif isinstance(node, ast.alias): if new_name == node.name: node.asname = None else: node.asname = new_name elif is_ast_node(node, 'arg'): if arg_rename_in_place(node): node.arg = new_name else: if func_namespace_binding is None: func_namespace_binding = node.namespace else: assert func_namespace_binding is node.namespace elif isinstance(node, ast.ExceptHandler): node.name = new_name elif is_ast_node(node, (ast.Global, 'Nonlocal')): node.names = [ new_name if n == self._name else n for n in node.names ] elif isinstance(node, ast.arguments): rename_vararg = (node.vararg == self._name) and not getattr( node, 'vararg_renamed', False) rename_kwarg = (node.kwarg == self._name) and not getattr( node, 'kwarg_renamed', False) if rename_vararg: node.vararg = new_name node.vararg_renamed = True if rename_kwarg: node.kwarg = new_name node.kwarg_renamed = True elif is_ast_node(node, 'MatchAs'): node.name = new_name elif is_ast_node(node, 'MatchStar'): node.name = new_name elif is_ast_node(node, 'MatchMapping'): node.rest = new_name if func_namespace_binding is not None: func_namespace_binding.body = list( insert( func_namespace_binding.body, ast.Assign( targets=[ast.Name(id=new_name, ctx=ast.Store())], value=ast.Name(id=self._name, ctx=ast.Load()), ), )) self._name = new_name
def value(self): if is_ast_node(self._value_node, (ast.Str, 'Bytes')): return self._value_node.s else: return self._value_node.value
def is_literal_statement(self, node): if not isinstance(node, ast.Expr): return False return is_ast_node(node.value, (ast.Num, ast.Str, 'NameConstant', 'Bytes'))