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)
Example #2
0
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)
Example #4
0
    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)
Example #6
0
    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
Example #7
0
    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
Example #8
0
    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)
Example #10
0
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)
Example #11
0
    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)
Example #12
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)
Example #13
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)
Example #14
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
Example #15
0
 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'))