예제 #1
0
 def transform(self, node, results):
     head = results["head"]
     method = results["method"][0]  # Extract node for method name
     tail = results["tail"]
     syms = self.syms
     method_name = method.value
     isiter = method_name.startswith("iter")
     isview = method_name.startswith("view")
     if isiter or isview:
         method_name = method_name[4:]
     assert method_name in ("keys", "items", "values"), repr(method)
     head = [n.clone() for n in head]
     tail = [n.clone() for n in tail]
     special = not tail and self.in_special_context(node, isiter)
     args = head + [
         pytree.Node(syms.trailer,
                     [Dot(), Name(method_name, prefix=method.prefix)]),
         results["parens"].clone(),
     ]
     new = pytree.Node(syms.power, args)
     if not (special or isview):
         new.prefix = ""
         new = Call(Name("iter" if isiter else "list"), [new])
     if tail:
         new = pytree.Node(syms.power, [new] + tail)
     new.prefix = node.prefix
     return new
예제 #2
0
    def transform(self, node, results):
        syms = self.syms

        exc = results["exc"].clone()
        if exc.type is token.STRING:
            self.cannot_convert(node,
                                "Python 3 does not support string exceptions")
            return

        # Leave "g.throw(E)" alone
        val = results.get("val")
        if val is None:
            return

        val = val.clone()
        if is_tuple(val):
            args = [c.clone() for c in val.children[1:-1]]
        else:
            val.prefix = ""
            args = [val]

        throw_args = results["args"]

        if "tb" in results:
            tb = results["tb"].clone()
            tb.prefix = ""

            e = Call(exc, args)
            with_tb = Attr(e, Name("with_traceback")) + [ArgList([tb])]
            throw_args.replace(pytree.Node(syms.power, with_tb))
        else:
            throw_args.replace(Call(exc, args))
예제 #3
0
 def transform_isinstance(self, node, results):
     x = results["x"].clone()  # The thing inside of type()
     T = results["T"].clone()  # The type being compared against
     x.prefix = ""
     T.prefix = " "
     test = Call(Name("isinstance"), [x, Comma(), T])
     if "n" in results:
         test.prefix = " "
         test = Node(syms.not_test, [Name("not"), test])
     test.prefix = node.prefix
     return test
예제 #4
0
    def transform(self, node, results):
        syms = self.syms

        exc = results["exc"].clone()
        if exc.type == token.STRING:
            msg = "Python 3 does not support string exceptions"
            self.cannot_convert(node, msg)
            return

        # Python 2 supports
        #  raise ((((E1, E2), E3), E4), E5), V
        # as a synonym for
        #  raise E1, V
        # Since Python 3 will not support this, we recurse down any tuple
        # literals, always taking the first element.
        if is_tuple(exc):
            while is_tuple(exc):
                # exc.children[1:-1] is the unparenthesized tuple
                # exc.children[1].children[0] is the first element of the tuple
                exc = exc.children[1].children[0].clone()
            exc.prefix = " "

        if "val" not in results:
            # One-argument raise
            new = pytree.Node(syms.raise_stmt, [Name("raise"), exc])
            new.prefix = node.prefix
            return new

        val = results["val"].clone()
        if is_tuple(val):
            args = [c.clone() for c in val.children[1:-1]]
        else:
            val.prefix = ""
            args = [val]

        if "tb" in results:
            tb = results["tb"].clone()
            tb.prefix = ""

            e = exc
            # If there's a traceback and None is passed as the value, then don't
            # add a call, since the user probably just wants to add a
            # traceback. See issue #9661.
            if val.type != token.NAME or val.value != "None":
                e = Call(exc, args)
            with_tb = Attr(e, Name("with_traceback")) + [ArgList([tb])]
            new = pytree.Node(syms.simple_stmt, [Name("raise")] + with_tb)
            new.prefix = node.prefix
            return new
        else:
            return pytree.Node(syms.raise_stmt,
                               [Name("raise"), Call(exc, args)],
                               prefix=node.prefix)
예제 #5
0
 def transform_range(self, node, results):
     if id(
             node
     ) not in self.transformed_xranges and not self.in_special_context(
             node):
         range_call = Call(Name("range"), [results["args"].clone()])
         # Encase the range call in list().
         list_call = Call(Name("list"), [range_call], prefix=node.prefix)
         # Put things that were after the range() call after the list call.
         for n in results["rest"]:
             list_call.append_child(n)
         return list_call
예제 #6
0
    def transform(self, node, results):
        if self.should_skip(node):
            return

        trailers = []
        if "extra_trailers" in results:
            for t in results["extra_trailers"]:
                trailers.append(t.clone())

        if node.parent.type == syms.simple_stmt:
            self.warning(node, "You should use a for loop here")
            new = node.clone()
            new.prefix = ""
            new = Call(Name("list"), [new])
        elif "map_lambda" in results:
            new = ListComp(results["xp"].clone(), results["fp"].clone(),
                           results["it"].clone())
            new = Node(syms.power, [new] + trailers, prefix="")

        else:
            if "map_none" in results:
                new = results["arg"].clone()
                new.prefix = ""
            else:
                if "args" in results:
                    args = results["args"]
                    if (args.type == syms.trailer
                            and args.children[1].type == syms.arglist
                            and args.children[1].children[0].type == token.NAME
                            and args.children[1].children[0].value == "None"):
                        self.warning(
                            node,
                            "cannot convert map(None, ...) "
                            "with multiple arguments because map() "
                            "now truncates to the shortest sequence",
                        )
                        return

                    new = Node(syms.power, [Name("map"), args.clone()])
                    new.prefix = ""

                if in_special_context(node):
                    return None

            new = Node(syms.power, [Name("list"), ArgList([new])] + trailers)
            new.prefix = ""

        new.prefix = node.prefix
        return new
예제 #7
0
    def transform(self, node, results):
        assert results

        base = results.get("base")
        attr = results.get("attr")
        name = results.get("name")

        if base:
            if self.shadowed_next:
                attr.replace(Name("__next__", prefix=attr.prefix))
            else:
                base = [n.clone() for n in base]
                base[0].prefix = ""
                node.replace(Call(Name("next", prefix=node.prefix), base))
        elif name:
            n = Name("__next__", prefix=name.prefix)
            name.replace(n)
        elif attr:
            # We don't do this transformation if we're assigning to "x.next".
            # Unfortunately, it doesn't seem possible to do this in PATTERN,
            #  so it's being done here.
            if is_assign_target(node):
                head = results["head"]
                if "".join([str(n) for n in head]).strip() == "__builtin__":
                    self.warning(node, bind_warning)
                return
            attr.replace(Name("__next__"))
        elif "global" in results:
            self.warning(node, bind_warning)
            self.shadowed_next = True
예제 #8
0
 def transform(self, node, results):
     """
     Call __builtins__.long() with the value and the base of the value.
     This works because 0b10 is int("10", 2), 0o10 is int("10", 8), etc.
     """
     val = node.value
     base_ = base(val)
     if base_ == 8:
         assert val.strip().startswith("0o") or val.strip().startswith(
             "0O"), "Invalid format for octal literal"
         node.changed()
         node.value = "".join(("0", val[2:]))
     elif base_ == 2:
         assert val.startswith(
             "0") and val[1] in "bB", "Invalid format for binary literal"
         # __builtins__.long
         func_name = Node(syms.power,
                          Attr(Name("__builtins__"), Name("long")))
         # ("...", 2)
         func_args = [
             String("".join(('"', val.strip()[2:], '"'))),
             Comma(),
             Number(2, prefix=" ")
         ]
         new_node = Call(func_name, func_args, node.prefix)
         return new_node
예제 #9
0
    def transform(self, node, results):
        # If we're already wrapped in an eval() call, we're done.
        if context.match(node.parent.parent):
            return

        new = node.clone()
        new.prefix = ""
        return Call(Name("eval"), [new], prefix=node.prefix)
예제 #10
0
 def _Call(self, name, args=None, prefix=None):
     """Help the next test"""
     children = []
     if isinstance(args, list):
         for arg in args:
             children.append(arg)
             children.append(Comma())
         children.pop()
     return Call(Name(name), children, prefix)
예제 #11
0
    def transform(self, node, results):
        sys_attr = results["attribute"][0]
        index = Number(self.exc_info.index(sys_attr.value))

        call = Call(Name("exc_info"), prefix=sys_attr.prefix)
        attr = Attr(Name("sys"), call)
        attr[1].children[0].prefix = results["dot"].prefix
        attr.append(Subscript(index))
        return Node(syms.power, attr, prefix=node.prefix)
예제 #12
0
    def transform(self, node, results):
        assert results

        bare_print = results.get("bare")

        if bare_print:
            # Special-case print all by itself
            bare_print.replace(
                Call(Name("print"), [], prefix=bare_print.prefix))
            return
        assert node.children[0] == Name("print")
        args = node.children[1:]
        if len(args) == 1 and parend_expr.match(args[0]):
            # We don't want to keep sticking parens around an
            # already-parenthesised expression.
            return

        sep = end = file = None
        if args and args[-1] == Comma():
            args = args[:-1]
            end = " "
        if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, ">>"):
            assert len(args) >= 2
            file = args[1].clone()
            args = args[3:]  # Strip a possible comma after the file expression
        # Now synthesize a print(args, sep=..., end=..., file=...) node.
        l_args = [arg.clone() for arg in args]
        if l_args:
            l_args[0].prefix = ""
        if sep is not None or end is not None or file is not None:
            if sep is not None:
                self.add_kwarg(l_args, "sep", String(repr(sep)))
            if end is not None:
                self.add_kwarg(l_args, "end", String(repr(end)))
            if file is not None:
                self.add_kwarg(l_args, "file", file)
        n_stmt = Call(Name("print"), l_args)
        n_stmt.prefix = node.prefix
        return n_stmt
예제 #13
0
    def transform(self, node, results):
        assert results
        syms = self.syms
        a = results["a"]
        b = results.get("b")
        c = results.get("c")
        args = [a.clone()]
        args[0].prefix = ""
        if b is not None:
            args.extend([Comma(), b.clone()])
        if c is not None:
            args.extend([Comma(), c.clone()])

        return Call(Name("exec"), args, prefix=node.prefix)
예제 #14
0
 def transform(self, node, results):
     syms = self.syms
     assert results
     func = results["func"]
     args = results["args"]
     kwds = results.get("kwds")
     # I feel like we should be able to express this logic in the
     # PATTERN above but I don't know how to do it so...
     if args:
         if args.type == self.syms.star_expr:
             return  # Make no change.
         if args.type == self.syms.argument and args.children[
                 0].value == "**":
             return  # Make no change.
     if kwds and (kwds.type == self.syms.argument
                  and kwds.children[0].value == "**"):
         return  # Make no change.
     prefix = node.prefix
     func = func.clone()
     if func.type not in (token.NAME, syms.atom) and (
             func.type != syms.power
             or func.children[-2].type == token.DOUBLESTAR):
         # Need to parenthesize
         func = parenthesize(func)
     func.prefix = ""
     args = args.clone()
     args.prefix = ""
     if kwds is not None:
         kwds = kwds.clone()
         kwds.prefix = ""
     l_newargs = [pytree.Leaf(token.STAR, "*"), args]
     if kwds is not None:
         l_newargs.extend(
             [Comma(), pytree.Leaf(token.DOUBLESTAR, "**"), kwds])
         l_newargs[-2].prefix = " "  # that's the ** token
     # XXX Sometimes we could be cleverer, e.g. apply(f, (x, y) + t)
     # can be translated into f(x, y, *t) instead of f(*(x, y) + t)
     # new = pytree.Node(syms.power, (func, ArgList(l_newargs)))
     return Call(func, l_newargs, prefix=prefix)
예제 #15
0
    def transform(self, node, results):
        # First, find the sys import. We'll just hope it's global scope.
        if "sys_import" in results:
            if self.sys_import is None:
                self.sys_import = results["sys_import"]
            return

        func = results["func"].clone()
        func.prefix = ""
        register = pytree.Node(syms.power,
                               Attr(Name("atexit"), Name("register")))
        call = Call(register, [func], node.prefix)
        node.replace(call)

        if self.sys_import is None:
            # That's interesting.
            self.warning(
                node,
                "Can't find sys import; Please add an atexit import at the top of your file."
            )
            return

        # Now add an atexit import after the sys import.
        names = self.sys_import.children[1]
        if names.type == syms.dotted_as_names:
            names.append_child(Comma())
            names.append_child(Name("atexit", " "))
        else:
            containing_stmt = self.sys_import.parent
            position = containing_stmt.children.index(self.sys_import)
            stmt_container = containing_stmt.parent
            new_import = pytree.Node(
                syms.import_name,
                [Name("import"), Name("atexit", " ")])
            new = pytree.Node(syms.simple_stmt, [new_import])
            containing_stmt.insert_child(position + 1, Newline())
            containing_stmt.insert_child(position + 2, new)
예제 #16
0
    def transform_sort(self, node, results):
        sort_stmt = results["sort"]
        next_stmt = results["next"]
        list_call = results.get("list")
        simple_expr = results.get("expr")

        if list_call:
            list_call.replace(Name("sorted", prefix=list_call.prefix))
        elif simple_expr:
            new = simple_expr.clone()
            new.prefix = ""
            simple_expr.replace(Call(Name("sorted"), [new], prefix=simple_expr.prefix))
        else:
            raise RuntimeError("should not have reached here")
        sort_stmt.remove()

        btwn = sort_stmt.prefix
        # Keep any prefix lines between the sort_stmt and the list_call and
        # shove them right after the sorted() call.
        if "\n" in btwn:
            if next_stmt:
                # The new prefix should be everything from the sort_stmt's
                # prefix up to the last newline, then the old prefix after a new
                # line.
                prefix_lines = (btwn.rpartition("\n")[0], next_stmt[0].prefix)
                next_stmt[0].prefix = "\n".join(prefix_lines)
            else:
                assert list_call.parent
                assert list_call.next_sibling is None
                # Put a blank line after list_call and set its prefix.
                end_line = BlankLine()
                list_call.parent.append_child(end_line)
                assert list_call.next_sibling is end_line
                # The new prefix should be everything up to the first new line
                # of sort_stmt's prefix.
                end_line.prefix = btwn.rpartition("\n")[0]
예제 #17
0
 def _isCallable(self, node, results):
     obj = results["obj"]
     return Call(Name("callable"), [obj.clone()], prefix=node.prefix)
예제 #18
0
 def _handle_type2abc(self, node, results, module, abc):
     touch_import(None, module, node)
     obj = results["obj"]
     args = [obj.clone(), String(", " + ".".join([module, abc]))]
     return Call(Name("isinstance"), args, prefix=node.prefix)
예제 #19
0
    def transform(self, node, results):
        expr = results["expr"].clone()

        if expr.type == self.syms.testlist1:
            expr = parenthesize(expr)
        return Call(Name("repr"), [expr], prefix=node.prefix)