We're evaluating switching to Mako from Genshi, primarily for
performance reasons. We run under Pylons and use Genshi in a fairly
specific way (we make extensive use of py:match in a similar way you'd
use <%def> / <%call> in Mako)
We have some 150+ templates to convert, so I wrote up an automated
script to do most of the work. See attached.
The basic approach I took was to use genshi to load the template and
process all the py: directives... then I derived from HTMLSerializer,
and use it to expand all the templates. This reaches pretty deep into
genshi and even into closures that genshi has defined, but the result
seems decent. It doesn't quite get interpreted by
Here are some of the limitations - some of which I think are worth
fixing, others..well... I plan to deal with the output manually after
running the script:
- Genshi compiles py:with statements down to an AST tree before
evaluation, but at that point I've lost all context. I've considered
trying to write an ast visitor that decompiles the AST back to python.
I'll bet for most AST nodes, it would be pretty simple.. but I thought
I'd ask around to see if anyone had tackled this before. On top of
this, Mako has no real notion of 'with' that I'm aware of, so I don't
have an easy way to scope variables just to one block
- Genshi allows '.' notation for dict member access - but not Mako. I
wish Mako had a similar mode, but I figure there's not much we can do
here other than wrap all our template-visible with some kind of
wrapper. We'll probably just deal with this by hand.
- I wasn't quite sure the equivalent of py:attrs in Mako - is there
any way to refer to caller.attributes() or anything?
- py:match conversion only works for the very specifc tag paths (i.e.
path="user-image") and not complex XPaths (i.e. path="user-
image[@id=X]")
- select() is not handled at all obviously. My hope here was to
recognize very specific patterns like "select('@*')" and "select('*|
text()')"
Please play with it! Send patches. If there's enough interest, I'll
start a google code project for this.
Alec
>
> - Genshi compiles py:with statements down to an AST tree before
> evaluation, but at that point I've lost all context. I've considered
> trying to write an ast visitor that decompiles the AST back to python.
> I'll bet for most AST nodes, it would be pretty simple.. but I thought
> I'd ask around to see if anyone had tackled this before. On top of
> this, Mako has no real notion of 'with' that I'm aware of, so I don't
> have an easy way to scope variables just to one block
py:with is....like python 2.6 with ? or just sets up some local
variables ? (I only used genshi briefly)
> - Genshi allows '.' notation for dict member access - but not Mako. I
> wish Mako had a similar mode, but I figure there's not much we can do
> here other than wrap all our template-visible with some kind of
> wrapper. We'll probably just deal with this by hand.
hm how do you tell apart someobject.someattr versus
somedict.somekey ? the compiler doesn't know the type of the parent.
> - I wasn't quite sure the equivalent of py:attrs in Mako - is there
> any way to refer to caller.attributes() or anything?
Mako recently supports somenamespace.attr.<somekey>, such as:
<%!
foo = "bar"
%>
then in a parent template:
${self.attr.foo}
this would work with "caller" too in a component-call-with-content
(they're all namespaces).
Although it can be emulated, it had to be done for TW's mako support
http://toscawidgets.org/trac/tw/browser/tw/core/mako_util.py
Yeah... and here is a good place to see how mako_util.py is used:
http://toscawidgets.org/trac/tw.forms/browser/tw/forms/templates
You can do a side-by-side comparison between genshi and mako templates
for tw.forms templates.
Cheers,
Roger