Kid
Ryan Tomayko's attribute-based XML template language for Python, which compiled well-formed XML templates into importable Python modules and served as TurboGears 1.0's view layer.
Created by Ryan Tomayko (later maintained by David Stanek and Christoph Zwerschke)
Kid is a template language for Python that generates and transforms XML vocabularies, usually XHTML. A Kid template is a well-formed XML document. Ordinary markup is annotated with attributes in a py: namespace (py:for, py:if, py:content, py:match and others), and Python code sits inside <?python ?> processing instructions. Because the template stays valid XML, it can be opened in an editor or browser to check the design, and it also fits into ordinary XML toolchains. Kid compiled each template into a native Python module, which could be imported like any other .py file. Ryan Tomayko wrote it in late 2004. During 2005-2006 it became the default view layer of the TurboGears web framework. Edgewall’s Genshi, which was designed as its successor, then displaced it.
Kid’s own README summed up its ancestry: it “was spawned as a result of a kinky love triangle between XSLT, TAL, and PHP”.
History & Origins
“In search of a Pythonic, XML-based Templating Language”
Tomayko announced Kid on his weblog (naeblis.cx) in a post dated 29 November 2004 in his archive, the same day as release 0.1 in Kid’s HISTORY file. He had used Zope’s TAL, through the SimpleTAL implementation, but had become dissatisfied with it. He then spent a week surveying the alternatives and decided to “just build the XML template language I really wanted”. The post explains the problem in one line, later quoted in Genshi’s FAQ:
“There’s at least four billion and nine text based template languages for Python but there aren’t a lot of options that fit nicely into the XML tool-chain. Or, if they do fit nicely into the XML tool-chain, they don’t fit nicely with Python.”
The post then goes through the options and says what Kid would keep from each:
| Source | What Kid kept | What Kid rejected |
|---|---|---|
| TAL (Zope Page Templates) | An attribute-only syntax that latches onto existing markup; survival of round-trips through editing tools | TALES’s multiple expression types (Tomayko wanted plain Python expressions); METAL, which he found “overly complex” |
| XSLT | Match-based templating (rewriting elements by name, i.e. custom tags); attribute value interpolation | Verbosity and “silly complex” simple cases |
| PTL (Quixote’s Python Template Language) | Compiling templates down to native Python modules that can be imported; Kid’s import hooks were adapted from Quixote’s | PTL’s text-based model |
| PXTL | — | Judged thorough but too large to learn quickly |
Early releases
Tomayko recorded the release history in Kid’s HISTORY file:
- 0.1 (29 November 2004): “Barely useful. No documentation.” It supported
kid:content,kid:if,kid:repeat,kid:omitand the<?kid?>code block. - 0.2 (1 December 2004): the “initial public release”, adding docs, a
distutilsinstaller, thekidccompiler and thekidrunner. - 0.3 (21 December 2004): the parser moved from SAX to Fredrik Lundh’s ElementTree, the
document()andXML()functions arrived, and the licence changed from the GPL to MIT. One reason given was compatibility with the Quixote-derived import hook code. - 0.4 (10 January 2005): introduced
kid:def, which works like a Python function inside a template, and theTemplateclass with itsserialize(),generate(),write()andpull()methods. - 0.5 (26 January 2005): changed the prefix to
py:and the instruction to<?python?>, addedpy:attrs(contributed by Christoph Zwerschke), and allowed brace interpolation in text content. - 0.6 (5 March 2005): a large redesign. Substitution became
${expr}/$name, the namespace moved fromhttp://naeblis.cx/ns/kid#to the persistenthttp://purl.org/kid/ns#,py:omitbecamepy:strip, and template inheritance (py:extends), match templates (py:match) and cElementTree support were added. Custom HTML and XHTML serializers followed in 0.6.2 (9 March 2005).
Archived directory listings from the project’s download area on lesscode.org reportedly date 0.6.4 to June 2005, 0.7a to 4 July 2005, 0.7.1 to 10 November 2005 and 0.8 to early December 2005.
TurboGears and the 0.9 series
Kevin Dangoor released TurboGears as open source at the end of September 2005. It bundled CherryPy, SQLObject, MochiKit and Kid, and that put Kid in front of many more Python web developers. Development then passed from Tomayko to other contributors. The 0.9.6 README credits Tomayko as “Original author of the Kid project”, David Stanek as “current project maintainer”, Christoph Zwerschke for coding and Ross Burton as Debian package maintainer. The project site moved from lesscode.org to kid-templating.org, which ran a Trac wiki and ticket tracker. The 0.9.3 release notes record the switch of links.
The 0.9 releases were all published on PyPI:
| Version | PyPI upload | Highlights (from the release notes) |
|---|---|---|
| 0.9 | 27 Feb 2006 | Layout templates (py:layout), defined()/value_of(), invisible <!--! --> comments, Windows launchers |
| 0.9.1 | 21 Apr 2006 | Layout and py:match fixes; dynamically chosen layouts |
| 0.9.2 | 17 Jun 2006 | Support for Python 2.5’s xml.etree; load_template(ns=...) |
| 0.9.3 | 21 Jul 2006 | Links moved to kid-templating.org; bug fixes |
| 0.9.4 | 26 Nov 2006 | Format output-control class, lowercase HTML serializer, rewritten import hooks for Python 2.5 and eggs; Python older than 2.3 dropped |
| 0.9.5 | 27 Jan 2007 | Errors traced back to the original .kid file; ElementTree dependency removed; automatic recompilation |
| 0.9.6 | 16 Jul 2007 | 'straight' format; a fix for TurboKid filter lists growing endlessly |
0.9.6 was the last release. Its PyPI classifier still read “Development Status :: 4 - Beta”.
Design Philosophy
- Templates are XML. A Kid template must be well-formed. Directives are attributes and processing instructions, so the template is still the document it describes and can be validated, previewed and edited with XML tools.
- Python is the expression language. Unlike TAL’s TALES, with its separate path, string and Python expression types, every Kid expression is Python. Code blocks are plain Python inside
<?python ?>. - Templates are Python modules. A template compiles to a Python module, and on import it is cached as a
.pycfile next to the source. Afterkid.enable_import(),import mytemplateloadsmytemplate.kiddirectly. Each compiled module exposes aTemplateclass. - Streaming output. The template runs as a generator of ElementTree-style events, which go through match-template filters and then a serializer. The language specification says the whole tree is never fully kept in memory during normal expansion, and that is why match expressions can only see an element’s tag and attributes.
Key Features
The py: attributes
| Attribute | Purpose |
|---|---|
py:for="x in seq" | Repeat the element for each item |
py:if="expr" | Output the element only when expr is true |
py:content="expr" | Replace the element’s children with expr |
py:replace="expr" | Replace the whole element with expr |
py:strip="expr" | Drop the element’s start and end tags but keep its children |
py:attrs="name=value, ..." | Set or override attributes |
py:def="name(args)" | Define a named template function |
py:match="expr" | Define a match template (an XSLT-style element rewrite) |
py:extends="'base.kid'" | Inherit functions and match templates from another template |
py:layout="'layout.kid'" | Apply this template’s content to a layout template (added in 0.9) |
The specification fixes the processing order when several attributes are on one element: py:def, py:match, py:for, py:if, py:replace, py:strip, py:attrs, py:content. Attribute value interpolation runs after all of them.
A basic template
This is the synopsis from the Kid Language Specification:
| |
Match templates: custom tags
py:match gives Kid an equivalent of XSLT’s <xsl:template match=...>. The specification’s example defines a <greeting> tag whose output depends on the time of day:
| |
The matched element is available as item. The specification warns that when a default namespace is declared, tags appear in Clark notation, e.g. item.tag == '{http://www.w3.org/1999/xhtml}body'.
Named template functions
| |
Python interface
| |
Templates can also be built from a string (Template(source='<p>$foo</p>', foo='Hello World!')). Output can be streamed with generate() or written with write(). Serializers cover XML, XHTML and HTML, and 0.9.4 added HTML variants for Mozilla’s standards, almost-standards and quirks rendering modes. The kidc command precompiles templates to .pyc, and kid runs a template from the command line.
Evolution and Decline
Kid’s main structural choices were code generation and ElementTree, and they caused its best-known weakness: error reporting. Genshi’s FAQ, written by the developers who replaced it, credits Kid with “a huge step forward for XML-based templating in Python”, praising match templates and the generator-based processing model. It then sets out the problem. A syntax error in a template expression raised an exception that pointed into the generated Python code, and ElementTree did not supply source locations for parse events. The Genshi team concluded that a new engine would be better than trying to fix Kid. Kid 0.9.5 did start tracing errors back to the original template file, but by then Genshi was available.
Genshi, from Edgewall Software (the makers of Trac), appeared in 2006. It kept Kid’s py: attribute vocabulary, which Wikipedia’s TurboGears article describes as nearly 100% syntax-compatible. Instead of generating Python, though, it interpreted templates as a stream of events. It used XInclude instead of py:extends, XPath for match templates, and added directives such as py:choose. TurboGears planned Genshi as the default for 1.1 and shipped that release in October 2009. For TurboGears 2.x, Wikipedia’s TurboGears article says Kid support is not planned because Genshi is virtually identical.
Kid’s last release was 0.9.6 in July 2007. Its README lists Python 2.3, 2.4 and 2.5 as tested on Linux, Windows XP and Mac OS X. It never moved to Python 3.
Current Relevance
Kid is historical. Nobody develops it, the kid-templating.org site survives only in web archives, and the code is Python 2 only. Its source distributions are still on PyPI, and some Linux distributions packaged it into the 2010s; Ubuntu 14.04, for example, shipped python-kid 0.9.6. Dependents such as repoview and legacy TurboGears 1.x applications were the likely reason it was kept.
The ideas lasted longer than the code. The py: attribute style, ${} interpolation and match templates continued in Genshi, which remained TurboGears’ default template engine for many years.
Why It Matters
Kid filled a specific gap in mid-2000s Python. There were many text-substitution template engines, and XML-native engines that were awkward to use from Python. Kid combined TAL’s attribute-on-markup approach, XSLT’s match-and-rewrite templates and Quixote’s idea of templates as importable Python modules, in a language small enough to learn from one specification. Through TurboGears it was, for a few years, arguably one of the most widely used XML template languages in Python. Its limits, mainly code generation and poor error locations, informed the design of Genshi, which kept Kid’s syntax and replaced its architecture.
Timeline
Notable Uses & Legacy
TurboGears 1.x
Kevin Dangoor's Python web 'megaframework' used Kid as its view layer alongside CherryPy, SQLObject and MochiKit. A TurboKid plugin connected the two, and Kid's 0.9.x release notes record fixes reported on the TurboGears mailing list.
Repoview (Fedora / Yum repositories)
The repoview utility generates static HTML browsing pages for Yum package repositories from Kid templates. Its man page requires a template directory containing index.kid, group.kid, package.kid and rss.kid.
Apache Software Foundation XDOK
XDOK, a site-generation tool in the ASF infrastructure Subversion tree, describes itself as a 'CLI tool for transforming trees of files using the Kid template language'. It ships Kid 0.8 and ElementTree in its lib directory, with a site.kid.html master template. Its own WARNING.txt later called it abandonware and recommended Anakia instead, so this was a small, short-lived use.