[svn] last changes from yesterday so that i can continue working in school on it
authorArmin Ronacher <armin.ronacher@active-4.com>
Fri, 2 Mar 2007 06:07:57 +0000 (07:07 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Fri, 2 Mar 2007 06:07:57 +0000 (07:07 +0100)
--HG--
branch : trunk

jdebug.py [new file with mode: 0644]
jinja/datastructure.py
jinja/nodes.py
jinja/parser.py
jinja/translators/python.py

diff --git a/jdebug.py b/jdebug.py
new file mode 100644 (file)
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()
index 80d6b1b443d7a83686a1a99f3c2d8c0bab363739..fed5cfacc16e5c4bbc492a4e55e0bfce7e207546 100644 (file)
@@ -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]
index a31b253926502b1c48dca16956b0df5299e10e64..256bcbd36909b1156c4436d4a8d89875adb581c5 100644 (file)
@@ -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.
index bc5d2a81a5053e28944a4dc18b43b97c1e187a0c..3150e53968f45cfd84a955b54af3dac19b628664 100644 (file)
@@ -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
index ee88789099d6f16fa82cb9b4e581b62fbf5f2cb0..31c4be7308cee30dd5c4bbfae4a4d688963df6e5 100644 (file)
@@ -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.