From 19863ef8a395b3cd962210d4301b5544bd86cd4c Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 2 Mar 2007 07:07:57 +0100 Subject: [PATCH] [svn] last changes from yesterday so that i can continue working in school on it --HG-- branch : trunk --- jdebug.py | 22 ++++++++++++++++++++++ jinja/datastructure.py | 5 ++++- jinja/nodes.py | 20 ++++++++++++++++++++ jinja/parser.py | 18 ++++++++++++++++-- jinja/translators/python.py | 16 ++++++++++++++-- 5 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 jdebug.py diff --git a/jdebug.py b/jdebug.py new file mode 100644 index 0000000..95f10cc --- /dev/null +++ b/jdebug.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +""" + jdebug + ~~~~~~ + + Helper module to simplify jinja debugging. Use + + :copyright: 2006 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +from jinja import Environment +from jinja.parser import Parser +from jinja.translators.python import PythonTranslator + + +__all__ = ['e', 't', 'p'] + +e = Environment() +t = e.from_string + +def p(x): + print PythonTranslator(e, Parser(e, x).parse()).translate() diff --git a/jinja/datastructure.py b/jinja/datastructure.py index 80d6b1b..fed5cfa 100644 --- a/jinja/datastructure.py +++ b/jinja/datastructure.py @@ -166,7 +166,8 @@ class LoopContext(object): """ jinja_allowed_attributes = ['index', 'index0', 'length', 'parent', - 'even', 'odd', 'revindex0', 'revindex'] + 'even', 'odd', 'revindex0', 'revindex', + 'first', 'last'] def __init__(self, seq, parent, loop_function): self.loop_function = loop_function @@ -193,6 +194,8 @@ class LoopContext(object): length = property(lambda s: s._stack[-1]['length']) even = property(lambda s: s._stack[-1]['index'] % 2 == 0) odd = property(lambda s: s._stack[-1]['index'] % 2 == 1) + first = property(lambda s: s._stack[-1]['index'] == 0) + last = property(lambda s: s._stack[-1]['index'] == s._stack[-1]['length'] - 1) def __iter__(self): s = self._stack[-1] diff --git a/jinja/nodes.py b/jinja/nodes.py index a31b253..256bcbd 100644 --- a/jinja/nodes.py +++ b/jinja/nodes.py @@ -203,6 +203,26 @@ class Macro(Node): ) +class Set(Node): + """ + Allow defining own variables. + """ + + def __init__(self, lineno, name, expr): + self.lineno = lineno + self.name = name + self.expr = expr + + def get_items(self): + return [self.name, self.expr] + + def __repr__(self): + return 'Set(%r, %r)' % ( + self.name, + self.expr + ) + + class Filter(Node): """ Node for filter sections. diff --git a/jinja/parser.py b/jinja/parser.py index bc5d2a8..3150e53 100644 --- a/jinja/parser.py +++ b/jinja/parser.py @@ -50,6 +50,7 @@ class Parser(object): 'for': self.handle_for_directive, 'if': self.handle_if_directive, 'cycle': self.handle_cycle_directive, + 'set': self.handle_set_directive, 'filter': self.handle_filter_directive, 'print': self.handle_print_directive, 'macro': self.handle_macro_directive, @@ -125,6 +126,19 @@ class Parser(object): # skip that. return nodes.Cycle(lineno, ast.expr.args[0]) + def handle_set_directive(self, lineno, gen): + """ + Handle {% set foo = 'value of foo' %}. + """ + try: + name = gen.next() + if name[1] != 'name' or gen.next()[1:] != ('operator', '='): + raise ValueError() + except (StopIteration, ValueError): + raise TemplateSyntaxError('invalid syntax for set', lineno) + ast = self.parse_python(lineno, gen, '(%s)') + return nodes.Set(lineno, name[1], ast.expr) + def handle_filter_directive(self, lineno, gen): """ Handle {% filter foo|bar %} directives. @@ -151,7 +165,7 @@ class Parser(object): def handle_macro_directive(self, lineno, gen): """ - Handle {% macro foo(bar, baz) %}. + Handle {% macro foo bar, baz %}. """ try: macro_name = gen.next() @@ -216,7 +230,7 @@ class Parser(object): raise TemplateSyntaxError('include requires a string', lineno) return nodes.Include(lineno, tokens[0][2][1:-1]) - def parse_python(self, lineno, gen, template='%s'): + def parse_python(self, lineno, gen, template): """ Convert the passed generator into a flat string representing python sourcecode and return an ast node or raise a diff --git a/jinja/translators/python.py b/jinja/translators/python.py index ee88789..31c4be7 100644 --- a/jinja/translators/python.py +++ b/jinja/translators/python.py @@ -86,6 +86,7 @@ class PythonTranslator(Translator): nodes.Cycle: self.handle_cycle, nodes.Print: self.handle_print, nodes.Macro: self.handle_macro, + nodes.Set: self.handle_set, nodes.Filter: self.handle_filter, nodes.Block: self.handle_block, nodes.Include: self.handle_include, @@ -136,7 +137,7 @@ class PythonTranslator(Translator): compile(translator.translate(), filename, 'exec')) process = staticmethod(process) - # -- private methods + # -- private helper methods def indent(self, text): """ @@ -146,7 +147,8 @@ class PythonTranslator(Translator): def filter(self, s, filter_nodes): """ - Apply a filter on an object. + Apply a filter on an object that already is a python expression. + Used to avoid redundant code in bitor and the filter directive. """ filters = [] for n in filter_nodes: @@ -214,6 +216,7 @@ class PythonTranslator(Translator): node = tmpl lines = [ + 'from __future__ import division\n' 'from jinja.datastructure import Undefined, LoopContext, CycleContext\n\n' 'def generate(context, write):\n' ' # BOOTSTRAPPING CODE\n' @@ -375,6 +378,15 @@ class PythonTranslator(Translator): return '\n'.join(buf) + def handle_set(self, node): + """ + Handle variable assignments. + """ + return self.indent('context[%r] = %s' % ( + node.name, + self.handle_node(node.expr) + )) + def handle_filter(self, node): """ Handle filter sections. -- 2.26.2