# HG changeset patch # User cmlenz # Date 1236936890 0 # Node ID 8ebccfa9a9fe3f69f61609748c58a3df02d16238 # Parent abb1f1d2f4f31b0e13d581704d4e75acbf4841a9 inline branch: Add code block support to the template inliner, and some tweaks/cleanup. diff --git a/examples/bench/bigtable.py b/examples/bench/bigtable.py --- 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 @@ """) +genshi_tmpl_compiled = genshi_tmpl.compile() genshi_tmpl2 = MarkupTemplate(""" $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) diff --git a/genshi/template/inline.py b/genshi/template/inline.py --- 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 = """ - +

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