Est. 2004 Intermediate

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)

Paradigm Declarative: attribute-based XML template language with embedded Python
Typing Dynamic (embedded Python expressions evaluated at render time)
First Appeared 2004
Latest Version Kid 0.9.6 (July 2007)

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:

SourceWhat Kid keptWhat Kid rejected
TAL (Zope Page Templates)An attribute-only syntax that latches onto existing markup; survival of round-trips through editing toolsTALES’s multiple expression types (Tomayko wanted plain Python expressions); METAL, which he found “overly complex”
XSLTMatch-based templating (rewriting elements by name, i.e. custom tags); attribute value interpolationVerbosity 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’sPTL’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:omit and the <?kid?> code block.
  • 0.2 (1 December 2004): the “initial public release”, adding docs, a distutils installer, the kidc compiler and the kid runner.
  • 0.3 (21 December 2004): the parser moved from SAX to Fredrik Lundh’s ElementTree, the document() and XML() 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 the Template class with its serialize(), generate(), write() and pull() methods.
  • 0.5 (26 January 2005): changed the prefix to py: and the instruction to <?python?>, added py: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 from http://naeblis.cx/ns/kid# to the persistent http://purl.org/kid/ns#, py:omit became py: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:

VersionPyPI uploadHighlights (from the release notes)
0.927 Feb 2006Layout templates (py:layout), defined()/value_of(), invisible <!--! --> comments, Windows launchers
0.9.121 Apr 2006Layout and py:match fixes; dynamically chosen layouts
0.9.217 Jun 2006Support for Python 2.5’s xml.etree; load_template(ns=...)
0.9.321 Jul 2006Links moved to kid-templating.org; bug fixes
0.9.426 Nov 2006Format output-control class, lowercase HTML serializer, rewritten import hooks for Python 2.5 and eggs; Python older than 2.3 dropped
0.9.527 Jan 2007Errors traced back to the original .kid file; ElementTree dependency removed; automatic recompilation
0.9.616 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 .pyc file next to the source. After kid.enable_import(), import mytemplate loads mytemplate.kid directly. Each compiled module exposes a Template class.
  • 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

AttributePurpose
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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?python
title = "A Kid Test Document"
fruits = ["apple", "orange", "kiwi", "M&M"]
from platform import system
?>
<html xmlns:py="http://purl.org/kid/ns#">
  <head>
    <title py:content="title">This is replaced.</title>
  </head>
  <body>
    <p>These are some of my favorite fruits:</p>
    <ul>
      <li py:for="fruit in fruits">
        I like ${fruit}s
      </li>
    </ul>
    <p py:if="system() == 'Linux'">
      Good for you!
    </p>
  </body>
</html>

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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?python
from time import localtime
def timeofday():
    """Get time of day ('am' or 'pm')"""
    return localtime().tm_hour < 12 and 'am' or 'pm'
?>
<html xmlns:py="http://purl.org/kid/ns#">
  <span py:match="item.tag == 'greeting'"
        py:replace="item.get(timeofday())">
  </span>
  <body>
    <p>Good <greeting am="Morning!" pm="Afternoon" /></p>
  </body>
</html>

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

1
2
3
4
5
<ul py:def="display_list(seq)">
  <li py:for="item in seq" py:content="item" />
</ul>

${display_list(['apple', 'orange', 'kiwi'])}

Python interface

1
2
3
4
from kid import Template

template = Template(file='test.kid', foo='bar', baz='bling')
print template.serialize(output='xhtml-strict')

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

2004
29 November: Kid 0.1, which according to its HISTORY file supports only kid:content, kid:if, kid:repeat, kid:omit and the <?kid?> code block
2004
29 November: Tomayko announces Kid on his weblog in the post 'In search of a Pythonic, XML-based Templating Language'
2004
1 December: Kid 0.2, the first public release, adds documentation, distutils installation, and the kid and kidc command-line tools
2004
21 December: Kid 0.3 moves from the GPL to an MIT licence and rewrites the parser on top of Fredrik Lundh's ElementTree; kid:repeat is renamed kid:for
2005
26 January: Kid 0.5 switches the attribute prefix from kid: to py: and the code-block instruction from <?kid?> to <?python?>
2005
5 March: Kid 0.6 introduces the ${expr} substitution syntax, the http://purl.org/kid/ns# namespace, template inheritance with py:extends, and match templates with py:match
2005
End of September: Kevin Dangoor releases TurboGears as open source, with Kid as its template layer
2006
27 February: Kid 0.9 is uploaded to PyPI, adding layout templates (py:layout)
2006
Edgewall Software publishes Genshi, an XML template engine whose FAQ calls it 'heavily inspired by Kid'
2007
16 July: Kid 0.9.6, the final release, is uploaded to PyPI
2009
October: TurboGears 1.1 is released, the version in which Genshi replaces Kid as the default template engine

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.

Language Influence

Influenced By

XSLT TAL PHP PTL

Influenced

Genshi

Running Today

Run examples using the official Docker image:

docker pull
Last updated: