Esempio n. 1
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. 2
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. 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 assign_after_filter_fails(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #set $foo = 'foo'
          $foo
          #set $foo = 'bar'
          $foo
        #end def
        """

        ast_root, function_node = self._build_function_template()
        first_assign = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode('foo'))
        function_node.append(first_assign)
        first_use = ast.FilterNode(ast.IdentifierNode('foo'))
        function_node.append(first_use)
        second_assign = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode('bar'))
        function_node.append(second_assign)
        second_use = ast.FilterNode(ast.IdentifierNode('foo'))
        function_node.append(second_use)

        optimization_analyzer = optimizer.OptimizationAnalyzer(
            ast_root, self.compiler.analyzer_options, self.compiler)

        optimization_analyzer.visit_ast = test_util.RecordedFunction(
            optimization_analyzer.visit_ast)

        self.assertRaises(compiler.Warning, optimization_analyzer.visit_ast,
                          ast_root)
Esempio n. 5
0
    def double_assign_ok(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #set $foo = 'foo'
          #set $foo = 'bar'
          $foo
        #end def
        """

        ast_root, function_node = self._build_function_template()
        first_assign = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode('foo'))
        function_node.append(first_assign)
        second_assign = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode('bar'))
        function_node.append(second_assign)
        first_use = ast.FilterNode(ast.IdentifierNode('foo'))
        function_node.append(first_use)

        optimization_analyzer = optimizer.OptimizationAnalyzer(
            ast_root, self.compiler.analyzer_options, self.compiler)

        optimization_analyzer.visit_ast = test_util.RecordedFunction(
            optimization_analyzer.visit_ast)

        try:
            optimization_analyzer.visit_ast(ast_root)
        except compiler.Warning:
            self.fail('visit_ast raised WarningError unexpectedly.')
Esempio n. 6
0
    def test_list_elements_are_optimized(self):
        self.ast_description = """
        Input:
        [1, 2, 3]
        """

        ast_root = ast.ListLiteralNode('list')
        ast_root.child_nodes.append(ast.LiteralNode(1))
        ast_root.child_nodes.append(ast.LiteralNode(2))
        ast_root.child_nodes.append(ast.LiteralNode(3))

        optimization_analyzer = self._get_analyzer(ast_root)
        optimization_analyzer.visit_ast(ast_root)
        self.assertEqual(len(optimization_analyzer.visit_ast.GetCalls()), 4)
Esempio n. 7
0
    def test_slice_non_identifier_error(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #set 1[1] = 1
        #end def
        """

        ast_root, def_node = self._build_function_template()
        assign_node = ast.AssignNode(
            ast.SliceNode(
                ast.LiteralNode(1), ast.LiteralNode(1)), ast.LiteralNode(1))
        def_node.append(assign_node)

        semantic_analyzer = self._get_analyzer(ast_root)

        self.assertRaises(analyzer.SemanticAnalyzerError,
                          semantic_analyzer.get_ast)
Esempio n. 8
0
    def test_index_before_assign_error(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #set $foo[1] = 1
        #end def
        """

        ast_root, function_node = self._build_function_template()
        assign_node = ast.AssignNode(
            ast.SliceNode(
                ast.IdentifierNode('foo'), ast.LiteralNode(1)),
            ast.LiteralNode(1))
        function_node.append(assign_node)

        optimization_analyzer = self._get_analyzer(ast_root)
        self.assertRaises(analyzer.SemanticAnalyzerError,
                          optimization_analyzer.visit_ast, ast_root)
Esempio n. 9
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. 10
0
    def test_slice_identifier_ok(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #set $foo[1] = 1
        #end def
        """

        ast_root, def_node = self._build_function_template()
        assign_node = ast.AssignNode(
            ast.SliceNode(
                ast.IdentifierNode('foo'), ast.LiteralNode(1)),
            ast.LiteralNode(1))
        def_node.append(assign_node)

        semantic_analyzer = self._get_analyzer(ast_root)

        try:
            semantic_analyzer.get_ast()
        except analyzer.SemanticAnalyzerError:
            self.fail('get_ast raised SemanticAnalyzerError unexpectedly.')
Esempio n. 11
0
    def analyzeTextNode(self, pnode):
        if pnode.child_nodes:
            self.compiler.error(
                SemanticAnalyzerError("ast.TextNode can't have children"),
                pos=pnode.pos)

        value = pnode.value
        if self.options.normalize_whitespace:
            value = text.normalize_whitespace(value)
        literal_node = ast.LiteralNode(value, pos=pnode.pos)
        buffer_write = ast.BufferWrite(literal_node, pos=pnode.pos)
        return [buffer_write]
Esempio n. 12
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. 13
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. 14
0
    def test_collect_writes_join_simple(self):
        self.ast_description = """
        file: TestTemplate

        #def test_function
          foo
          bar
        #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')))
        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))
        expected_hash = hash(ast_root)

        got_hash = hash(optimization_analyzer.optimize_ast())
        self.assertEqual(expected_hash, got_hash)
Esempio n. 15
0
    def test_collect_writes_no_change(self):
        self.ast_description = """
        file: TestTemplate

        #def test_function
          foo
        #end def
        """

        ast_root, function_node = self._build_function_template()
        function_node.append(ast.BufferWrite(ast.LiteralNode('foo')))
        expected_hash = hash(ast_root)

        optimization_analyzer = self._get_analyzer(ast_root)
        got_hash = hash(optimization_analyzer.optimize_ast())
        self.assertEqual(expected_hash, got_hash)
Esempio n. 16
0
    def test_attr_error(self):
        self.ast_description = """
        file: TestTemplate
        #implements library
        #attr $foo = True
        #def test_function
        #end def
        """

        ast_root, def_node = self._build_function_template_library()
        attr_node = ast.AttributeNode('foo', default=ast.LiteralNode(True))
        ast_root.insert_before(def_node, attr_node)

        semantic_analyzer = self._get_analyzer(ast_root)

        self.assertRaises(analyzer.SemanticAnalyzerError,
                          semantic_analyzer.get_ast)
Esempio n. 17
0
    def test_set_error(self):
        self.ast_description = """
        file: TestTemplate
        #implements library
        #set $foo = True
        #def test_function
        #end def
        """

        ast_root, def_node = self._build_function_template_library()
        assign_node = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(True))
        ast_root.insert_before(def_node, assign_node)

        semantic_analyzer = self._get_analyzer(ast_root)

        self.assertRaises(analyzer.SemanticAnalyzerError,
                          semantic_analyzer.get_ast)
Esempio n. 18
0
    def _build_for_template(self):
        """ Build a simple template with a function and a for loop.

        file: TestTemplate
        #def test_function
          #for $i in []
          #end for
        #end def
        """
        ast_root, def_node = self._build_function_template()
        target_list = ast.TargetListNode()
        target_list.append(ast.PlaceholderNode('foo'))
        expression_list = ast.ExpressionListNode()
        expression_list.append(ast.LiteralNode([]))
        for_node = ast.ForNode(target_list=target_list,
                               expression_list=expression_list)
        def_node.append(for_node)
        return (ast_root, def_node, for_node)
Esempio n. 19
0
    def test_non_empty_for_ok(self):
        self.ast_description = """
        file: TestTemplate
        #def test_function
          #for $i in []
             #set $foo = True
          #end for
        #end def
        """

        ast_root, def_node, for_node = self._build_for_template()
        assign_node = ast.AssignNode(
            ast.IdentifierNode('foo'), ast.LiteralNode(True))
        for_node.append(assign_node)

        semantic_analyzer = self._get_analyzer(ast_root)

        try:
            semantic_analyzer.get_ast()
        except analyzer.SemanticAnalyzerError:
            self.fail('get_ast raised SemanticAnalyzerError unexpectedly.')
Esempio n. 20
0
    def analyzePlaceholderSubstitutionNode(self, pnode):
        # print ' '.join(analyzePlaceholderSubstitutionNode', pnode,
        #                pnode.parameter_list.get_arg_map())
        node_list = []
        ph_expression = self.build_ast(pnode.expression)[0]
        # If the expression contained a macro that was parsed as a
        # fragment, the expression is now a statement and can be moved
        # outside of the ast.PlaceholderSubstitutionNode.
        #
        # This is a hack to get around design decisions that were made
        # early on. It is up to the macro authors to correctly decide how
        # the macro should be parsed and the compiler should throw errors
        # if there is an odd state where nodes are somewhere unexpected.
        if isinstance(ph_expression, ast.statement_nodes):
            return [ph_expression]

        arg_map = pnode.parameter_list.get_arg_map()
        default_format_string = '%s'
        format_string = arg_map.get('format_string', default_format_string)

        skip_filter = False
        cache_forever = False
        registered_function = False
        function_has_only_literal_args = False
        never_cache = False
        if isinstance(ph_expression, ast.CallFunctionNode):
            fname = ph_expression.expression.name
            if self.compiler.registry_contains(fname):
                function_has_only_literal_args = (
                    ph_expression.arg_list and not [
                        _arg for _arg in ph_expression.arg_list
                        if not isinstance(_arg, ast.LiteralNode)
                    ])
                skip_filter = self.compiler.get_registry_value(
                    fname, 'skip_filter')
                skip_unless_baked = self.compiler.get_registry_value(
                    fname, 'skip_filter_unless_baked')
                skip_filter = skip_filter or (not self.template.baked
                                              and skip_unless_baked)
                cache_forever = self.compiler.get_registry_value(
                    fname, 'cache_forever')
                never_cache = self.compiler.get_registry_value(
                    fname, 'never_cache')

            elif ph_expression.library_function:
                # Don't escape function calls into library templates.
                skip_filter = True

        if (self.compiler.enable_filters
                and format_string == default_format_string
                and not isinstance(ph_expression, ast.LiteralNode)):
            arg_node_map = pnode.parameter_list.get_arg_node_map()
            if 'raw' in arg_map:
                # If this is a |raw usage and the template does not allow raw,
                # raise an error.
                self.uses_raw = True
                if (self.options.no_raw
                        and not self.template.explicitly_allow_raw):
                    err_msg = ('|raw is not allowed in templates compiled '
                               'with the --no-raw flag.')
                    self.compiler.error(SemanticAnalyzerError(err_msg),
                                        pos=pnode.pos)
            else:
                # if we need to filter, wrap up the node and wait for further
                # analysis later on
                if skip_filter:
                    # explicitly set the filter to none here - this means we
                    # will cache expensive pseudo-filtered nodes
                    ph_expression = ast.FilterNode(ph_expression,
                                                   None,
                                                   pos=pnode.pos)
                else:
                    ph_expression = ast.FilterNode(
                        ph_expression,
                        arg_node_map.get('filter', ast.DefaultFilterFunction),
                        pos=pnode.pos)

                # if this is a literal node, we still might want to filter it
                # but the output should always be the same - so do it once and
                # cache FIXME: could fold this and apply the function at
                # compile-time
                if (not never_cache and
                    (registered_function and function_has_only_literal_args)
                        or cache_forever or 'cache' in arg_map):
                    cache_expression = ast.CacheNode(ph_expression,
                                                     pos=pnode.pos)
                    self.template.cached_identifiers.add(cache_expression)
                    node_list.append(cache_expression)
                    ph_expression = ast.IdentifierNode(cache_expression.name,
                                                       pos=pnode.pos)

        if isinstance(ph_expression, ast.LiteralNode):
            buffer_write = ast.BufferWrite(ph_expression, pos=pnode.pos)
            node_list.append(buffer_write)
        elif (self.compiler.enable_filters
              and format_string == default_format_string):
            # we are already filtering, don't bother creating a new string
            buffer_write = ast.BufferWrite(ph_expression, pos=pnode.pos)
            node_list.append(buffer_write)
        else:
            buffer_write = ast.BufferWrite(ast.BinOpNode(
                '%', ast.LiteralNode(format_string, pos=pnode.pos),
                ph_expression),
                                           pos=pnode.pos)
            node_list.append(buffer_write)
        return node_list
Esempio n. 21
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. 22
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]