On 4/3/07, Darren Chamberlain <[EMAIL PROTECTED]> wrote:
On 4/3/07, Sean McAfee <[EMAIL PROTECTED]> wrote:
> So, not much interest has been expressed in my proposal so far--not
> surprisingly, since I imagine this audience doesn't include many regular
> Python users. I wish I wasn't one myself. However, I still think a
Python
> implementation for the Template Toolkit would be a great thing to
have. The
> TT's power blows away any Python templating system I've ever
encountered.
I started a Python port of TT about three, maybe four years ago. Andy
and I discussed hosting it alongside the Perl source tree, but I
didn't get very far with it.
You didn't mention what you're using to generate the Template.Grammar
class,
Actually, I took the fast/lazy route of translating Template::Grammar
directly. A few regexen handled the state transition tables, while I
handled the rule routines manually.
but I took the approach of starting with the Perl grammar
(parser/Parser.yp), modifying the productions to be Python instead of
Perl, and then making a Grammar.py.skel to hold the code. I
considered using something other than YAPP to build the grammar, but
keeping the grammar the same between two different parser generators
wasn't something I wanted to think about, and I liked being able to
compare the Perl and Python versions side by side and see the exact
differences. All the native Python parser generators I saw did all
their work at runtime, and I think building a static grammar module
(the way Template::Grammar is built) is the Right Way to do it; The
TT grammar is not small, and building it dynamically when the grammar
module is loaded seems very wasteful to me. (Python is slow enough as
it is!) As far as generating the grammar statically: The problem is
the whitespace. Normally it doesn't bother me (I can even see how it
could be construed as a feature), but it makes generating Python code
artificially difficult.
This actually turned out to be far less difficult than I expected, with the
aid of a code-building helper class. For example, from the directive
routine to build an "if" statement:
code = Code()
code.write("if %s:" % expr, code.indent, block)
for expr, block in elses:
code.write(code.unindent, "elif %s:" % expr, code.indent, block)
if else_ is not None:
code.write(code.unindent, "else:", code.indent, else_)
return code.text()
Furthermore, all of the indentation-sensitive code lives in the Python
version of Directive.pm. I didn't need to care about indentation at all
when translating Grammar.pm.
I think there would have been a definite niche for it a few years ago,
but at this point there are a few template libraries for Python that
are popular, and usable, if not ideal. I don't use Python much
anymore, myself, so I can't say that I would need to use it now, but I
would have killed for a complete TT implementation in Python a few
years ago (I was part of a team that built a massive Zope product a
few years ago, and I lost much time and sanity to ZPT, but I've done
very little with Python since then).
Seems reasonable that there are people who would kill for one now, then,
right? Aside from myself, that is.
Has you gotten opinions on this
from anyone in the python community? Are there any prospective users?
Well, I use Python because I have to, not because I want to (although I like
it better now than I did at the start), so I haven't really become a part of
the Python community-at-large. What I had in mind was more along the lines
of: Throw another template system into the mix, and may the best one win, or
at least prosper. It's hard for me to imagine the TT wouldn't do well. I
mean, consider Django, seemingly one of the more popular options out there.
The template language is severely underwhelming compared to the TT. To do
something like a switch, you have to do this:
{% ifequal x 1 %}
...
{% else %}
{% ifequal x 2 %}
...
{% else %}
{% ifequal x 3 %}
...
{% endifequal %}
{% endifequal %}
{% endifequal %}
Some actual code at my workplace has one of these beasts seven levels deep,
because there's no better way to do it. Who wouldn't jump at the
opportunity to use something cleaner and more powerful? Or take
Clearsilver. You can't even do something as simple as pass an array
directly to your renderer. Where with the TT you do this:
$template->process($file, { rows => [EMAIL PROTECTED] });
With CS, you need to populate a "hierarchical data format" object, indexing
your data purely with strings. It looks kind of like this:
my $hdf = HDF->new();
for my $i (0 .. $#rows) {
$hdf->setValue("row.$i", $rows[$i]);
}
$renderer->render($hdf);
Repeat for every array in the dataset. Just painful.
--Sean