changeset 351:0cc031745884 trunk

The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
author cmlenz
date Fri, 10 Nov 2006 23:32:24 +0000
parents 96882a191686
children 28b9ec2dce7f
files genshi/template/core.py genshi/template/directives.py
diffstat 2 files changed, 42 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/template/core.py
+++ b/genshi/template/core.py
@@ -177,6 +177,15 @@
             expr = ' "%s"' % self.expr.source
         return '<%s%s>' % (self.__class__.__name__, expr)
 
+    def prepare(self, directives, stream):
+        """Called after the template stream has been completely parsed.
+        
+        The part of the template stream associated with the directive will be
+        replaced by what this function returns. This allows the directive to
+        optimize the template or validate the way the directive is used.
+        """
+        return stream
+
     def tagname(self):
         """Return the local tag name of the directive as it is used in
         templates.
@@ -230,7 +239,7 @@
 
         self.filters = [self._flatten, self._eval]
 
-        self.stream = self._parse(encoding)
+        self.stream = list(self._prepare(self._parse(encoding)))
 
     def __repr__(self):
         return '<%s "%s">' % (self.__class__.__name__, self.filename)
@@ -288,6 +297,25 @@
         return _interpolate(text, [cls._FULL_EXPR_RE, cls._SHORT_EXPR_RE])
     _interpolate = classmethod(_interpolate)
 
+    def _prepare(self, stream):
+        """Call the `prepare` method of every directive instance in the
+        template so that various optimization and validation tasks can be
+        performed.
+        """
+        for kind, data, pos in stream:
+            if kind is SUB:
+                directives, substream = data
+                for directive in directives[:]:
+                    substream = directive.prepare(directives, substream)
+                substream = self._prepare(substream)
+                if directives:
+                    yield kind, (directives, list(substream)), pos
+                else:
+                    for event in substream:
+                        yield event
+            else:
+                yield kind, data, pos
+
     def generate(self, *args, **kwargs):
         """Apply the template to the given context data.
         
--- a/genshi/template/directives.py
+++ b/genshi/template/directives.py
@@ -114,16 +114,9 @@
     """
     __slots__ = []
 
-    def __call__(self, stream, ctxt, directives):
-        def _generate():
-            yield stream.next()
-            yield EXPR, self.expr, (None, -1, -1)
-            event = stream.next()
-            for next in stream:
-                event = next
-            yield event
-
-        return _apply_directives(_generate(), ctxt, directives)
+    def prepare(self, directives, stream):
+        directives.remove(self)
+        return [stream[0], (EXPR, self.expr, (None, -1, --1)),  stream[-1]]
 
 
 class DefDirective(Directive):
@@ -367,8 +360,9 @@
     """
     __slots__ = []
 
-    def __call__(self, stream, ctxt, directives):
-        yield EXPR, self.expr, (None, -1, -1)
+    def prepare(self, directives, stream):
+        directives.remove(self)
+        return [(EXPR, self.expr, (None, -1, -1))]
 
 
 class StripDirective(Directive):
@@ -406,11 +400,7 @@
 
     def __call__(self, stream, ctxt, directives):
         def _generate():
-            if self.expr:
-                strip = self.expr.evaluate(ctxt)
-            else:
-                strip = True
-            if strip:
+            if self.expr.evaluate(ctxt):
                 stream.next() # skip start tag
                 previous = stream.next()
                 for event in stream:
@@ -419,8 +409,13 @@
             else:
                 for event in stream:
                     yield event
+        return _apply_directives(_generate(), ctxt, directives)
 
-        return _apply_directives(_generate(), ctxt, directives)
+    def prepare(self, directives, stream):
+        if not self.expr:
+            directives.remove(self)
+            return stream[1:-1]
+        return stream
 
 
 class ChooseDirective(Directive):
Copyright (C) 2012-2017 Edgewall Software