Esempio n. 1
0
    def test_duplicate_node_collect(self):
        self.ast_description = """
        file: TestTemplate

        #def test_function
          foo
          bar
          #if True
            #set $foo = 1
          #end if
          baz
          boo
          #if True
            #set $foo = 1
          #end if
        #end def

        NOTE: This test will break if collect_writes is written
        using ast.ASTNode.insert_before.
        """

        ast_root, function_node = self._build_function_template()
        function_node.append(ast.BufferWrite(ast.LiteralNode('foo')))
        function_node.append(ast.BufferWrite(ast.LiteralNode('bar')))
        if_node = ast.IfNode()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))
        function_node.append(if_node)
        function_node.append(ast.BufferWrite(ast.LiteralNode('baz')))
        function_node.append(ast.BufferWrite(ast.LiteralNode('boo')))
        if_node = ast.IfNode()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))
        optimization_analyzer = self._get_analyzer(ast_root)

        ast_root, function_node = self._build_function_template()
        tuple_node = ast.TupleLiteralNode()
        tuple_node.append(ast.LiteralNode('foo'))
        tuple_node.append(ast.LiteralNode('bar'))
        function_node.append(ast.BufferExtend(tuple_node))
        if_node = ast.IfNode()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))
        function_node.append(if_node)
        tuple_node = ast.TupleLiteralNode()
        tuple_node.append(ast.LiteralNode('baz'))
        tuple_node.append(ast.LiteralNode('boo'))
        function_node.append(ast.BufferExtend(tuple_node))
        if_node = ast.IfNode()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))

        expected_hash = hash(ast_root)

        got_hash = hash(optimization_analyzer.optimize_ast())
        self.assertEqual(expected_hash, got_hash)
Esempio n. 2
0
    def test_index_scope_ok(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #set $foo = {}
          #if True
            #set $foo[1] = 1
          #end if
        #end def
        """

        ast_root, function_node = self._build_function_template()
        assign_node1 = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.DictLiteralNode())
        function_node.append(assign_node1)
        if_node = ast.IfNode(ast.LiteralNode(True))
        assign_node2 = ast.AssignNode(
            ast.SliceNode(
                ast.IdentifierNode('foo'), ast.LiteralNode(1)),
            ast.LiteralNode(1))
        if_node.append(assign_node2)
        function_node.append(if_node)

        optimization_analyzer = self._get_analyzer(ast_root)

        try:
            optimization_analyzer.visit_ast(ast_root)
        except analyzer.SemanticAnalyzerError:
            self.fail('visit_ast raised SemanticAnalyzerError unexpectedly.')
Esempio n. 3
0
    def test_nested_else(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #if True
            #set $foo = 1
          #else
            #if
              #set $foo = 2
            #else
              #set $foo = 3
            #end if
          #end if
          $foo
        #end def
        """

        ast_root, function_node, if_node = self._build_if_template()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))
        if_node_2 = ast.IfNode(ast.LiteralNode(True))
        if_node_2.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(2)))
        if_node_2.else_.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(3)))
        if_node.else_.append(if_node_2)
        function_node.append(ast.PlaceholderNode('foo'))

        optimization_analyzer = self._get_analyzer(ast_root)

        try:
            optimization_analyzer.visit_ast(ast_root)
        except analyzer.SemanticAnalyzerError:
            self.fail('visit_ast raised SemanticAnalyzerError unexpectedly.')
Esempio n. 4
0
    def test_partial_nested_else_if(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #if True
            #set $foo = 1
          #else
            #if True
              #set $foo = 2
            #end if
          #end if
          $foo
        #end def
        """

        ast_root, function_node, if_node = self._build_if_template()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))
        if_node_2 = ast.IfNode(ast.LiteralNode(True))
        if_node_2.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(2)))
        if_node.else_.append(if_node_2)
        function_node.append(ast.PlaceholderNode('foo'))

        optimization_analyzer = self._get_analyzer(ast_root)
        self.assertRaises(analyzer.SemanticAnalyzerError,
                          optimization_analyzer.visit_ast, ast_root)
Esempio n. 5
0
    def test_collect_writes_join_if(self):
        self.ast_description = """
        file: TestTemplate

        #def test_function
          foo
          bar
          #if True
            #set $foo = 1
          #end if
          baz
          boo
        #end def
        """

        ast_root, function_node = self._build_function_template()
        function_node.append(ast.BufferWrite(ast.LiteralNode('foo')))
        function_node.append(ast.BufferWrite(ast.LiteralNode('bar')))
        if_node = ast.IfNode()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))
        function_node.append(if_node)
        function_node.append(ast.BufferWrite(ast.LiteralNode('baz')))
        function_node.append(ast.BufferWrite(ast.LiteralNode('boo')))
        optimization_analyzer = self._get_analyzer(ast_root)

        ast_root, function_node = self._build_function_template()
        tuple_node = ast.TupleLiteralNode()
        tuple_node.append(ast.LiteralNode('foo'))
        tuple_node.append(ast.LiteralNode('bar'))
        function_node.append(ast.BufferExtend(tuple_node))
        if_node = ast.IfNode()
        if_node.append(ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(1)))
        function_node.append(if_node)
        tuple_node = ast.TupleLiteralNode()
        tuple_node.append(ast.LiteralNode('baz'))
        tuple_node.append(ast.LiteralNode('boo'))
        function_node.append(ast.BufferExtend(tuple_node))

        expected_hash = hash(ast_root)

        got_hash = hash(optimization_analyzer.optimize_ast())
        self.assertEqual(expected_hash, got_hash)
Esempio n. 6
0
 def handle_condition(self, dom_node, attr_name):
     expr_ast = util.parse(dom_node.getAttribute(attr_name),
                           'rhs_expression')
     node_list = []
     if_node = ast.IfNode(expr_ast)
     node_list.append(if_node)
     if_node.append(self.make_tag_node(dom_node))
     for n in dom_node.childNodes:
         if_node.extend(self.build_ast(n))
     if_node.extend(self.make_tag_node(dom_node, close=True))
     return node_list
Esempio n. 7
0
    def _build_if_template(self, condition=None):
        """ Build a simple template with a function and an if statement.

        file: TestTemplate
        #def test_function
          #if True
          #end if
        #end def
        """
        ast_root, function_node = self._build_function_template()
        condition_node = condition or ast.LiteralNode(True)
        if_node = ast.IfNode(condition_node)
        function_node.append(if_node)
        return (ast_root, function_node, if_node)
Esempio n. 8
0
    def analyzeIfNode(self, pnode):
        # If all of the children are nodes that get ignored or there are
        # no nodes, throw an error.
        if all([isinstance(pn, _BLANK_NODES) for pn in pnode.child_nodes]):
            self.compiler.error(
                SemanticAnalyzerError("can't define an empty #if block"),
                pos=pnode.pos)

        if_node = ast.IfNode(pos=pnode.pos)
        if_node.else_.pos = pnode.else_.pos
        if_node.test_expression = self.build_ast(pnode.test_expression)[0]
        for pn in self.optimize_parsed_nodes(pnode.child_nodes):
            if_node.extend(self.build_ast(pn))
            if_node.child_nodes = self.optimize_buffer_writes(
                if_node.child_nodes)
        for pn in self.optimize_parsed_nodes(pnode.else_.child_nodes):
            if_node.else_.extend(self.build_ast(pn))
            if_node.else_.child_nodes = self.optimize_buffer_writes(
                if_node.else_.child_nodes)
        return [if_node]
Esempio n. 9
0
    def test_empty_elif_fails(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #if True
            #set $foo = True
          #elif False
          #end if
        #end def
        """

        ast_root, def_node, if_node = self._build_if_template()
        assign_node = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(True))
        if_node.append(assign_node)
        elif_node = ast.IfNode(ast.LiteralNode(False))
        if_node.else_.append(elif_node)
        semantic_analyzer = self._get_analyzer(ast_root)

        self.assertRaises(analyzer.SemanticAnalyzerError,
                          semantic_analyzer.get_ast)
Esempio n. 10
0
    def make_tag_node(self, dom_node, close=False, attr_ast=None):
        debug("make_tag_node", dom_node)
        node_list = []
        node_name = dom_node.nodeName
        if close:
            if self.has_child_stuff(dom_node):
                node_list.append(ast.TextNode(u'</%(node_name)s>' % vars()))
        else:
            attr_text = ' '.join([
                '%s="%s"' % (key, value)
                for key, value in dom_node.attributes.items()
                if not key.startswith('py:')
            ])
            # fixme: this is starting to look fugly - hard to maintain and error
            # prone
            if self.has_child_stuff(dom_node):
                if attr_text:
                    if attr_ast:
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s %(attr_text)s' %
                                         vars()))
                        node_list.extend(attr_ast)
                        node_list.append(ast.TextNode(u'>'))
                    else:
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s %(attr_text)s>' %
                                         vars()))
                else:
                    if attr_ast:
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s' % vars()))
                        node_list.extend(attr_ast)
                        node_list.append(ast.TextNode(u'>'))
                    else:
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s>' % vars()))
            else:
                if attr_text:
                    if attr_ast:
                        # print "XXX make_tag_node", dom_node.nodeName, attr_ast
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s %(attr_text)s' %
                                         vars()))
                        node_list.extend(attr_ast)
                        node_list.append(ast.TextNode(u' />'))
                    else:
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s %(attr_text)s />' %
                                         vars()))
                else:
                    if attr_ast:
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s' % vars()))
                        node_list.extend(attr_ast)
                        node_list.append(ast.TextNode(u' />'))
                    else:
                        node_list.append(
                            ast.TextNode(u'<%(node_name)s />' % vars()))

        omit_tag = getattr(dom_node, 'omit_tag', False)
        omit_tag_ast = getattr(dom_node, 'omit_tag_ast', None)
        if omit_tag:
            if omit_tag_ast:
                if_node = ast.IfNode(omit_tag_ast)
                if_node.extend(node_list)
                return [if_node]
            else:
                return []

        return node_list
Esempio n. 11
0
    def codegenASTFunctionNode(self, node):
        name = node.name
        node.uses_globals = False
        node.uses_filter_function = False
        node.uses_private_filter_function = False
        node.uses_buffer_write = False
        node.uses_buffer_extend = False
        self.function_stack.append(node)
        if node.parameter_list:
            parameter_list = self.generate_python(
                self.build_code(node.parameter_list)[0])
        else:
            parameter_list = ''

        decorator_node = CodeNode('@template_method')
        # NOTE: for Cheetah compatibility, we have to handle the case where
        # Cheetah tries to pass a 'transaction' object through. hopefully this
        # doesn't have some other baggage coming with it.
        if self.options and self.options.cheetah_compatibility:
            if parameter_list:
                code_node = CodeNode(
                    'def %(name)s(%(parameter_list)s, **kargs):' % vars(),
                    input_pos=node.pos)
            else:
                code_node = CodeNode('def %(name)s(**kargs):' % vars(),
                                     input_pos=node.pos)
        else:
            code_node = CodeNode('def %(name)s(%(parameter_list)s):' % vars(),
                                 input_pos=node.pos)

        needs_globals_added = True
        child_nodes = node.child_nodes

        if self.options and self.options.cheetah_compatibility:
            if_cheetah = CodeNode("if 'trans' in kargs:")
            code_node.append(if_cheetah)
            if_cheetah.append(CodeNode("_buffer = kargs['trans'].response()"))
            else_spitfire = CodeNode('else:')
            else_spitfire.append(CodeNode('_buffer = self.new_buffer()'))
            code_node.append(else_spitfire)
        else:
            # If the first node is an if statement with no else AND there's no
            # other statements, generate the if code first.  That way, we can
            # avoid doing extra work when the condition is false.  ie, avoid the
            # overhead of creating a new list setting up useless local variables
            # and joining all to get an empty string. Disable this in baked mode
            # until I figure out how to handle this. TODO: Do not perform
            # sanitization inside of a test_expression. Then we can remove this
            # baked_mode check.
            if child_nodes and len(child_nodes) == 1 and not self.baked_mode:
                if_node = child_nodes[0]
                if isinstance(if_node,
                              ast.IfNode) and not if_node.else_.child_nodes:
                    child_nodes = if_node.child_nodes
                    # Insert code that does:
                    #   if not ($test_expression):
                    #     return ''
                    new_if_condition = ast.IfNode(
                        ast.UnaryOpNode('not', if_node.test_expression))
                    new_if_condition.append(ast.ReturnNode(
                        ast.LiteralNode('')))
                    new_code = self.build_code(new_if_condition)
                    if node.uses_globals:
                        needs_globals_added = False
                        code_node.append(CodeNode('_globals = globals()'))
                    code_node.extend(new_code)

            code_node.append(CodeNode('_buffer = self.new_buffer()'))

        # Save the point where _globals and self_filter_funtion will go if used.
        # We don't append these here because we have to determine if these two
        # functions are used in the scope of the current ast.FunctionNode.
        insertion_point = len(code_node.child_nodes)

        if self.options and self.options.cheetah_cheats:
            node.uses_globals = True
            if_cheetah = CodeNode('if self.search_list:')
            if_cheetah.append(
                CodeNode('_self_search_list = self.search_list + [_globals]'))
            else_cheetah = CodeNode('else:')
            else_cheetah.append(CodeNode('_self_search_list = [_globals]'))
            code_node.append(if_cheetah)
            code_node.append(else_cheetah)

        for n in child_nodes:
            code_child_nodes = self.build_code(n)
            code_node.extend(code_child_nodes)

        if node.uses_globals and needs_globals_added:
            code_node.insert(insertion_point, CodeNode('_globals = globals()'))
            insertion_point += 1
        if node.uses_filter_function:
            code_node.insert(
                insertion_point,
                CodeNode('_self_filter_function = self.filter_function'))
            insertion_point += 1
        if node.uses_private_filter_function:
            code_node.insert(
                insertion_point,
                CodeNode(
                    '_self_private_filter_function = self._filter_function'))
            insertion_point += 1
        if node.uses_buffer_write:
            code_node.insert(insertion_point,
                             CodeNode('_buffer_write = _buffer.write'))
            insertion_point += 1
        if node.uses_buffer_extend:
            code_node.insert(insertion_point,
                             CodeNode('_buffer_extend = _buffer.extend'))
        if self.options.cheetah_compatibility:
            if_cheetah = CodeNode("if 'trans' not in kargs:")
            if_cheetah.append(CodeNode('return _buffer.getvalue()'))
            code_node.append(if_cheetah)
        else:
            code_node.append(CodeNode('return _buffer.getvalue()'))
        self.function_stack.pop()
        return [decorator_node, code_node]