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), ]
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)
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), ]
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()