def transform(self, node, results):
        meta_results = has_metaclass(node)
        if not meta_results: return
        for meta in meta_results:
            meta.remove()
        target = Leaf(token.NAME, u"__metaclass__")
        equal = Leaf(token.EQUAL, u"=", prefix=u" ")
        # meta is the last item in what was returned by has_metaclass(): name
        name = meta
        name.prefix = u" "
        stmt_node = Node(syms.atom, [target, equal, name])

        suitify(node)
        for item in node.children:
            if item.type == syms.suite:
                for stmt in item.children:
                    if stmt.type == token.INDENT:
                        # Insert, in reverse order, the statement, a newline,
                        # and an indent right after the first indented line
                        loc = item.children.index(stmt) + 1
                        # Keep consistent indentation form
                        ident = Leaf(token.INDENT, stmt.value)
                        item.insert_child(loc, ident)
                        item.insert_child(loc, Newline())
                        item.insert_child(loc, stmt_node)
                        break
def has_metaclass(parent):
    results = None
    for node in parent.children:
        kids = node.children
        if node.type == syms.argument:
            if kids[0] == Leaf(token.NAME, u"metaclass") and \
                kids[1] == Leaf(token.EQUAL, u"=") and \
                kids[2]:
                #Hack to avoid "class X(=):" with this case.
                results = [node] + kids
                break
        elif node.type == syms.arglist:
            # Argument list... loop through it looking for:
            # Node(*, [*, Leaf(token.NAME, u"metaclass"), Leaf(token.EQUAL, u"="), Leaf(*, *)]
            for child in node.children:
                if results: break
                if child.type == token.COMMA:
                    #Store the last comma, which precedes the metaclass
                    comma = child
                elif type(child) == Node:
                    meta = equal = name = None
                    for arg in child.children:
                        if arg == Leaf(token.NAME, u"metaclass"):
                            #We have the (metaclass) part
                            meta = arg
                        elif meta and arg == Leaf(token.EQUAL, u"="):
                            #We have the (metaclass=) part
                            equal = arg
                        elif meta and equal:
                            #Here we go, we have (metaclass=X)
                            name = arg
                            results = (comma, meta, equal, name)
                            break
    return results
Example #3
0
def _generate_import_node(package, name, prefix=""):

    def DottedName(name, prefix=""):
        split = name.rsplit('.')
        if len(split) > 1:
            # Reconstruct the dotted name as a list of leaves
            leftmost_name = Leaf(token.NAME, split[0])
            children = [leftmost_name]
            for entry in split[1:]:
                next_name = [Leaf(token.DOT, '.'), Leaf(token.NAME, entry)]
                children.extend(next_name)
            return Node(syms.dotted_name, children, prefix=prefix)
        return Leaf(token.NAME, name, prefix=prefix)

    if not package:
        import_ = Node(syms.import_name, [
            Leaf(token.NAME, "import", prefix=prefix),
            DottedName(name, prefix=" ")
        ])
    else:
        import_ = Node(syms.import_from, [
            Leaf(token.NAME, "from", prefix=prefix),
            DottedName(package, prefix=" "),
            Leaf(token.NAME, "import", prefix=" "),
            Leaf(token.NAME, name, prefix=" "),
        ])

    return import_
Example #4
0
 def DottedName(name, prefix=""):
     split = name.rsplit('.')
     if len(split) > 1:
         # Reconstruct the dotted name as a list of leaves
         leftmost_name = Leaf(token.NAME, split[0])
         children = [leftmost_name]
         for entry in split[1:]:
             next_name = [Leaf(token.DOT, '.'), Leaf(token.NAME, entry)]
             children.extend(next_name)
         return Node(syms.dotted_name, children, prefix=prefix)
     return Leaf(token.NAME, name, prefix=prefix)
Example #5
0
 def transform(self, node, results):
     name, val, trc = (results.get_products(u"name"), results.get_products(u"val"), results.get_products(u"trc"))
     chain = results.get_products(u"chain")
     if chain is not None:
         self.warning(node, u"explicit exception chaining is not supported in Python 2")
         chain.prev_sibling.remove()
         chain.remove()
     if trc is not None:
         val = val[0] if val else Leaf(token.NAME, u"None")
         val.prefix = trc.prefix = u" "
         kids = [Leaf(token.NAME, u"raise"), name.clone(), Comma(),
                 val.clone(), Comma(), trc.clone()]
         raise_stmt = Node(syms.raise_stmt, kids)
         node.replace(raise_stmt)
 def transform(self, node, result):
     if len(node.children) == 3 and node.children[-1].type == token.NUMBER:
         userdata_id = int(node.children[-1].value)
         replacement = self.subfun(userdata_id)
         if replacement:
             new = Node(python_symbols.subscriptlist,
                        [Leaf(token.NAME, replacement)])
             return new
     return None
    def transform(self, node, results):
        # Determine the node's column number by finding the first leaf.
        leaf = node
        while not isinstance(leaf, Leaf):
            leaf = leaf.children[0]
        # Only match functions and the global indentation level.
        if leaf.column != 0:
            return

        indent = None
        for child in node.children:
            if isinstance(child, Node) and child.type == python_symbols.suite:
                indent = find_indentation(child)
            if isinstance(
                    child, Leaf
            ) and child.type == token.NAME and child.value == self.funcname:
                child.value = self.newname
            elif isinstance(child,
                            Node) and child.type == python_symbols.parameters:
                pre_params = []
                for param in self.pre_params:
                    pre_params.append(Leaf(token.NAME, param))
                    pre_params.append(Leaf(token.COMMA, ', '))
                child.children[1:1] = pre_params
                post_params = []
                for param in self.post_params:
                    post_params.append(Leaf(token.COMMA, ','))
                    post_params.append(Leaf(token.NAME, param))
                child.children[-1:-1] = post_params
                if child.children[-2].type == token.COMMA:
                    child.children.pop(-2)
                child.changed()
        if self.add_statement:
            node.children.append(
                Leaf(0, indent + self.add_statement.rstrip() + '\n'))
        if self.remove:
            self.results.append(node)
            node.replace([])
            return None
        else:
            return node
Example #8
0
def _new_type_check_with_import(package, name, root, insert_pos):
    # type: (Optional[str], str, Node, int) -> None
    """
    Inserts a new TYPE_CHECKING block containing a new import statement for package and name

    Parameters
    -----------
    package : Optional[str]
    name : str
    root : Node
    insert_pos : int
    """
    # [Grammar]
    # if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite]
    type_check_node = Node(syms.if_stmt,
                           [Leaf(token.NAME, 'if'),
                            Leaf(token.NAME, 'TYPE_CHECKING', prefix=" "),
                            Leaf(token.COLON, ':'),
                            # [Grammar]
                            # suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
                            Node(syms.suite, [Leaf(token.NEWLINE, '\n'),
                                              Leaf(token.INDENT, '    '),
                                              Node(syms.simple_stmt,
                                                   [_generate_import_node(package, name), Newline()]),
                                              Leaf(token.DEDENT, '')])])

    # We can just hardcode the correct insert position since we just created the typing block
    root.insert_child(insert_pos, type_check_node)
    # Make sure to import TYPE_CHECKING just before using
    import_type_checking = [_generate_import_node('typing', 'TYPE_CHECKING'), Newline()]
    root.insert_child(insert_pos, Node(syms.simple_stmt, import_type_checking))
Example #9
0
def assignment_source(num_pre, num_post, LISTNAME, ITERNAME):
    u"""
    Accepts num_pre and num_post, which are counts of values
    before and after the starg (not including the starg)
    Returns a source fit for Assign() from fixer_util
    """
    children = []
    pre = unicode(num_pre)
    post = unicode(num_post)
    # This code builds the assignment source from lib2to3 tree primitives.
    # It's not very readable, but it seems like the most correct way to do it.
    if num_pre > 0:
        pre_part = Node(syms.power, [Name(LISTNAME), Node(syms.trailer, [Leaf(token.LSQB, u"["), Node(syms.subscript, [Leaf(token.COLON, u":"), Number(pre)]), Leaf(token.RSQB, u"]")])])
        children.append(pre_part)
        children.append(Leaf(token.PLUS, u"+", prefix=u" "))
    main_part = Node(syms.power, [Leaf(token.LSQB, u"[", prefix=u" "), Name(LISTNAME), Node(syms.trailer, [Leaf(token.LSQB, u"["), Node(syms.subscript, [Number(pre) if num_pre > 0 else Leaf(1, u""), Leaf(token.COLON, u":"), Node(syms.factor, [Leaf(token.MINUS, u"-"), Number(post)]) if num_post > 0 else Leaf(1, u"")]), Leaf(token.RSQB, u"]"), Leaf(token.RSQB, u"]")])])
    children.append(main_part)
    if num_post > 0:
        children.append(Leaf(token.PLUS, u"+", prefix=u" "))
        post_part = Node(syms.power, [Name(LISTNAME, prefix=u" "), Node(syms.trailer, [Leaf(token.LSQB, u"["), Node(syms.subscript, [Node(syms.factor, [Leaf(token.MINUS, u"-"), Number(post)]), Leaf(token.COLON, u":")]), Leaf(token.RSQB, u"]")])])
        children.append(post_part)
    source = Node(syms.arith_expr, children)
    return source
Example #10
0
    def transform(self, node, results):
        fixup_parse_tree(node)

        text_type = node.children[0].type # always Leaf(nnn, 'class')

        # figure out what kind of classdef we have
        if len(node.children) == 7:
            # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
            #                 0        1       2    3        4    5    6
            if node.children[3].type == syms.arglist:
                arglist = node.children[3]
            # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
            else:
                parent = node.children[3].clone()
                arglist = Node(syms.arglist, [parent])
                node.set_child(3, arglist)
        elif len(node.children) == 6:
            # Node(classdef, ['class', 'name', '(',  ')', ':', suite])
            #                 0        1       2     3    4    5
            arglist = Node(syms.arglist, [])
            node.insert_child(3, arglist)
        elif len(node.children) == 4:
            # Node(classdef, ['class', 'name', ':', suite])
            #                 0        1       2    3
            arglist = Node(syms.arglist, [])
            node.insert_child(2, Leaf(token.RPAR, u')'))
            node.insert_child(2, arglist)
            node.insert_child(2, Leaf(token.LPAR, u'('))
        else:
            raise ValueError("Unexpected class definition")

        for child in arglist.children:
            if child.value == 'Torsion':
                child.value = 'Dihedral'
            if child.value == 'Improper_Torsion':
                child.value = 'ImproperDihedral'
    def transform(self, node, results):
        u"""
        This replaces function type annotations with a commented version.
        """

        params = results.get(u"params")
        body = results.get(u"body")
        ret = results.get(u"ret")
        lhs = results.get(u"lhs")
        ann = results.get(u"ann")
        rhs = results.get(u"rhs")
        annnode = results.get(u"annnode")
        
        if params is not None and body is not None:
            ret_type = u"None"
            types = []
            for child in params.children:
                if child.type == syms.typedargslist:
                    types = handle_typedargslist(child)
                elif child.type == syms.tname:
                    types = retrieve_type(child)
                    handle_tname_or_name(child)
            if ret is not None:
                assert ret.prev_sibling.type == token.RARROW, u"invalid return annotation"
                ret_type = ret.value
                ret.prev_sibling.remove()
                ret.remove()
            type_sig = "# type: ({}) -> {}".format(", ".join(types), ret_type)
            type_sig_comment = Leaf(token.COMMENT, type_sig)

            indents = [l for l in body.leaves() if l.type == token.INDENT]
            if not len(indents):
                indent_node = Leaf(token.INDENT, "    ")
                body.insert_child(0, indent_node)
                body.insert_child(0, Leaf(token.NEWLINE, "\n"))
            else:
                indent_node = indents[0]
            body.insert_child(0, type_sig_comment)
            body.insert_child(0, indent_node)
            body.insert_child(0, Leaf(token.NEWLINE, "\n"))
        elif ann is not None:
            type_ann_comment = Leaf(token.COMMENT, "  # type: {}".format(
                ''.join(x.value for x in ann.leaves())
            ))
            lhs.parent.append_child(Leaf(token.EQUAL, " ="))
            if rhs is None:
                lhs.parent.append_child(Leaf(token.NAME, " None"))
            else:
                lhs.parent.append_child(rhs)
            annnode.remove()
            lhs.parent.append_child(type_ann_comment)
Example #12
0
def Import(name_leafs):

    for leaf in name_leafs:
        # Pull the leaves out of their old tree
        leaf.remove()

    def add_commas(leafs):
        yield leafs[0]
        for a in leafs[1:]:
            yield Comma()
            yield a

    children = [Leaf(token.NAME, u'import'),
                Node(syms.dotted_as_names, list(add_commas(name_leafs)))]
    imp = Node(syms.import_name, children)
    return imp
Example #13
0
    def transform(self, node, results):
        if not has_metaclass(node):
            return  # pragma: no cover

        fixup_parse_tree(node)

        # find metaclasses, keep the last one
        last_metaclass = None
        for suite, i, stmt in find_metas(node):
            last_metaclass = stmt
            stmt.remove()

        text_type = node.children[0].type  # always Leaf(nnn, 'class')

        # figure out what kind of classdef we have
        if len(node.children) == 7:
            # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
            #                 0        1       2    3        4    5    6
            if node.children[3].type == syms.arglist:
                arglist = node.children[3]
            # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
            else:
                parent = node.children[3].clone()
                arglist = Node(syms.arglist, [parent])
                node.set_child(3, arglist)
        elif len(node.children) == 6:
            # Node(classdef, ['class', 'name', '(',  ')', ':', suite])
            #                 0        1       2     3    4    5
            arglist = Node(syms.arglist, [])
            node.insert_child(3, arglist)
        elif len(node.children) == 4:
            # Node(classdef, ['class', 'name', ':', suite])
            #                 0        1       2    3
            arglist = Node(syms.arglist, [])
            node.insert_child(2, Leaf(token.RPAR, u')'))
            node.insert_child(2, arglist)
            node.insert_child(2, Leaf(token.LPAR, u'('))
        else:
            raise ValueError("Unexpected class definition")  # pragma: no cover

        touch_import(None, u'six', node)

        metaclass = last_metaclass.children[0].children[2].clone()
        metaclass.prefix = u''

        arguments = [metaclass]

        if arglist.children:
            bases = arglist.clone()
            bases.prefix = u' '
            arguments.extend([Comma(), bases])

        arglist.replace(
            Call(Name(u'six.with_metaclass', prefix=arglist.prefix),
                 arguments))

        fixup_indent(suite)

        # check for empty suite
        if not suite.children:
            # one-liner that was just __metaclass__
            suite.remove()
            pass_leaf = Leaf(text_type, u'pass')
            pass_leaf.prefix = last_metaclass.prefix
            node.append_child(pass_leaf)
            node.append_child(Leaf(token.NEWLINE, u'\n'))

        elif len(suite.children) > 1 and \
                 (suite.children[-2].type == token.INDENT and
                  suite.children[-1].type == token.DEDENT):
            # there was only one line in the class body and it was __metaclass__
            pass_leaf = Leaf(text_type, u'pass')
            suite.insert_child(-1, pass_leaf)
            suite.insert_child(-1, Leaf(token.NEWLINE, u'\n'))
Example #14
0
    def transform(self, node, results):
        if not has_metaclass(node):
            return

        fixup_parse_tree(node)

        # find metaclasses, keep the last one
        last_metaclass = None
        for suite, i, stmt in find_metas(node):
            last_metaclass = stmt
            stmt.remove()

        text_type = node.children[0].type  # always Leaf(nnn, 'class')

        # figure out what kind of classdef we have
        if len(node.children) == 7:
            # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
            #                 0        1       2    3        4    5    6
            if node.children[3].type == syms.arglist:
                arglist = node.children[3]
            # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
            else:
                parent = node.children[3].clone()
                arglist = Node(syms.arglist, [parent])
                node.set_child(3, arglist)
        elif len(node.children) == 6:
            # Node(classdef, ['class', 'name', '(',  ')', ':', suite])
            #                 0        1       2     3    4    5
            arglist = Node(syms.arglist, [])
            node.insert_child(3, arglist)
        elif len(node.children) == 4:
            # Node(classdef, ['class', 'name', ':', suite])
            #                 0        1       2    3
            arglist = Node(syms.arglist, [])
            node.insert_child(2, Leaf(token.RPAR, u')'))
            node.insert_child(2, arglist)
            node.insert_child(2, Leaf(token.LPAR, u'('))
        else:
            raise ValueError("Unexpected class definition")

        # now stick the metaclass in the arglist
        meta_txt = last_metaclass.children[0].children[0]
        meta_txt.value = 'metaclass'
        orig_meta_prefix = meta_txt.prefix

        # Was: touch_import(None, u'future.utils', node)
        touch_import(u'future.utils', u'with_metaclass', node)

        metaclass = last_metaclass.children[0].children[2].clone()
        metaclass.prefix = u''

        arguments = [metaclass]

        if arglist.children:
            if len(arglist.children) == 1:
                base = arglist.children[0].clone()
                base.prefix = u' '
            else:
                # Unfortunately six.with_metaclass() only allows one base
                # class, so we have to dynamically generate a base class if
                # there is more than one.
                bases = parenthesize(arglist.clone())
                bases.prefix = u' '
                base = Call(Name('type'), [
                    String("'NewBase'"),
                    Comma(), bases,
                    Comma(),
                    Node(syms.atom,
                         [Leaf(token.LBRACE, u'{'),
                          Leaf(token.RBRACE, u'}')],
                         prefix=u' ')
                ],
                            prefix=u' ')
            arguments.extend([Comma(), base])

        arglist.replace(
            Call(Name(u'with_metaclass', prefix=arglist.prefix), arguments))

        fixup_indent(suite)

        # check for empty suite
        if not suite.children:
            # one-liner that was just __metaclass_
            suite.remove()
            pass_leaf = Leaf(text_type, u'pass')
            pass_leaf.prefix = orig_meta_prefix
            node.append_child(pass_leaf)
            node.append_child(Leaf(token.NEWLINE, u'\n'))

        elif len(suite.children) > 1 and \
                (suite.children[-2].type == token.INDENT and
                 suite.children[-1].type == token.DEDENT):
            # there was only one line in the class body and it was __metaclass__
            pass_leaf = Leaf(text_type, u'pass')
            suite.insert_child(-1, pass_leaf)
            suite.insert_child(-1, Leaf(token.NEWLINE, u'\n'))
Example #15
0
    def transform(self, node, results):
        if not has_metaclass(node):
            return

        fixup_parse_tree(node)

        # find metaclasses, keep the last one
        last_metaclass = None
        for suite, i, stmt in find_metas(node):
            last_metaclass = stmt
            stmt.remove()

        text_type = node.children[0].type # always Leaf(nnn, 'class')

        # figure out what kind of classdef we have
        if len(node.children) == 7:
            # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
            #                 0        1       2    3        4    5    6
            if node.children[3].type == syms.arglist:
                arglist = node.children[3]
            # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
            else:
                parent = node.children[3].clone()
                arglist = Node(syms.arglist, [parent])
                node.set_child(3, arglist)
        elif len(node.children) == 6:
            # Node(classdef, ['class', 'name', '(',  ')', ':', suite])
            #                 0        1       2     3    4    5
            arglist = Node(syms.arglist, [])
            node.insert_child(3, arglist)
        elif len(node.children) == 4:
            # Node(classdef, ['class', 'name', ':', suite])
            #                 0        1       2    3
            arglist = Node(syms.arglist, [])
            node.insert_child(2, Leaf(token.RPAR, u')'))
            node.insert_child(2, arglist)
            node.insert_child(2, Leaf(token.LPAR, u'('))
        else:
            raise ValueError("Unexpected class definition")

        touch_import(None, u'six', node)

        metaclass = last_metaclass.children[0].children[2].clone()
        metaclass.prefix = u''

        arguments = [metaclass]

        if arglist.children:
            if len(arglist.children) == 1:
                base = arglist.children[0].clone()
                base.prefix = u' '
            else:
                # Unfortunately six.with_metaclass() only allows one base
                # class, so we have to dynamically generate a base class if
                # there is more than one.
                bases = parenthesize(arglist.clone())
                bases.prefix = u' '
                base = Call(Name('type'), [
                    String("'NewBase'"),
                    Comma(),
                    bases,
                    Comma(),
                    Node(
                        syms.atom,
                        [Leaf(token.LBRACE, u'{'), Leaf(token.RBRACE, u'}')],
                        prefix=u' '
                    )
                ], prefix=u' ')
            arguments.extend([Comma(), base])

        arglist.replace(Call(
            Name(u'six.with_metaclass', prefix=arglist.prefix),
            arguments
        ))

        fixup_indent(suite)

        # check for empty suite
        if not suite.children:
            # one-liner that was just __metaclass_
            suite.remove()
            pass_leaf = Leaf(text_type, u'pass')
            pass_leaf.prefix = orig_meta_prefix
            node.append_child(pass_leaf)
            node.append_child(Leaf(token.NEWLINE, u'\n'))

        elif len(suite.children) > 1 and \
                 (suite.children[-2].type == token.INDENT and
                  suite.children[-1].type == token.DEDENT):
            # there was only one line in the class body and it was __metaclass__
            pass_leaf = Leaf(text_type, u'pass')
            suite.insert_child(-1, pass_leaf)
            suite.insert_child(-1, Leaf(token.NEWLINE, u'\n'))
    def transform(self, node, results):
        if not has_metaclass(node):
            return  # pragma: no cover

        fixup_parse_tree(node)

        # find metaclasses, keep the last one
        last_metaclass = None
        for suite, i, stmt in find_metas(node):
            last_metaclass = stmt
            stmt.remove()

        text_type = node.children[0].type  # always Leaf(nnn, 'class')

        # figure out what kind of classdef we have
        if len(node.children) == 7:
            # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
            #                 0        1       2    3        4    5    6
            if node.children[3].type == syms.arglist:
                arglist = node.children[3]
            # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
            else:
                parent = node.children[3].clone()
                arglist = Node(syms.arglist, [parent])
                node.set_child(3, arglist)
        elif len(node.children) == 6:
            # Node(classdef, ['class', 'name', '(',  ')', ':', suite])
            #                 0        1       2     3    4    5
            arglist = Node(syms.arglist, [])
            node.insert_child(3, arglist)
        elif len(node.children) == 4:
            # Node(classdef, ['class', 'name', ':', suite])
            #                 0        1       2    3
            arglist = Node(syms.arglist, [])
            node.insert_child(2, Leaf(token.RPAR, u")"))
            node.insert_child(2, arglist)
            node.insert_child(2, Leaf(token.LPAR, u"("))
        else:
            raise ValueError("Unexpected class definition")  # pragma: no cover

        touch_import(None, u"six", node)

        metaclass = last_metaclass.children[0].children[2].clone()
        metaclass.prefix = u""

        arguments = [metaclass]

        if arglist.children:
            bases = arglist.clone()
            bases.prefix = u" "
            arguments.extend([Comma(), bases])

        arglist.replace(Call(Name(u"six.with_metaclass", prefix=arglist.prefix), arguments))

        fixup_indent(suite)

        # check for empty suite
        if not suite.children:
            # one-liner that was just __metaclass__
            suite.remove()
            pass_leaf = Leaf(text_type, u"pass")
            pass_leaf.prefix = last_metaclass.prefix
            node.append_child(pass_leaf)
            node.append_child(Leaf(token.NEWLINE, u"\n"))

        elif len(suite.children) > 1 and (
            suite.children[-2].type == token.INDENT and suite.children[-1].type == token.DEDENT
        ):
            # there was only one line in the class body and it was __metaclass__
            pass_leaf = Leaf(text_type, u"pass")
            suite.insert_child(-1, pass_leaf)
            suite.insert_child(-1, Leaf(token.NEWLINE, u"\n"))