changeset 826:8ebccfa9a9fe experimental-inline

inline branch: Add code block support to the template inliner, and some tweaks/cleanup.
author cmlenz
date Fri, 13 Mar 2009 09:34:50 +0000
parents abb1f1d2f4f3
children eb8aa8690480
files examples/bench/bigtable.py genshi/template/inline.py
diffstat 2 files changed, 51 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/examples/bench/bigtable.py
+++ b/examples/bench/bigtable.py
@@ -9,8 +9,10 @@
 import sys
 import timeit
 from StringIO import StringIO
+
 from genshi.builder import tag
-from genshi.template import MarkupTemplate, NewTextTemplate
+from genshi.core import Stream
+from genshi.template import Context, MarkupTemplate, NewTextTemplate
 
 try:
     from elementtree import ElementTree as et
@@ -55,6 +57,7 @@
 </tr>
 </table>
 """)
+genshi_tmpl_compiled = genshi_tmpl.compile()
 
 genshi_tmpl2 = MarkupTemplate("""
 <table xmlns:py="http://genshi.edgewall.org/">$table</table>
@@ -103,6 +106,11 @@
     stream = genshi_tmpl.generate(table=table)
     stream.render('html', strip_whitespace=False)
 
+def test_genshi_compiled():
+    """Genshi template, compiled to Python"""
+    stream = Stream(genshi_tmpl_compiled.generate(Context(table=table)))
+    stream.render('html', strip_whitespace=False)
+
 def test_genshi_text():
     """Genshi text template"""
     stream = genshi_text_tmpl.generate(table=table)
@@ -196,9 +204,10 @@
 
 
 def run(which=None, number=10):
-    tests = ['test_builder', 'test_genshi', 'test_genshi_text',
-             'test_genshi_builder', 'test_mako', 'test_kid', 'test_kid_et',
-             'test_et', 'test_cet', 'test_clearsilver', 'test_django']
+    tests = ['test_builder', 'test_genshi', 'test_genshi_compiled',
+             'test_genshi_text', 'test_genshi_builder', 'test_mako',
+             'test_kid', 'test_kid_et', 'test_et', 'test_cet',
+             'test_clearsilver', 'test_django']
 
     if which:
         tests = filter(lambda n: n[5:] in which, tests)
--- a/genshi/template/inline.py
+++ b/genshi/template/inline.py
@@ -15,7 +15,7 @@
 
 from genshi.core import Attrs, Stream, _ensure, START, END, TEXT
 from genshi.template.astutil import _ast
-from genshi.template.base import EXPR, SUB
+from genshi.template.base import EXEC, EXPR, SUB
 from genshi.template.directives import *
 
 
@@ -45,22 +45,28 @@
         # characters
         if isinstance(obj, basestring):
             yield TEXT, obj, pos
+        elif isinstance(obj, (int, float, long)):
+            yield TEXT, unicode(obj), pos
         elif hasattr(obj, '__iter__'):
             for event in _ensure(obj):
                 yield event
         else:
             yield TEXT, unicode(obj), pos
 
+
 def _expand_text(obj):
     if obj is not None:
         if isinstance(obj, basestring):
             return [obj]
+        elif isinstance(obj, (int, float, long)):
+            return [unicode(result)]
         elif hasattr(obj, '__iter__'):
             return [e[1] for e in _ensure(obj) if e[0] is TEXT]
         else:
             return [unicode(obj)]
     return []
 
+
 def _assign(ast):
     buf = []
     def _build(node, indices):
@@ -72,17 +78,19 @@
     _build(ast, ())
     return '{%s}' % ', '.join(buf)
 
+
 def inline(template):
     w = CodeWriter()
 
     yield w('from genshi.core import Attrs, QName')
-    yield w('from genshi.core import START, START_NS, END, END_NS, DOCTYPE, TEXT')
+    yield w('from genshi.core import START, START_CDATA, START_NS, END, '
+                                    'END_CDATA, END_NS, DOCTYPE, TEXT')
     yield w('from genshi.path import Path')
-    yield w('from genshi.template.eval import Expression')
+    yield w('from genshi.template.eval import Expression, Suite')
     yield w('from genshi.template.inline import _expand, _expand_text')
     yield w()
 
-    def _predecl_vars(stream):
+    def _declare_vars(stream):
         for kind, data, pos in stream:
 
             if kind is START:
@@ -103,6 +111,9 @@
             elif kind is EXPR:
                 yield 'E', data, data
 
+            elif kind is EXEC:
+                yield 'S', data, data
+
             elif kind is SUB:
                 directives, substream = data
                 for directive in directives:
@@ -117,24 +128,24 @@
                     elif hasattr(directive, 'path') and directive.path:
                         yield 'P', directive.path, directive.path
 
-                for line in _predecl_vars(substream):
+                for line in _declare_vars(substream):
                     yield line
 
-    def _predecl_defs(stream):
+    def _declare_functions(stream, names):
         for kind, data, pos in stream:
             if kind is SUB:
                 directives, substream = data
                 for idx, directive in enumerate(directives):
                     if isinstance(directive, DefDirective):
-                        defs.append(directive.name)
+                        names.append(directive.name)
                         yield w('def %s:', directive.signature)
                         w.shift()
                         args = ['%r: %s' % (name, name) for name
                                 in directive.args]
-                        yield w('ctxt.push({%s})', ', '.join(args))
+                        yield w('push({%s})', ', '.join(args))
                         for line in _apply(directives[idx + 1:], substream):
                             yield line
-                        yield w('ctxt.pop()')
+                        yield w('pop()')
                         w.unshift()
 
     # Recursively apply directives
@@ -156,10 +167,10 @@
         if isinstance(d, ForDirective):
             yield w('for v in e[%d].evaluate(ctxt):', index['E'][d.expr])
             w.shift()
-            yield w('ctxt.push(%s)', _assign(d.target))
+            yield w('push(%s)', _assign(d.target))
             for line in _apply(rest, stream):
                 yield line
-            yield w('ctxt.pop()')
+            yield w('pop()')
             w.unshift()
 
         elif isinstance(d, IfDirective):
@@ -182,6 +193,9 @@
                 yield w('for evt in _expand(e[%d].evaluate(ctxt), (f, %d, %d)): yield evt',
                         index['E'][data], *pos[1:])
 
+            elif kind is EXEC:
+                yield w('s[%d].execute(ctxt)', index['S'][data])
+
             elif kind is START:
                 tagname, attrs = data
                 qn = index['Q'][tagname]
@@ -225,9 +239,9 @@
     yield w('_F = %r', template.filename)
     yield w()
 
-    yield '# predeclare qnames, attributes, and expressions'
+    yield '# Create qnames, attributes, expressions, and suite objects'
     index, counter, values = {}, {}, {}
-    for prefix, key, value in _predecl_vars(template.stream):
+    for prefix, key, value in _declare_vars(template.stream):
         if not prefix in counter:
             counter[prefix] = 0
         if key not in index.get(prefix, ()):
@@ -243,16 +257,17 @@
 
     yield w('def generate(ctxt, %s):',
             ', '.join(['f=_F'] + ['%s=_%s' % (n.lower(), n) for n in index]))
+    w.shift()
+    yield w('push = ctxt.push; pop = ctxt.pop')
     yield w()
-    w.shift()
 
     # Define macro functions
     defs = []
-    for line in _predecl_defs(template.stream):
+    for line in _declare_functions(template.stream, names=defs):
         yield line
     if defs:
         yield w()
-        yield w('ctxt.push({%s})', ', '.join(['%r: %s' % (n, n) for n in defs]))
+        yield w('push({%s})', ', '.join('%r: %s' % (n, n) for n in defs))
         yield w()
 
     ei, pi = [0], [0]
@@ -264,12 +279,13 @@
     import timeit
     from genshi.template import Context, MarkupTemplate
 
-    text = """<!DOCTYPE html
-    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
+    text = """<html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:py="http://genshi.edgewall.org/"
       lang="en">
+ <?python
+    def foo(x):
+        return x*x
+ ?>
  <body>
     <h1 py:def="sayhi(name='world')" py:strip="">
       Hello, $name!
@@ -293,12 +309,12 @@
 
     print
     print 'Interpreted template:'
-    print tmpl.generate(ctxt)
+    print tmpl.generate(ctxt).render('html')
 
     print
     print 'Executed module:'
     module = tmpl.compile()
-    print Stream(module.generate(ctxt))
+    print Stream(module.generate(ctxt)).render('html')
 
     print
     print
Copyright (C) 2012-2017 Edgewall Software