Example #1
0
    def _transform_children(self, node):
        if not isinstance(node, Node):
            raise ValueError('Expected a Node, got %r' % node)

        # In these trees, strings and Nodes are leaves
        leaves = (str, Node)
        tree_map = partial(tree.tree_map, leaves=leaves)

        children = tree_map(partial(self.transform), node.getChildrenTree())
        return node.__class__(*children)
Example #2
0
    def _transform_children(self, node):
        if not isinstance(node, Node):
            raise ValueError('Expected a Node, got %r' % node)

        # In these trees, strings and Nodes are leaves
        leaves = (str, Node)
        tree_map = partial(tree.tree_map, leaves=leaves)

        children = tree_map(partial(self.transform), node.getChildrenTree())
        return node.__class__(*children)
Example #3
0
    def test_transformer_base_class(self):
        'Transformer base class'

        test = partial(self._base, Transformer())

        # Transformer.transform doesn't change anything
        test('a = 0', 'a = 0')
        test('a = b', 'a = b')
        test('if t == u-1: a = b,f(c)', 'if t == u-1: a = b,f(c)')
        # ...

        # Transformer.transform makes deep copies by default
        code = 'if t == u: a,b = [1]+[2]\nreturn sum(b,a)'
        a = parse(code)
        b = Transformer().transform(a)
        b.node.nodes[1] = parse('yield x').node.nodes[0]
        b.node.nodes[0].tests[0][0].ops[0] = parse('t > 0').node.nodes[0].expr
        b.node.nodes[0].tests[0][1].nodes[0].expr.left.nodes[0] = 5
        self.assertNotSimilar(b, parse(code))
        self.assertSimilar(a, parse(code))
Example #4
0
    def test_transformer_base_class(self):
        'Transformer base class'

        test = partial(self._base, Transformer())

        # Transformer.transform doesn't change anything
        test('a = 0', 'a = 0')
        test('a = b', 'a = b')
        test('if t == u-1: a = b,f(c)', 'if t == u-1: a = b,f(c)')
        # ...

        # Transformer.transform makes deep copies by default
        code = 'if t == u: a,b = [1]+[2]\nreturn sum(b,a)'
        a = parse(code)
        b = Transformer().transform(a)
        b.node.nodes[1] = parse('yield x').node.nodes[0]
        b.node.nodes[0].tests[0][0].ops[0] = parse('t > 0').node.nodes[0].expr
        b.node.nodes[0].tests[0][1].nodes[0].expr.left.nodes[0] = 5
        self.assertNotSimilar(b, parse(code))
        self.assertSimilar(a, parse(code))
Example #5
0
    def transformAssign(self, node):

        # Only transform constant assignments
        if not is_const(node.expr):
            return self._transform_children(node)

        # '__foo' names come from each lhs name at the head of the assignment:
        #   'l = a,b = 0,1' -> 'l = a,b = __a,__b', { '__a':0, '__b':1 }
        #
        # Unpack the rhs enough to map each '__foo' name to a value.
        #   'a,l = 0,[1,2]' -> 'a,l = __a,__l', { '__a':0, '__l':[1,2] }
        #   'a,l = 2'       -> SyntaxError

        def lvalue_name(node):
            'Construct a "magic" name to represent an l-value.'
            prefix = sep = '__'
            dot = '_'
            if isinstance(node, AssName):
                return prefix + node.name
            elif isinstance(node, AssAttr):
                name = node.attrname
                expr = node.expr
                while isinstance(expr, Getattr):
                    name = sep.join([expr.attrname, name])
                    expr = expr.expr
                if isinstance(expr, Name):
                    expr_name = expr.name
                else:
                    expr_name = dot
                return prefix + sep.join([expr_name, name])

        # In these trees, strings and tuples are leaves
        leaves = (str, tuple, AssAttr, AssName)
        tree_zip = partial(tree.tree_zip, leaves=leaves)
        flatten = partial(tree.flatten, leaves=leaves)
        tree_embeds = partial(tree.tree_embeds, leaves=leaves)

        # Grab the (right-most) lhs and the rhs
        lhs, rhs = node.nodes[-1], node.expr

        # Associate constants with l-value names
        if not tree_embeds(lhs, rhs):
            raise SyntaxError('Not enough r-values to unpack: %s' % node)
        zipped = flatten(tree_zip(lhs, rhs))
        const_ast_for = map_keys(lambda v: lvalue_name(v), dict(zipped))

        # Gather name<->const mappings for names we haven't seen before
        name_for = {}
        for name in const_ast_for.keys():
            if name not in self.const_for.keys():
                self.const_for[name] = eval_ast(Expression(const_ast_for[name]))
                assert const_ast_for[name] not in name_for
                name_for[const_ast_for[name]] = name

        class C(Transformer):
            def transform(self, node):
                if isinstance(node, Node) and node in name_for.keys():
                    return Name(name_for[node])
                else:
                    return super(C, self).transform(node)
        return Assign(node.nodes, C().transform(rhs))
Example #6
0
    def transformAssign(self, node):

        # Only transform constant assignments
        if not is_const(node.expr):
            return self._transform_children(node)

        # '__foo' names come from each lhs name at the head of the assignment:
        #   'l = a,b = 0,1' -> 'l = a,b = __a,__b', { '__a':0, '__b':1 }
        #
        # Unpack the rhs enough to map each '__foo' name to a value.
        #   'a,l = 0,[1,2]' -> 'a,l = __a,__l', { '__a':0, '__l':[1,2] }
        #   'a,l = 2'       -> SyntaxError

        def lvalue_name(node):
            'Construct a "magic" name to represent an l-value.'
            prefix = sep = '__'
            dot = '_'
            if isinstance(node, AssName):
                return prefix + node.name
            elif isinstance(node, AssAttr):
                name = node.attrname
                expr = node.expr
                while isinstance(expr, Getattr):
                    name = sep.join([expr.attrname, name])
                    expr = expr.expr
                if isinstance(expr, Name):
                    expr_name = expr.name
                else:
                    expr_name = dot
                return prefix + sep.join([expr_name, name])

        # In these trees, strings and tuples are leaves
        leaves = (str, tuple, AssAttr, AssName)
        tree_zip = partial(tree.tree_zip, leaves=leaves)
        flatten = partial(tree.flatten, leaves=leaves)
        tree_embeds = partial(tree.tree_embeds, leaves=leaves)

        # Grab the (right-most) lhs and the rhs
        lhs, rhs = node.nodes[-1], node.expr

        # Associate constants with l-value names
        if not tree_embeds(lhs, rhs):
            raise SyntaxError('Not enough r-values to unpack: %s' % node)
        zipped = flatten(tree_zip(lhs, rhs))
        const_ast_for = map_keys(lambda v: lvalue_name(v), dict(zipped))

        # Gather name<->const mappings for names we haven't seen before
        name_for = {}
        for name in const_ast_for.keys():
            if name not in self.const_for.keys():
                self.const_for[name] = eval_ast(Expression(
                    const_ast_for[name]))
                assert const_ast_for[name] not in name_for
                name_for[const_ast_for[name]] = name

        class C(Transformer):
            def transform(self, node):
                if isinstance(node, Node) and node in name_for.keys():
                    return Name(name_for[node])
                else:
                    return super(C, self).transform(node)

        return Assign(node.nodes, C().transform(rhs))