예제 #1
0
    def parse(self, parser):
        lineno = parser.stream.__next__().lineno
        value = parser.parse_expression()

        items_per_page_obj = parser.stream.next_if('integer')
        items_per_page = items_per_page_obj.value if items_per_page_obj else DEFAULT_PAGINATION

        if parser.stream.skip_if('name:as'):
            name = parser.stream.expect('name').value
        elif hasattr(value, 'name'):
            name = value.name
        else:
            raise TemplateSyntaxError("Cannot determine the name of objects you want to paginate, use 'as foobar' syntax", lineno)

        while not parser.stream.current.type == 'block_end':
            parser.stream.skip()

        return [
            nodes.Assign(nodes.Name(name + '_pages', 'store'),
                self.call_method('_render_pages', [value, nodes.Name('request', 'load'), nodes.Const(items_per_page)])
            ).set_lineno(lineno),

            nodes.Assign(nodes.Name(name, 'store'),
                nodes.Getattr(nodes.Name(name + '_pages', 'load'), 'object_list', nodes.Impossible())
            ).set_lineno(lineno),
        ]
예제 #2
0
    def _output_child_to_const(self, node, frame, finalize):
        const = node.as_const(frame.eval_ctx)

        if not has_safe_repr(const):
            raise nodes.Impossible()

        if isinstance(node, nodes.TemplateData):
            return const

        return finalize.const(const)
예제 #3
0
    def parse(self, parser):
        lineno = parser.stream.next().lineno
        object_list = parser.parse_expression()
        if parser.stream.skip_if('name:as'):
            name = parser.stream.expect('name').value
        elif hasattr(object_list, 'name'):
            name = object_list.name
        else:
            raise TemplateSyntaxError(
                "Cannot determine the name of objects " \
                    "you want to paginate, use 'as foobar' syntax", lineno)

        kwargs = [] # wait... what?
        loops = 0
        while parser.stream.current.type != 'block_end':
            lineno = parser.stream.current.lineno
            if loops:
                parser.stream.expect('comma')
            key = parser.parse_assign_target().name
            if key not in self.default_kwargs.keys():
                raise TemplateSyntaxError(
                    "Unknown keyword argument for autopaginate. "\
                        "Your options are: %s" % (
                            ", ".join(self.default_kwargs.keys())
                            ))
            parser.stream.expect('assign')
            value = parser.parse_expression()
            kwargs.append(nodes.Keyword(key, value))
            loops += 1

        return [
            nodes.Assign(nodes.Name(name + '_pages', 'store'),
                         self.call_method('_render_pages',
                                          [object_list, nodes.Name('request', 'load')],
                                          kwargs)
                         ).set_lineno(lineno),

            nodes.Assign(nodes.Name(name, 'store'),
                         nodes.Getattr(nodes.Name(name + '_pages', 'load'),
                                       'object_list',
                                       nodes.Impossible())
                         ).set_lineno(lineno),
            ]
예제 #4
0
    def visit_Output(self, node, frame):
        """Same as :meth:`CodeGenerator.visit_Output`, but do not call
        ``to_string`` on output nodes in generated code.
        """
        if self.has_known_extends and frame.require_output_check:
            return

        finalize = self.environment.finalize
        finalize_context = getattr(finalize, 'contextfunction', False)
        finalize_eval = getattr(finalize, 'evalcontextfunction', False)
        finalize_env = getattr(finalize, 'environmentfunction', False)

        if finalize is not None:
            if finalize_context or finalize_eval:
                const_finalize = None
            elif finalize_env:

                def const_finalize(x):
                    return finalize(self.environment, x)
            else:
                const_finalize = finalize
        else:

            def const_finalize(x):
                return x

        # If we are inside a frame that requires output checking, we do so.
        outdent_later = False

        if frame.require_output_check:
            self.writeline('if parent_template is None:')
            self.indent()
            outdent_later = True

        # Try to evaluate as many chunks as possible into a templates string at
        # compile time.
        body = []

        for child in node.nodes:
            try:
                if const_finalize is None:
                    raise nodes.Impossible()

                const = child.as_const(frame.eval_ctx)
                if not has_safe_repr(const):
                    raise nodes.Impossible()
            except nodes.Impossible:
                body.append(child)
                continue

            # the frame can't be volatile here, because otherwise the as_const
            # function would raise an Impossible exception at that point
            try:
                if frame.eval_ctx.autoescape:
                    if hasattr(const, '__html__'):
                        const = const.__html__()
                    else:
                        const = escape(const)

                const = const_finalize(const)
            except Exception:
                # if something goes wrong here we evaluate the node at runtime
                # for easier debugging
                body.append(child)
                continue

            if body and isinstance(body[-1], list):
                body[-1].append(const)
            else:
                body.append([const])

        # if we have less than 3 nodes or a buffer we yield or extend/append
        if len(body) < 3 or frame.buffer is not None:
            if frame.buffer is not None:
                # for one item we append, for more we extend
                if len(body) == 1:
                    self.writeline('%s.append(' % frame.buffer)
                else:
                    self.writeline('%s.extend((' % frame.buffer)

                self.indent()

            for item in body:
                if isinstance(item, list):
                    val = repr(native_concat(item))

                    if frame.buffer is None:
                        self.writeline('yield ' + val)
                    else:
                        self.writeline(val + ',')
                else:
                    if frame.buffer is None:
                        self.writeline('yield ', item)
                    else:
                        self.newline(item)

                    close = 0

                    if finalize is not None:
                        self.write('environment.finalize(')

                        if finalize_context:
                            self.write('context, ')

                        close += 1

                    self.visit(item, frame)

                    if close > 0:
                        self.write(')' * close)

                    if frame.buffer is not None:
                        self.write(',')

            if frame.buffer is not None:
                # close the open parentheses
                self.outdent()
                self.writeline(len(body) == 1 and ')' or '))')

        # otherwise we create a format string as this is faster in that case
        else:
            format = []
            arguments = []

            for item in body:
                if isinstance(item, list):
                    format.append(native_concat(item).replace('%', '%%'))
                else:
                    format.append('%s')
                    arguments.append(item)

            self.writeline('yield ')
            self.write(repr(concat(format)) + ' % (')
            self.indent()

            for argument in arguments:
                self.newline(argument)
                close = 0

                if finalize is not None:
                    self.write('environment.finalize(')

                    if finalize_context:
                        self.write('context, ')
                    elif finalize_eval:
                        self.write('context.eval_ctx, ')
                    elif finalize_env:
                        self.write('environment, ')

                    close += 1

                self.visit(argument, frame)
                self.write(')' * close + ', ')

            self.outdent()
            self.writeline(')')

        if outdent_later:
            self.outdent()