Ejemplo n.º 1
0
 def test_basic_patterns(self):
     # Build a tree
     l1 = pytree.Leaf(100, "foo")
     l2 = pytree.Leaf(100, "bar")
     l3 = pytree.Leaf(100, "foo")
     n1 = pytree.Node(1000, [l1, l2])
     n2 = pytree.Node(1000, [l3])
     root = pytree.Node(1000, [n1, n2])
     # Build a pattern matching a leaf
     pl = pytree.LeafPattern(100, "foo", name="pl")
     r = {}
     self.assertFalse(pl.match(root, results=r))
     self.assertEqual(r, {})
     self.assertFalse(pl.match(n1, results=r))
     self.assertEqual(r, {})
     self.assertFalse(pl.match(n2, results=r))
     self.assertEqual(r, {})
     self.assertTrue(pl.match(l1, results=r))
     self.assertEqual(r, {"pl": l1})
     r = {}
     self.assertFalse(pl.match(l2, results=r))
     self.assertEqual(r, {})
     # Build a pattern matching a node
     pn = pytree.NodePattern(1000, [pl], name="pn")
     self.assertFalse(pn.match(root, results=r))
     self.assertEqual(r, {})
     self.assertFalse(pn.match(n1, results=r))
     self.assertEqual(r, {})
     self.assertTrue(pn.match(n2, results=r))
     self.assertEqual(r, {"pn": n2, "pl": l3})
     r = {}
     self.assertFalse(pn.match(l1, results=r))
     self.assertEqual(r, {})
     self.assertFalse(pn.match(l2, results=r))
     self.assertEqual(r, {})
Ejemplo n.º 2
0
    def test_changed(self):
        l1 = pytree.Leaf(100, "f")
        self.assertFalse(l1.was_changed)
        l1.changed()
        self.assertTrue(l1.was_changed)

        l1 = pytree.Leaf(100, "f")
        n1 = pytree.Node(1000, [l1])
        self.assertFalse(n1.was_changed)
        n1.changed()
        self.assertTrue(n1.was_changed)

        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "+")
        l3 = pytree.Leaf(100, "bar")
        n1 = pytree.Node(1000, [l1, l2, l3])
        n2 = pytree.Node(1000, [n1])
        self.assertFalse(l1.was_changed)
        self.assertFalse(n1.was_changed)
        self.assertFalse(n2.was_changed)

        n1.changed()
        self.assertTrue(n1.was_changed)
        self.assertTrue(n2.was_changed)
        self.assertFalse(l1.was_changed)
Ejemplo n.º 3
0
 def test_wildcard(self):
     # Build a tree for testing
     l1 = pytree.Leaf(100, "foo")
     l2 = pytree.Leaf(100, "bar")
     l3 = pytree.Leaf(100, "foo")
     n1 = pytree.Node(1000, [l1, l2])
     n2 = pytree.Node(1000, [l3])
     root = pytree.Node(1000, [n1, n2])
     # Build a pattern
     pl = pytree.LeafPattern(100, "foo", name="pl")
     pn = pytree.NodePattern(1000, [pl], name="pn")
     pw = pytree.WildcardPattern([[pn], [pl, pl]], name="pw")
     r = {}
     self.assertFalse(pw.match_seq([root], r))
     self.assertEqual(r, {})
     self.assertFalse(pw.match_seq([n1], r))
     self.assertEqual(r, {})
     self.assertTrue(pw.match_seq([n2], r))
     # These are easier to debug
     self.assertEqual(sorted(r.keys()), ["pl", "pn", "pw"])
     self.assertEqual(r["pl"], l1)
     self.assertEqual(r["pn"], n2)
     self.assertEqual(r["pw"], [n2])
     # But this is equivalent
     self.assertEqual(r, {"pl": l1, "pn": n2, "pw": [n2]})
     r = {}
     self.assertTrue(pw.match_seq([l1, l3], r))
     self.assertEqual(r, {"pl": l3, "pw": [l1, l3]})
     self.assertIs(r["pl"], l3)
     r = {}
Ejemplo n.º 4
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
Ejemplo n.º 5
0
 def test_pre_order(self):
     l1 = pytree.Leaf(100, "foo")
     l2 = pytree.Leaf(100, "bar")
     l3 = pytree.Leaf(100, "fooey")
     c1 = pytree.Node(1000, [l1, l2])
     n1 = pytree.Node(1000, [c1, l3])
     self.assertEqual(list(n1.pre_order()), [n1, c1, l1, l2, l3])
Ejemplo n.º 6
0
    def transform(self, node, results):
        single = results.get("single")
        if single:
            # Make a fake listmaker
            fake = pytree.Node(syms.listmaker, [single.clone()])
            single.replace(fake)
            items = fake
        else:
            items = results["items"]

        # Build the contents of the literal
        literal = [pytree.Leaf(token.LBRACE, "{")]
        literal.extend(n.clone() for n in items.children)
        literal.append(pytree.Leaf(token.RBRACE, "}"))
        # Set the prefix of the right brace to that of the ')' or ']'
        literal[-1].prefix = items.next_sibling.prefix
        maker = pytree.Node(syms.dictsetmaker, literal)
        maker.prefix = node.prefix

        # If the original was a one tuple, we need to remove the extra comma.
        if len(maker.children) == 4:
            n = maker.children[2]
            n.remove()
            maker.children[-1].prefix = n.prefix

        # Finally, replace the set call with our shiny new literal.
        return maker
Ejemplo n.º 7
0
    def test_node_prev_sibling(self):
        n1 = pytree.Node(1000, [])
        n2 = pytree.Node(1000, [])
        p1 = pytree.Node(1000, [n1, n2])

        self.assertIs(n2.prev_sibling, n1)
        self.assertEqual(n1.prev_sibling, None)
        self.assertEqual(p1.prev_sibling, None)
Ejemplo n.º 8
0
    def test_leaves(self):
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar")
        l3 = pytree.Leaf(100, "fooey")
        n2 = pytree.Node(1000, [l1, l2])
        n3 = pytree.Node(1000, [l3])
        n1 = pytree.Node(1000, [n2, n3])

        self.assertEqual(list(n1.leaves()), [l1, l2, l3])
Ejemplo n.º 9
0
 def test_node_recursive_equality(self):
     l1 = pytree.Leaf(100, "foo")
     l2 = pytree.Leaf(100, "foo")
     n1 = pytree.Node(1000, [l1])
     n2 = pytree.Node(1000, [l2])
     self.assertEqual(n1, n2)
     l3 = pytree.Leaf(100, "bar")
     n3 = pytree.Node(1000, [l3])
     self.assertNotEqual(n1, n3)
Ejemplo n.º 10
0
    def test_depth(self):
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar")
        n2 = pytree.Node(1000, [l1, l2])
        n3 = pytree.Node(1000, [])
        n1 = pytree.Node(1000, [n2, n3])

        self.assertEqual(l1.depth(), 2)
        self.assertEqual(n3.depth(), 1)
        self.assertEqual(n1.depth(), 0)
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
 def transform(self, node, results):
     assert results
     syms = self.syms
     if node.parent.type == syms.not_test and self.pattern.match(
             node.parent):
         # Don't transform a node matching the first alternative of the
         # pattern when its parent matches the second alternative
         return None
     negation = results.get("negation")
     anchor = results["anchor"]
     prefix = node.prefix
     before = [n.clone() for n in results["before"]]
     arg = results["arg"].clone()
     after = results.get("after")
     if after:
         after = [n.clone() for n in after]
     if arg.type in (
             syms.comparison,
             syms.not_test,
             syms.and_test,
             syms.or_test,
             syms.test,
             syms.lambdef,
             syms.argument,
     ):
         arg = parenthesize(arg)
     if len(before) == 1:
         before = before[0]
     else:
         before = pytree.Node(syms.power, before)
     before.prefix = " "
     n_op = Name("in", prefix=" ")
     if negation:
         n_not = Name("not", prefix=" ")
         n_op = pytree.Node(syms.comp_op, (n_not, n_op))
     new = pytree.Node(syms.comparison, (arg, n_op, before))
     if after:
         new = parenthesize(new)
         new = pytree.Node(syms.power, (new, ) + tuple(after))
     if node.parent.type in (
             syms.comparison,
             syms.expr,
             syms.xor_expr,
             syms.and_expr,
             syms.shift_expr,
             syms.arith_expr,
             syms.term,
             syms.factor,
             syms.power,
     ):
         new = parenthesize(new)
     new.prefix = prefix
     return new
Ejemplo n.º 13
0
    def test_get_suffix(self):
        l1 = pytree.Leaf(100, "foo", prefix="a")
        l2 = pytree.Leaf(100, "bar", prefix="b")
        n1 = pytree.Node(1000, [l1, l2])

        self.assertEqual(l1.get_suffix(), l2.prefix)
        self.assertEqual(l2.get_suffix(), "")
        self.assertEqual(n1.get_suffix(), "")

        l3 = pytree.Leaf(100, "bar", prefix="c")
        n2 = pytree.Node(1000, [n1, l3])

        self.assertEqual(n1.get_suffix(), l3.prefix)
        self.assertEqual(l3.get_suffix(), "")
        self.assertEqual(n2.get_suffix(), "")
Ejemplo n.º 14
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))
Ejemplo n.º 15
0
 def test_generate_matches(self):
     la = pytree.Leaf(1, "a")
     lb = pytree.Leaf(1, "b")
     lc = pytree.Leaf(1, "c")
     ld = pytree.Leaf(1, "d")
     le = pytree.Leaf(1, "e")
     lf = pytree.Leaf(1, "f")
     leaves = [la, lb, lc, ld, le, lf]
     root = pytree.Node(1000, leaves)
     pa = pytree.LeafPattern(1, "a", "pa")
     pb = pytree.LeafPattern(1, "b", "pb")
     pc = pytree.LeafPattern(1, "c", "pc")
     pd = pytree.LeafPattern(1, "d", "pd")
     pe = pytree.LeafPattern(1, "e", "pe")
     pf = pytree.LeafPattern(1, "f", "pf")
     pw = pytree.WildcardPattern(
         [[pa, pb, pc], [pd, pe], [pa, pb], [pc, pd], [pe, pf]],
         min=1,
         max=4,
         name="pw")
     self.assertEqual([x[0] for x in pw.generate_matches(leaves)],
                      [3, 5, 2, 4, 6])
     pr = pytree.NodePattern(type=1000, content=[pw], name="pr")
     matches = list(pytree.generate_matches([pr], [root]))
     self.assertEqual(len(matches), 1)
     c, r = matches[0]
     self.assertEqual(c, 1)
     self.assertEqual(str(r["pr"]), "abcdef")
     self.assertEqual(r["pw"], [la, lb, lc, ld, le, lf])
     for c in "abcdef":
         self.assertEqual(r["p" + c], pytree.Leaf(1, c))
Ejemplo n.º 16
0
    def test_remove_parentless(self):
        n1 = pytree.Node(1000, [])
        n1.remove()
        self.assertEqual(n1.parent, None)

        l1 = pytree.Leaf(100, "foo")
        l1.remove()
        self.assertEqual(l1.parent, None)
Ejemplo n.º 17
0
 def test_node_prefix(self):
     l1 = pytree.Leaf(100, "foo")
     self.assertEqual(l1.prefix, "")
     n1 = pytree.Node(1000, [l1])
     self.assertEqual(n1.prefix, "")
     n1.prefix = " "
     self.assertEqual(n1.prefix, " ")
     self.assertEqual(l1.prefix, " ")
Ejemplo n.º 18
0
    def test_leaf_prev_sibling(self):
        l1 = pytree.Leaf(100, "a")
        l2 = pytree.Leaf(100, "b")
        p1 = pytree.Node(1000, [l1, l2])

        self.assertIs(l2.prev_sibling, l1)
        self.assertEqual(l1.prev_sibling, None)
        self.assertEqual(p1.prev_sibling, None)
Ejemplo n.º 19
0
    def test_replace_with_list(self):
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "+")
        l3 = pytree.Leaf(100, "bar")
        n1 = pytree.Node(1000, [l1, l2, l3])

        l2.replace([pytree.Leaf(100, "*"), pytree.Leaf(100, "*")])
        self.assertEqual(str(n1), "foo**bar")
        self.assertIsInstance(n1.children, list)
Ejemplo n.º 20
0
 def test_node_constructor_prefix(self):
     for prefix in ("xyz_", ""):
         l1 = pytree.Leaf(100, "self")
         l2 = pytree.Leaf(100, "foo", prefix="_")
         n1 = pytree.Node(1000, [l1, l2], prefix=prefix)
         self.assertTrue(str(n1), prefix + "self_foo")
         self.assertEqual(n1.prefix, prefix)
         self.assertEqual(l1.prefix, prefix)
         self.assertEqual(l2.prefix, "_")
Ejemplo n.º 21
0
 def add_kwarg(self, l_nodes, s_kwd, n_expr):
     # XXX All this prefix-setting may lose comments (though rarely)
     n_expr.prefix = ""
     n_argument = pytree.Node(
         self.syms.argument,
         (Name(s_kwd), pytree.Leaf(token.EQUAL, "="), n_expr))
     if l_nodes:
         l_nodes.append(Comma())
         n_argument.prefix = " "
     l_nodes.append(n_argument)
Ejemplo n.º 22
0
 def handle_tuple(tuple_arg, add_prefix=False):
     n = Name(self.new_name())
     arg = tuple_arg.clone()
     arg.prefix = ""
     stmt = Assign(arg, n.clone())
     if add_prefix:
         n.prefix = " "
     tuple_arg.replace(n)
     new_lines.append(pytree.Node(syms.simple_stmt,
                                  [stmt, end.clone()]))
Ejemplo n.º 23
0
 def test_has_key_example(self):
     pattern = pytree.NodePattern(
         331, (pytree.LeafPattern(7), pytree.WildcardPattern(name="args"),
               pytree.LeafPattern(8)))
     l1 = pytree.Leaf(7, "(")
     l2 = pytree.Leaf(3, "x")
     l3 = pytree.Leaf(8, ")")
     node = pytree.Node(331, [l1, l2, l3])
     r = {}
     self.assertTrue(pattern.match(node, r))
     self.assertEqual(r["args"], [l2])
Ejemplo n.º 24
0
    def test_node_set_child(self):
        l1 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1])

        l2 = pytree.Leaf(100, "bar")
        n1.set_child(0, l2)
        self.assertEqual(l1.parent, None)
        self.assertEqual(l2.parent, n1)
        self.assertEqual(n1.children, [l2])

        n2 = pytree.Node(1000, [l1])
        n2.set_child(0, n1)
        self.assertEqual(l1.parent, None)
        self.assertEqual(n1.parent, n2)
        self.assertEqual(n2.parent, None)
        self.assertEqual(n2.children, [n1])

        self.assertRaises(IndexError, n1.set_child, 4, l2)
        # I don't care what it raises, so long as it's an exception
        self.assertRaises(Exception, n1.set_child, 0, list)
Ejemplo n.º 25
0
    def test_remove(self):
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1, l2])
        n2 = pytree.Node(1000, [n1])

        self.assertEqual(n1.remove(), 0)
        self.assertEqual(n2.children, [])
        self.assertEqual(l1.parent, n1)
        self.assertEqual(n1.parent, None)
        self.assertEqual(n2.parent, None)
        self.assertFalse(n1.was_changed)
        self.assertTrue(n2.was_changed)

        self.assertEqual(l2.remove(), 1)
        self.assertEqual(l1.remove(), 0)
        self.assertEqual(n1.children, [])
        self.assertEqual(l1.parent, None)
        self.assertEqual(n1.parent, None)
        self.assertEqual(n2.parent, None)
        self.assertTrue(n1.was_changed)
        self.assertTrue(n2.was_changed)
Ejemplo n.º 26
0
 def test_replace(self):
     l1 = pytree.Leaf(100, "foo")
     l2 = pytree.Leaf(100, "+")
     l3 = pytree.Leaf(100, "bar")
     n1 = pytree.Node(1000, [l1, l2, l3])
     self.assertEqual(n1.children, [l1, l2, l3])
     self.assertIsInstance(n1.children, list)
     self.assertFalse(n1.was_changed)
     l2new = pytree.Leaf(100, "-")
     l2.replace(l2new)
     self.assertEqual(n1.children, [l1, l2new, l3])
     self.assertIsInstance(n1.children, list)
     self.assertTrue(n1.was_changed)
Ejemplo n.º 27
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)
Ejemplo n.º 28
0
    def test_node_append_child(self):
        n1 = pytree.Node(1000, [])

        l1 = pytree.Leaf(100, "foo")
        n1.append_child(l1)
        self.assertEqual(l1.parent, n1)
        self.assertEqual(n1.children, [l1])

        l2 = pytree.Leaf(100, "bar")
        n1.append_child(l2)
        self.assertEqual(l2.parent, n1)
        self.assertEqual(n1.children, [l1, l2])

        # I don't care what it raises, so long as it's an exception
        self.assertRaises(Exception, n1.append_child, list)
Ejemplo n.º 29
0
    def test_node_insert_child(self):
        l1 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1])

        l2 = pytree.Leaf(100, "bar")
        n1.insert_child(0, l2)
        self.assertEqual(l2.parent, n1)
        self.assertEqual(n1.children, [l2, l1])

        l3 = pytree.Leaf(100, "abc")
        n1.insert_child(2, l3)
        self.assertEqual(n1.children, [l2, l1, l3])

        # I don't care what it raises, so long as it's an exception
        self.assertRaises(Exception, n1.insert_child, 0, list)
Ejemplo n.º 30
0
    def transform(self, node, results):
        syms = self.syms

        tail = [n.clone() for n in results["tail"]]

        try_cleanup = [ch.clone() for ch in results["cleanup"]]
        for except_clause, e_suite in find_excepts(try_cleanup):
            if len(except_clause.children) == 4:
                (E, comma, N) = except_clause.children[1:4]
                comma.replace(Name("as", prefix=" "))

                if N.type != token.NAME:
                    # Generate a new N for the except clause
                    new_N = Name(self.new_name(), prefix=" ")
                    target = N.clone()
                    target.prefix = ""
                    N.replace(new_N)
                    new_N = new_N.clone()

                    # Insert "old_N = new_N" as the first statement in
                    #  the except body. This loop skips leading whitespace
                    #  and indents
                    # TODO(cwinter) suite-cleanup
                    suite_stmts = e_suite.children
                    for i, stmt in enumerate(suite_stmts):
                        if isinstance(stmt, pytree.Node):
                            break

                    # The assignment is different if old_N is a tuple or list
                    # In that case, the assignment is old_N = new_N.args
                    if is_tuple(N) or is_list(N):
                        assign = Assign(target, Attr(new_N, Name("args")))
                    else:
                        assign = Assign(target, new_N)

                    # TODO(cwinter) stopgap until children becomes a smart list
                    for child in reversed(suite_stmts[:i]):
                        e_suite.insert_child(0, child)
                    e_suite.insert_child(i, assign)
                elif N.prefix == "":
                    # No space after a comma is legal; no space after "as",
                    # not so much.
                    N.prefix = " "

        # TODO(cwinter) fix this when children becomes a smart list
        children = [c.clone() for c in node.children[:3]] + try_cleanup + tail
        return pytree.Node(node.type, children)