I originally wrote Margate as an exercise in learning about Python bytecode, but I released it in case it was somewhat useful. However, after releasing it I discovered that Jinja2 also includes a bytecode generator, so probably makes this obsolete for any practical purposes. I'm not actively maintaining this project any more.
Margate is a library that provides a Django-compatible template engine where the templates compile to raw Python bytecode. In theory, this will make them expand faster. This is at a very early stage and is experimental.
Currently Margate supports the following:
for
loopsif
blocks with arbitrary conditions (but notelse
blocks)extends
nodes andblock
nodes that can be overridden in extending templates- Arbitrary nesting of the above (though this isn't well tested yet)
- Embedding expression values in output
The compiler takes a text template and ultimately outputs an ordinary Python function, which you can call (passing context data as the kwargs) to get rendered text output.
The first stage is to parse it into a tree structure. In theory this might be able to reuse some parsing code from within Django, but the API doesn't really seem to be designed to be extended. Instead, there's a small ad hoc parser. First it "tokenises", where each "token" is a chunk of the template (a literal string, a variable inclusion or a {% xyz %} block. The expressions inside the execution blocks also get parsed as a separate operation.
The resultant parse tree is processed by a code generator that generates abstract bytecode, using the Bytecode module to turn this into concrete bytecode that can be processed natively by the Python virtual machine. Code generation just expands out some templates with hand-generated bytecode.
I've only done minimal performance tests so far, but on a couple of simple cases Margate is 10 times faster than "real" Django templates.
See performance_test.py for the details.
This probably means you can shave a few milliseconds off your page load time by using Margate.