s-expression templating in python

I’m constantly on the hunt for the perfect templating module. When I was much younger, primarily doing PHP, I quickly saw that string concatenation and variable interpolation were not good solutions when trying to author lots of complex documents. I did some searching, and found Smarty, which satisfied my needs at that time. Over the past year, I’ve started using python primarily, and my desires have changed.

Real useage provides the practical definitions for software requirements. For now, I’d like to take a look at approaches I’d personally consider using for generating XML. For now, I consider XML generation a primary task, and we can talk about HTML generation some other time. In fact, I’m currently satisfied using XSLT to transform XML into HTML.

My first forray into templating engines was kid. They had xml-based syntax, with variable implementation reminiscent of smarty and php. It was supposed to be a kind of simpler, procedural XSLT-like templating language. However, I ended up not liking it very much. I know Genshi is around, which promises to make certain idioms simpler and advertises better performance, but I think my issue isn’t so much with the syntax, as the some of the conceptual foundations. Then again, I was attempting to use it for HTML and XML generation. Perhaps if I reconsidered for purely XML generation, I might change my mind.

Anyway, Kid has been around since November of 2004 (see line #236).

During my PHP days, I remember reading some LISP documentation. I found one lisp package that suggested that HTML looked an awful lot like s-expressions, but with uglier syntax. This really intrigued me. Earlier this year, I discovered stan, which is a python library implementing s-expression based html/xml generation through clever use of __call__. The basic idea is that you can invoke the name of the tag you want, provide keyword arguments to fill out the infoset’s attributes, and you use list syntax to fill out the contents of the object. There’s not much overhead for infoset processing as there are with other XML toolkits, presumably it performs quite well, although I’ve never tested it.

Stan is complicated though. It seems to be intended for primarily HTML generation, and it’s unclear how to use it in the same manner as suggested for HTML but for predefined XML vocabularies. There is some kind of callback system that I haven’t quite grokked, despite reading “meet stan” several times over. However, I like the approach.

I looked real hard for the history of stan. The earliest changeset I could find was 564, but it had no information and no file. So the second earliest changeset I could find is dated February 2004. I didn’t see any CHANGES or HISTORY files, but I would assume the author probably was noodling on stan for a few months before that. Please correct me if you know otherwise.

Stan also has a lot of dependencies, and can be a bit tricky to install. For some reason or another, I was unable to get it using the cheeseshop/distutils/easy_install method. Then a short while ago, I stumbled upon breve. It claims to be a fresh rewrite of TurboStan, by the author of turbostan. Basically, the story here is that the author created a turbogears plugin that allowed stan to be used in turbogears applications. After doing this, the author became wiser, and decided to rewrite stan without all the dependencies, and called it breve. I believe breve was written this year (2007) or late 2006, but I can’t quickly find any resources to verify, and I’m tired of researching.

On a side note, using AJAX for testing is an interesting idea.

Since Breve is pretty much similar to stan, I still don’t quite fully understand how the renderer and context stuff works. However, they do explain how to facilitate new xml syntax and added a “when” facility for easier conditionals. I think this is my current favorite, and I look forward to using this in projects going forward. What would be really nifty is to go from relax-ng to s-expression xml generation. Breve uses xsd to provide you with new xml tags, but I think it’d be better to go with relax-ng, especially the compact syntax. Optimally, it would have an option to check validate your syntax for you, as well.

Today, I was reading through Ian Bicking’s stuff, when I found (among many many interesting things) py.xml. Which claims to have been inspired by XIST. XIST is ANOTHER s-expression based xml generation library. They again chose to focus on producing HTML (I think this is a mistake.) This one uses named parameters for attributes, and unamed parameters as content. It’s also much older as the oldest entry is from some time in 2000, and it’s clear that it was around for some time before that entry (although they jokingly claim written history, heh). However, I had never heard of XIST until today. I also can’t find changesets or any history files to determine how long py.xml has been around, so I’ll assume it’s recent.

While these packages are capable of producing HTML, and the people authoring HTML could use it, I think it’s clear that the approach hasn’t worked. I think the authors of these libraries should start focusing on helping developers use them to produce XML, then tackle the problem of producing HTML separately. My guess is that the most common authors of HTML are graphic designers. I know some graphic designers who would be able to use this approach, but I also know several graphic designers, and probably even several programmers, who would not be able to use this approach. Too much overhead, and too many layers of indirection make it difficult to use.

In the spirit of the web, instead of attempting to unify or divide the files and code website authors share, let’s divide the URIs we share. One set of URIs for web developers to emit and consume XML, and another set of URIs for web designers to emit HTML, and consume the actions of humans. The two sets of URIs can talk amongst themselves by passing messages… over the web. This approach is more scalable. To even further separate the business logic of an application from presentation of the user experience (or web experience), you can have the web experience instruct the user (using normal HTML) to submit their forms and other interactiosn with side-effects directly to the developer’s set of URIs (perhaps call the web-app backplane?). Then when the web application has finished processing state and interaction, it can redirect the user back to the web experience, where they are given a nice human-consumable web page. This can also reduce accidental replays. It also allows designers and developers to work together without stepping on each others toes. It’s easier to test. It’s scalable.

P.S. any one know how to get decent looking code blocks in wordpress?

One Comment

  1. Posted July 21, 2008 at 8:19 pm | Permalink

    Cool post. The earliest version of the Nevow implementation of stan is on the web here:

    http://soundfarmer.com/content/code/nevow/0.0.1/nevow.py

    The timestamp on this version is October 17, 2003, which is close to the time that I did the Nevow rewrite of Woven. There was an earlier version of stan written by myself, Bob Ippolito, and David Abrahams at PyCon 2003 (in March) but I don’t think it made it onto the web anywhere.

    The Nevow version of stan is overly complicated; if I did it again today I’m sure it would be a lot simpler. The main advantage of it is that it supports Deferreds, which obviously is only important for people that are using Twisted.

    I did a rewrite of stan without the nevow/twisted dependencies in 2005, which now lives on in my mulib project. It hasn’t seen much use; mostly what I’ve tried to do with this version is simplify it as much as possible to try to find it’s core essence:

    http://donovanpreston.com:8888/mulib/file/4cf798eb0fee/mulib/stan.py

    I’m glad breve exists, and someday I should check it out more deeply to try to understand what it brings to the concept. However I haven’t done any front-end web development in years, so I’m a bit out of touch with new concepts that people have brought to the table.

    I’m pretty sure I had seen XIST and was influenced by it. I was also very heavily influenced by Zope’s TAL/TALES/ZPT early on, which is why most of my templating designs involve an intermediate DOM representation step of some kind, which I see as essential for maximum flexibility from the Python side. I was also influenced by the short-lived lmx concept from twisted’s microdom:

    http://twistedmatrix.com/trac/changeset/4542

    Finally, I totally agree with your last paragraph (before the P.S.). I have been trying to write all my web apps in that fashion recently (although that hasn’t been many apps) and Mulib is designed to be used in that fashion, with content-type negotiation and pluggable adapters for going from raw python types to xml, json, etc. You should do a full blog post on this topic, would be interesting.


Post a Comment

Required fields are marked *
*
*