Evoque – managed eval-based freeform templating

Evoque is a full-featured generic text templating system for python using
a simple $-substitution syntax and providing support for flow control, nested
templates, overlays, inter-template addressing and invocation, cache management,
arbitrary python expressions, all python % operator formatting,
restricted execution, automatic cross-site scripting protection, advanced
encoding guessing algorithm, and more.

Allowing only python expressions and a managed evaluation namespace, Evoque
offers a surprising level of simplicity, versatility and performance.

Buzz

  • Full-featured pure python templating engine / 992 SLOC
  • Python 2.4, 2.5, 2.6 and 3.0
  • Unicode
  • Simplicity
  • Restrictable execution / sandbox
  • Data-driven template inheritance / runtime base template selection
  • Open-ended source or target file formats
  • Templates are managed via Collections in a Domain / cascading defaults
  • Domain-wide template names / addressing
  • Automatic input quoting / XSS protection
  • Speed

Snapshot

$overlay{name=site_base}

$begin{table_row}
    $for{ col in row }
        <td>${col}</td>\
    $else
        <td class="empty" colspan="7">empty row</td>
    $rof
$end{table_row}

<table>
    $for{ i, row in enumerate(rows) }
        <tr$if{i%2} class="odd"$fi> #[ "odd" rows get a special style ]#
            $evoque{#table_row}
        </tr>
    $rof
</table>

$evoque{disclaimer, collection="legals"}

$test{% site_base="site.html", 
        rows=[("a", "b", 3.0, {"one":1}, "<escape-me/>", "i", "j")] %}

Usage from within a Python application

Templates are always part of a Collection in a Domain —
a Domain and a default Collection instance are always created,
be it explicitly or implicitly.

The preferred way to load/retrieve a Template is via a Domain instance;
the following code implicitly creates the default Collection instance:

domain = Domain("/home/user/templates")
t = domain.get_template("snap.html")
print t.evoque(vars())

It may sometimes be more convenient to instantiate directly;
the following code implicitly creates the Domain and the default
Collection instances:

t = Template("/home/user/templates", "snap.html")
print t.evoque(vars())

Basic benchmark

A basic benchmark, consisting of a small template
that does a variety of standard templating tasks such as looping,
calling nested and external sub-templates, escaping of data, etc.
For each run, time is averaged over 2000 renderings, and the
best time of 4 runs is retained.
All times are in ms.
What you should want is automatic quoting and less time.

quoting qpy 1.7 evoque 0.4 mako 0.2.4 genshi 0.5.1
automatic 0.104 0.339 0.421 2.706 (c)
automatic R(a) 0.386
manual 0.318 (b) 0.387
none 0.262 0.308

(a) Restricted —
qpy 1.7 /
mako 0.2.4 /
genshi 0.5.1
offer no support for restricted execution or sandboxing
(b) manual quoting implies no qpy
(c) xml mode