Added extension ordering, this fixes #376.
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 12 Apr 2010 12:04:14 +0000 (14:04 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 12 Apr 2010 12:04:14 +0000 (14:04 +0200)
--HG--
branch : trunk

jinja2/environment.py
jinja2/ext.py
jinja2/parser.py
jinja2/testsuite/ext.py

index 25cec88b1c5063b7d1b201c960b5f800ec10f223..529c14c407d0a1b29050cb11e9161730b394b19f 100644 (file)
@@ -334,6 +334,11 @@ class Environment(object):
 
     lexer = property(get_lexer, doc="The lexer for this environment.")
 
+    def iter_extensions(self):
+        """Iterates over the extensions by priority."""
+        return iter(sorted(self.extensions.values(),
+                           key=lambda x: x.priority))
+
     def getitem(self, obj, argument):
         """Get an item or attribute of an object but prefer the item."""
         try:
@@ -407,7 +412,7 @@ class Environment(object):
         because there you usually only want the actual source tokenized.
         """
         return reduce(lambda s, e: e.preprocess(s, name, filename),
-                      self.extensions.itervalues(), unicode(source))
+                      self.iter_extensions(), unicode(source))
 
     def _tokenize(self, source, name, filename=None, state=None):
         """Called by the parser to do the preprocessing and filtering
@@ -415,7 +420,7 @@ class Environment(object):
         """
         source = self.preprocess(source, name, filename)
         stream = self.lexer.tokenize(source, name, filename, state)
-        for ext in self.extensions.itervalues():
+        for ext in self.iter_extensions():
             stream = ext.filter_stream(stream)
             if not isinstance(stream, TokenStream):
                 stream = TokenStream(stream, name, filename)
index 64d5525adf436a8c33ac53681144262b75630995..63ce408125aecc45c05050305d719a2ad07be730 100644 (file)
@@ -57,6 +57,13 @@ class Extension(object):
     #: if this extension parses this is the list of tags it's listening to.
     tags = set()
 
+    #: the priority of that extension.  This is especially useful for
+    #: extensions that preprocess values.  A lower value means higher
+    #: priority.
+    #:
+    #: .. versionadded:: 2.4
+    priority = 100
+
     def __init__(self, environment):
         self.environment = environment
 
index 1f5e12a721c71af9fd2b00e719ec04f89cf783b4..9814c939c7252e2ca5a20a28e2f1f90486f6b757 100644 (file)
@@ -34,7 +34,7 @@ class Parser(object):
         self.filename = filename
         self.closed = False
         self.extensions = {}
-        for extension in environment.extensions.itervalues():
+        for extension in environment.iter_extensions():
             for tag in extension.tags:
                 self.extensions[tag] = extension.parse
         self._last_identifier = 0
index ac273b9887766bf2a919c386e45851e86c653582..c00c589fc1942a99b6bc6be1aadc36c8d0994df9 100644 (file)
@@ -204,6 +204,16 @@ class ExtensionsTestCase(JinjaTestCase):
         out = tmpl.render()
         assert out == 'Foo BAR Baz'
 
+    def test_extension_ordering(self):
+        class T1(Extension):
+            priority = 1
+        class T2(Extension):
+            priority = 2
+        env = Environment(extensions=[T1, T2])
+        ext = list(env.iter_extensions())
+        assert ext[0].__class__ is T1
+        assert ext[1].__class__ is T2
+
 
 class InternationalizationTestCase(JinjaTestCase):