Cheetah Users' Guide

Edited by Mike Orr and Tavis Rudd


Contents

©Copyright 2001-2005, The Cheetah Development Team. This document may be copied and modified under the terms of the Open Publication License http://www.opencontent.org/openpub/


1 Introduction


1.1 Who should read this Guide?

This Users' Guide provides a technical overview and reference for the Cheetah template system. Knowledge of Python and object-oriented programming is assumed. The emphasis in this Guide is on features useful in a wide variety of situations. Information on less common situations and troubleshooting tips are gradually being moved to the Cheetah FAQ. There is also a Cheetah Developer's Guide for those who want to know what goes on under the hood.

This Guide also contains examples of integrating Cheetah with Webware for Python. You will have to learn Webware from its own documentation in order to build a Webware + Cheetah site.


1.2 What is Cheetah?

Cheetah is a Python-powered template engine and code generator. It may be used as a standalone utility or combined with other tools. Cheetah has many potential uses, but web developers looking for a viable alternative to ASP, JSP, PHP and PSP are expected to be its principle user group.

Cheetah:

Cheetah integrates tightly with Webware for Python (http://webware.sourceforge.net/): a Python-powered application server and persistent servlet framework. Webware provides automatic session, cookie, and user management and can be used with almost any operating-system, web server, or database. Through Python, it works with XML, SOAP, XML-RPC, CORBA, COM, DCOM, LDAP, IMAP, POP3, FTP, SSL, etc.. Python supports structured exception handling, threading, object serialization, unicode, string internationalization, advanced cryptography and more. It can also be extended with code and libraries written in C, C++, Java and other languages.

Like Python, Cheetah and Webware are Open Source software and are supported by active user communities. Together, they are a powerful and elegant framework for building dynamic web sites.

Like its namesake, Cheetah is fast, flexible and powerful.


1.3 What is the philosophy behind Cheetah?

Cheetah's design was guided by these principles:


1.3.1 Why Cheetah doesn't use HTML-style tags

Cheetah does not use HTML/XML-style tags like some other template languages for the following reasons: Cheetah is not limited to HTML, HTML-style tags are hard to distinguish from real HTML tags, HTML-style tags are not visible in rendered HTML when something goes wrong, HTML-style tags often lead to invalid HTML (e.g., <img src="<template-directive>">), Cheetah tags are less verbose and easier to understand than HTML-style tags, and HTML-style tags aren't compatible with most WYSIWYG editors

Besides being much more compact, Cheetah also has some advantages over languages that put information inside the HTML tags, such as Zope Page Templates or PHP: HTML or XML-bound languages do not work well with other languages, While ZPT-like syntaxes work well in many ways with WYSIWYG HTML editors, they also give up a significant advantage of those editors - concrete editing of the document. When logic is hidden away in (largely inaccessible) tags it is hard to understand a page simply by viewing it, and it is hard to confirm or modify that logic.


1.4 Give me an example!

Here's a very simple example that illustrates some of Cheetah's basic syntax:

<HTML>
<HEAD><TITLE>$title</TITLE></HEAD>
<BODY>

<TABLE>
#for $client in $clients
<TR>
<TD>$client.surname, $client.firstname</TD>
<TD><A HREF="mailto:$client.email">$client.email</A></TD>
</TR>
#end for
</TABLE>

</BODY>
</HTML>

Compare this with PSP:

<HTML>
<HEAD><TITLE><%=title%></TITLE></HEAD>
<BODY>

<TABLE>
<% for client in clients: %>
<TR>
<TD><%=client['surname']%>, <%=client['firstname']%></TD>
<TD><A HREF="mailto:<%=client['email']%>"><%=client['email']%></A></TD>
</TR>
<%end%>
</TABLE>

</BODY>
</HTML>

Section 3.7 has a more typical example that shows how to get the plug-in values into Cheetah, and section 4.2 explains how to turn your template definition into an object-oriented Python module.


1.5 Give me an example of a Webware servlet!

This example uses an HTML form to ask the user's name, then invokes itself again to display a personalized friendly greeting.

<HTML><HEAD><TITLE>My Template-Servlet</TITLE></HEAD><BODY>   
#set $name = $request.field('name', None)
#if $name  
Hello $name
#else
<FORM ACTION="" METHOD="GET">
Name: <INPUT TYPE="text" NAME="name"><BR>
<INPUT TYPE="submit">
</FORM>
#end if
</BODY></HTML>

To try it out for yourself on a Webware system:

  1. copy the template definition to a file test.tmpl in your Webware servlet directory.
  2. Run ``cheetah compile test.tmpl''. This produces test.py (a .py template module) in the same directory.
  3. In your web browser, go to test.py, using whatever site and directory is appropriate. Depending on your Webware configuration, you may also be able to go to test.

At the first request, field `name' will be blank (false) so the ``#else'' portion will execute and present a form. You type your name and press submit. The form invokes the same page. Now `name' is true so the ``#if'' portion executes, which displays the greeting. The ``#set'' directive creates a local variable that lasts while the template is being filled.


1.6 How mature is Cheetah?

Cheetah is stable, production quality, post-beta code. Cheetah's syntax, semantics and performance have been generally stable since a performance overhaul in mid 2001. Most of the changes since October 2001 have been in response to specific requests by production sites, things they need that we hadn't considered.

As of summer 2003, we are putting in the final touches before the 1.0 release.

The TODO and BUGS files in the Cheetah distribution show what we're working on now or planning to work on. There's also a ToDo page on the wiki (see below), which is updated less often. The WishList page on the wiki shows requested features we're considering but haven't commited to.


1.7 Where can I get news?

Cheetah releases and other stuff can be obtained from the the Cheetah Web site: http://CheetahTemplate.sourceforge.net

Cheetah discussions take place on the mailing list cheetahtemplate-discuss@lists.sourceforge.net. This is where to hear the latest news first.

The Cheetah wiki is becoming an increasingly popular place to list examples of Cheetah in use, provide cookbook tips for solving various problems, and brainstorm ideas for future versions of Cheetah. http://www.cheetahtemplate.org/wiki(The wiki is actually hosted at http://cheetah.colorstudy.net/twiki/bin/view/Cheetah/WebHome, but the other URL is easier to remember.) For those unfamiliar with a wiki, it's a type of Web site that readers can edit themselves to make additions or corrections to. Try it. Examples and tips from the wiki will also be considered for inclusion in future versions of this Users' Guide.

If you encounter difficulties, or are unsure about how to do something, please post a detailed message to the list.


1.8 How can I contribute?

Cheetah is the work of many volunteers. If you use Cheetah please share your experiences, tricks, customizations, and frustrations.

1.8.1 Bug reports and patches

If you think there is a bug in Cheetah, send a message to the e-mail list with the following information:

  1. a description of what you were trying to do and what happened
  2. all tracebacks and error output
  3. your version of Cheetah
  4. your version of Python
  5. your operating system
  6. whether you have changed anything in the Cheetah installation

1.8.2 Example sites and tutorials

If you're developing a website with Cheetah, please put a link on the wiki on the WhoIsUsingCheetah page, and mention it on the list. Also, if you discover new and interesting ways to use Cheetah, please put a quick tutorial (HOWTO) about your technique on the CheetahRecipies page on the wiki.

1.8.3 Template libraries and function libraries

We hope to build up a framework of Template libraries (see section 17.5) to distribute with Cheetah and would appreciate any contributions.

1.8.4 Test cases

Cheetah is packaged with a regression testing suite that is run with each new release to ensure that everything is working as expected and that recent changes haven't broken anything. The test cases are in the Cheetah.Tests module. If you find a reproduceable bug please consider writing a test case that will pass only when the bug is fixed. Send any new test cases to the email list with the subject-line ``new test case for Cheetah.''

1.8.5 Publicity

Help spread the word ... recommend it to others, write articles about it, etc.


1.9 Acknowledgements

Cheetah is one of several templating frameworks that grew out of a `templates' thread on the Webware For Python email list. Tavis Rudd, Mike Orr, Chuck Esterbrook and Ian Bicking are the core developers.

We'd like to thank the following people for contributing valuable advice, code and encouragement: Geoff Talvola, Jeff Johnson, Graham Dumpleton, Clark C. Evans, Craig Kattner, Franz Geiger, Geir Magnusson, Tom Schwaller, Rober Kuzelj, Jay Love, Terrel Shumway, Sasa Zivkov, Arkaitz Bitorika, Jeremiah Bellomy, Baruch Even, Paul Boddie, Stephan Diehl, Chui Tey, Michael Halle, Edmund Lian and Aaron Held.

The Velocity, WebMacro and Smarty projects provided inspiration and design ideas. Cheetah has benefitted from the creativity and energy of their developers. Thank you.


1.10 License

The gist

Cheetah is open source, but products developed with Cheetah or derived from Cheetah may be open source or closed source.

Cheetah.Utils.optik is based on a third-party package Optik by Gregory P Ward. Optik's license is in appendix D.

Legal terms

Copyright ©2001, The Cheetah Development Team: Tavis Rudd, Mike Orr, Ian Bicking, Chuck Esterbrook.

Permission to use, copy, modify, and distribute this software for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of the authors not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.

THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

These terms do not apply to the Cheetah.Utils.optik package. Optik's license is in appendix D.


2 Vocabulary

Template is an informal term meaning a template definition, a template instance or a template class. A template definition is what the human template maintainer writes: a string consisting of text, placeholders and directives. Placeholders are variables that will be looked up when the template is filled. Directives are commands to be executed when the template is filled, or instructions to the Cheetah compiler. The conventional suffix for a file containing a template definition is .tmpl.

There are two things you can do with a template: compile it or fill it. Filling is the reason you have a template in the first place: to get a finished string out of it. Compiling is a necessary prerequisite: the Cheetah compiler takes a template definition and produces Python code to create the finished string. Cheetah provides several ways to compile and fill templates, either as one step or two.

Cheetah's compiler produces a subclass of Cheetah.Template specific to that template definition; this is called the generated class. A template instance is an instance of a generated class.

If the user calls the Template constructor directly (rather than a subclass constructor), s/he will get what appears to be an instance of Template but is actually a subclass created on-the-fly.

The user can make the subclass explicit by using the ``cheetah compile'' command to write the template class to a Python module. Such a module is called a .py template module.

The Template Definition Language - or the ``Cheetah language'' for short - is the syntax rules governing placeholders and directives. These are discussed in sections 5 and following in this Guide.

To fill a template, you call its main method. This is normally .respond(), but it may be something else, and you can use the #implements directive to choose the method name. (Section 8.3.

A template-servlet is a .py template module in a Webware servlet directory. Such templates can be filled directly through the web by requesting the URL. ``Template-servlet'' can also refer to the instance being filled by a particular web request. If a Webware servlet that is not a template-servlet invokes a template, that template is not a template-servlet either.

A placeholder tag is the substring in the template definition that is the placeholder, including the start and end delimeters (if there is an end delimeter). The placeholder name is the same but without the delimeters.

Placeholders consist of one or more identifiers separated by periods (e.g., a.b). Each identifier must follow the same rules as Python identifiers; that is, a letter or underscore followed by one or more letters, digits or underscores. (This is the regular expression [A-Za-z_][A-Za-z0-9_]*.)

The first (or only) identifier of a placeholder name represents a variable to be looked up. Cheetah looks up variables in various namespaces: the searchList, local variables, and certain other places. The searchList is a list of objects (containers) with attributes and/or keys: each container is a namespace. Every template instance has exactly one searchList. Identifiers after the first are looked up only in the parent object. The final value after all lookups have been performed is the placeholder value.

Placeholders may occur in three positions: top-level, expression and LVALUE. Top-level placeholders are those in ordinary text (``top-level text''). Expression placeholders are those in Python expressions. LVALUE placeholders are those naming a variable to receive a value. (LVALUE is computerese for ``the left side of the equal sign''.) Section 5.3 explains the differences between these three positions.

The routine that does the placeholder lookups is called the NameMapper. Cheetah's NameMapper supports universal dotted notation and autocalling. Universal dotted notation means that keys may be written as if they were attributes: a.b instead of a['b']. Autocalling means that if any identifier's value is found to be a function or method, Cheetah will call it without arguments if there is no () following. More about the NameMapper is in section 5.5.

Some directives are multi-line, meaning they have a matching #end tag. The lines of text between the start and end tags is the body of the directive. Arguments on the same line as the start tag, in contrast, are considered part of the directive tag. More details are in section 5.8 (Directive Syntax Rules).


3 Getting Started


3.1 Requirements

Cheetah requires Python release 2.0 or greater, and has been tested with Python 2.0, 2.1 and 2.2. It is known to run on Linux, Windows NT/98/XP, FreeBSD and Solaris, and should run anywhere Python runs.

99% of Cheetah is written in Python. There is one small C module (_namemapper.so) for speed, but Cheetah automatically falls back to a Python equivalent (NameMapper.py) if the C module is not available.


3.2 Installation

To install Cheetah in your system-wide Python library:

  1. Login as a user with privileges to install system-wide Python packages. On POSIX systems (AIX, Solaris, Linux, IRIX, etc.), the command is normally 'su root'. On non-POSIX systems such as Windows NT, login as an administrator.

  2. Run python setup.py install at the command prompt.

  3. The setup program will install the wrapper script cheetah to wherever it usually puts Python binaries ("/usr/bin/", "bin/" in the Python install directory, etc.)

Cheetah's installation is managed by Python's Distribution Utilities ('distutils'). There are many options for customization. Type ``python setup.py help'' for more information.

To install Cheetah in an alternate location - someplace outside Python's site-packages/ directory, use one of these options:

    python setup.py install --home /home/tavis 
    python setup.py install --install-lib /home/tavis/lib/python
Either way installs to /home/tavis/lib/python/Cheetah/ . Of course, /home/tavis/lib/python must be in your Python path in order for Python to find Cheetah.


3.3 Files

If you do the systemwide install, all Cheetah modules are installed in the site-packages/Cheetah/ subdirectory of your standard library directory; e.g., /opt/Python2.2/lib/python2.2/site-packages/Cheetah.

Two commands are installed in Python's bin/ directory or a system bin directory: cheetah (section 3.5) and cheetah-compile (section 4.2).


3.4 Uninstalling

To uninstall Cheetah, merely delete the site-packages/Cheetah/ directory. Then delete the ``cheetah'' and ``cheetah-compile'' commands from whichever bin/ directory they were put in.


3.5 The 'cheetah' command

Cheetah comes with a utility cheetah that provides a command-line interface to various housekeeping tasks. The command's first argument is the name of the task. The following commands are currently supported:

cheetah compile [options] [FILES ...]     : Compile template definitions
cheetah fill [options] [FILES ...]        : Fill template definitions
cheetah help                              : Print this help message
cheetah options                           : Print options help message
cheetah test                              : Run Cheetah's regression tests
cheetah version                           : Print Cheetah version number

You only have to type the first letter of the command: cheetah c is the same as cheetah compile.

The test suite is described in the next section. The compile command will be described in section 4.2, and the fill command in section 4.3.

The depreciated cheetah-compile program does the same thing as cheetah compile.


3.6 Testing your installation

After installing Cheetah, you can run its self-test routine to verify it's working properly on your system. Change directory to any directory you have write permission in (the tests write temporary files). Do not run the tests in the directory you installed Cheetah from, or you'll get unnecessary errors. Type the following at the command prompt:

cheetah test

The tests will run for about three minutes and print a success/failure message. If the tests pass, start Python in interactive mode and try the example in the next section.

Certain test failures are insignificant:

AssertionError: Template output mismatch: Expected Output = 0(end) Actual Output = False(end) Python 2.3 changed the string representation of booleans, and the tests haven't yet been updated to reflect this.
AssertionError: subcommand exit status 127 Certain tests run ``cheetah'' as a subcommand. The failure may mean the command wasn't found in your system path. (What happens if you run ``cheetah'' on the command line?) The failure also happens on some Windows systems for unknown reasons. This failure has never been observed outside the test suite. Long term, we plan to rewrite the tests to do a function call rather than a subcommand, which will also make the tests run significantly faster.
ImportError: No module named SampleBaseClass The test tried to write a temporary module in the current directory and import it. Reread the first paragraph in this section about the current directory.
ImportError: No module named tmp May be the same problem as SampleBaseClass; let us know if changing the current directory doesn't work.

If any other tests fail, please send a message to the e-mail list with a copy of the test output and the following details about your installation:

  1. your version of Cheetah
  2. your version of Python
  3. your operating system
  4. whether you have changed anything in the Cheetah installation


3.7 Quickstart tutorial

This tutorial briefly introduces how to use Cheetah from the Python prompt. The following chapters will discuss other ways to use templates and more of Cheetah's features.

The core of Cheetah is the Template class in the Cheetah.Template module. The following example shows how to use the Template class in an interactive Python session. t is the Template instance. Lines prefixed with »> and ... are user input. The remaining lines are Python output.

>>> from Cheetah.Template import Template
>>> templateDef = """
... <HTML>
... <HEAD><TITLE>$title</TITLE></HEAD>
... <BODY>
... $contents
... ## this is a single-line Cheetah comment and won't appear in the output
... #* This is a multi-line comment and won't appear in the output
...    blah, blah, blah 
... *#
... </BODY>
... </HTML>"""
>>> nameSpace = {'title': 'Hello World Example', 'contents': 'Hello World!'}
>>> t = Template(templateDef, searchList=[nameSpace])
>>> print t
 
<HTML>
<HEAD><TITLE>Hello World Example</TITLE></HEAD>
<BODY>
Hello World!
</BODY>
</HTML>
>>> print t    # print it as many times as you want
      [ ... same output as above ... ]
>>> nameSpace['title'] = 'Example #2'
>>> nameSpace['contents'] = 'Hiya Planet Earth!'
>>> print t   # Now with different plug-in values.
<HTML>
<HEAD><TITLE>Example #2</TITLE></HEAD>
<BODY>
Hiya Planet Earth!
</BODY>
</HTML>

Since Cheetah is extremely flexible, you can achieve the same result this way:

>>> t2 = Template(templateDef)
>>> t2.title = 'Hello World Example!'
>>> t2.contents = 'Hello World'
>>> print t2
      [ ... same output as the first example above ... ]
>>> t2.title = 'Example #2'
>>> t2.contents = 'Hello World!'
>>> print t2
     [ ... same as Example #2 above ... ]

Or this way:

>>> class Template3(Template):
>>>     title = 'Hello World Example!'
>>>     contents = 'Hello World!'
>>> t3 = Template3(templateDef)
>>> print t3
     [ ... you get the picture ... ]

The template definition can also come from a file instead of a string, as we will see in section 4.1.

The above is all fine for short templates, but for long templates or for an application that depends on many templates in a hierarchy, it's easier to store the templates in separate *.tmpl files and use the cheetah compile program to convert them into Python classes in their own modules. This will be covered in section 4.2.

As an appetizer, we'll just briefly mention that you can store constant values inside the template definition, and they will be converted to attributes in the generated class. You can also create methods the same way. You can even use inheritance to arrange your templates in a hierarchy, with more specific templates overriding certain parts of more general templates (e.g., a "page" template overriding a sidebar in a "section" template).

For the minimalists out there, here's a template definition, instantiation and filling all in one Python statement:

>>> print Template("Templates are pretty useless without placeholders.")
Templates are pretty useless without placeholders.

You use a precompiled template the same way, except you don't provide a template definition since it was already established:

from MyPrecompiledTemplate import MyPrecompiledTemplate
t = MyPrecompiledTemplate()
t.name = "Fred Flintstone"
t.city = "Bedrock City"
print t


4 How Cheetah Works

As mentioned before, you can do two things with templates: compile them and fill them. (Actually you can query them too, to see their attributes and method values.) Using templates in a Python program was shown in section 3.7 (Quickstart tutorial). Here we'll focus on compiling and filling templates from the shell command line, and how to make .py template modules. The compiling information here is also important for template-servlets, which will be otherwise covered in chapter 14 (Webware).


4.1 Constructing Template Objects

The heart of Cheetah is the Template class in the Cheetah.Template module. You can use it directly if you have a template definition in hand, or indirectly through a precompiled template, which is a subclass. The constructor accepts the following keyword arguments. (If you're a beginner, learn the first three arguments now; the others are much less frequent.)

source The template definition as a string. You may omit the source= prefix if it's the first argument, as in all the examples below. The source can be a string literal in your module, or perhaps a string you read from a database or other data structure.
file A filename or file object containing the template definition. A filename must be a string, and a file object must be open for reading. By convention, template definition files have the extension .tmpl.
searchList A list of objects to add to the searchList. The attributes/keys of these objects will be consulted for $placeholder lookup.
filter A class that will format every $placeholder value. You may specify a class object or string. If a class object, it must be a subclass of Cheetah.Filters.Filter. If a string, it must be the name of one of the filters in filtersLib module (see next item). (You may also use the #filter directive (section 7.9) to switch filters at runtime.)
filtersLib A module containing the filters Cheetah should look up by name. The default is Cheetah.Filters. All classes in this module that are subclasses of Cheetah.Filters.Filter are considered filters.
errorCatcher A class to handle $placeholder errors. You may specify a class object or string. If a class object, it must be a subclass of Cheetah.ErrorCatchers.ErrorCatcher. If a string, it must be the name of one of the error catchers in Cheetah.ErrorCatchers. This is similar to the #errorCatcher directive (section 10.2).
compilerSettings A dictionary (or dictionary hierarchy) of settings that change Cheetah's behavior. Not yet documented.

To use Template directly, you must specify either source or file, but not both. To use a precompiled template, you must not specify either one, because the template definition is already built into the class. The other arguments, however, may be used in either case. Here are typical ways to create a template instance:

t = Template("The king is a $placeholder1.")
Pass the template definition as a string.
t = Template(file="fink.tmpl")
Read the template definition from a file named "fink.tmpl".
t = Template(file=f)
Read the template definition from file-like object 'f'.
t = Template("The king is a $placeholder1.", searchList=[dict, obj])
Pass the template definition as a string. Also pass two namespaces for the searchList: a dictionary 'dict' and an instance 'obj'.
t = Template(file="fink.txt", searchList=[dict, obj])
Same, but pass a filename instead of a string.
t = Template(file=f, searchList=[dict, obj])
Same with a file object.

If you use Template directly, the template definition will be compiled the first time it's filled. Compilation creates a template-specific class called the generated class, which is a subclass of Template. It then dynamically switches the instance so it's now an instance of this class. Don't worry if you don't understand this; it works.

When you precompile a template using the ``cheetah compile'' command, it writes the generated class to a file. Actually, what it writes is the source code for a Python module that contains the generated class. Again, the generated class is a subclass of Template. We call the generated module a .py template module. Thus, if you always use precompiled templates (as many people do), you can view Cheetah as a convenient front-end for writing certain kinds of Python modules, the way you might use a graphical dialog builder to make a dialog module.

Precompiled templates provide a slight performance boost because the compilation happens only once rather than every time it's instantiated. Also, once you import the .py template module and allow Python to create a .pyc or .pyo file, you skip the Python compiler too. The speed advantage of all this is negligable, but it may make a difference in programs that use templates many times a second.

Template subclasses Webware's Servlet class when available, so the generated class can be used as a Webware servlet. This is practical only with precompiled templates.

To fill a template, you call its main method. This is normally .respond(), but under certain circumstances it's .writeBody() or a user-defined name. (Section 8.3 explains why the method name is not always the same.) However, .__str__() is always an alias for the main method, so you can always use print myTemplateInstance or str(myTempateInstance) to fill it. You can also call any #def or #block method and it will fill just that portion of the template, although this feature is not often used.


4.2 ``cheetah compile'' and .py template modules

To create a .py template module, do either of these:

cheetah compile [options] [FILES ...]
cheetah c [options] [FILES ...]

The following options are supported:

  --idir DIR, --odir DIR : input/output directories (default: current dir)
  --iext EXT, --oext EXT : input/output filename extensions
    (default input: tmpl,  default output:  py)
  -R : recurse subdirectories looking for input files
  --debug : print lots of diagnostic output to standard error
  --flat : no destination subdirectories
  --nobackup : don't make backups
  --stdout, -p : output to standard output (pipe)

Note: If Cheetah can't find your input files, or if it puts output files in the wrong place, use the --debug option to see what Cheetah thinks of your command line.

The most basic usage is:

cheetah compile a.tmpl           : writes a.py
cheetah compile a.tmpl b.tmpl    : writes a.py and b.py

Cheetah will automatically add the default input extension (.tmpl) if the file is not found. So the following two examples are the same as above (provided files ``a'' and ``b'' don't exist):

cheetah compile a                : writes a.py (from a.tmpl)
cheetah compile a b              : writes a.py and b.py

You can override the default input extension and output extension (py) using --iext and --oext, although there's little reason to do so. Cheetah assumes the extension has a leading dot (.) even if you don't specify it.

Use the -R option to recurse subdirectories:

cheetah compile dir1             : error, file is a directory
cheetah compile -R dir1          : look in `dir1' for files to compile
cheetah compile                  : error, no file specified
cheetah compile -R               : look in current directory for files
                                   to compile
cheetah compile -R a b dir1      : compile files and recurse
When recursing, only regular files that end in the input extension (.tmpl) are considered source files. All other filenames are ignored.

The options --idir and --odir allow you to specify that the source (and/or destination) paths are relative to a certain directory rather than to the current directory. This is useful if you keep your *.tmpl and *.py files in separate directory hierarchies. After editing a source file, just run one of these (or put the command in a script or Makefile):

cheetah compile --odir /var/webware a.tmpl
cheetah compile -R --odir /var/webware
cheetah c --odir /var/webware sub/a.tmpl
                                 : writes /var/webware/sub/a.py

``cheetah compile'' overwrites any existing .py file it finds, after backing it up to FILENAME.py_bak (unless you specify --nobackup). For this reason, you should make changes to the .tmpl version of the template rather than to the .py version.

For the same reason, if your template requires custom Python methods or other Python code, don't put it in the FILENAME.py file. Instead, put it in a separate base class and use the #extends directive to inherit from it.

Because FILENAME will be used as a class and module name, it must be a valid Python identifier. For instance, cheetah compile spam-eggs.tmpl is illegal because of the hyphen ("-"). This is sometimes inconvenient when converting a site of HTML files into Webware servlets. Fortunately, the directory it's in does not have to be an identifier. (Hint: for date-specific files, try converting 2002/04/12.html to 2002/04/12/index.tmpl. This also gives you a directory to store images or supplemental files.)

Occasionally you may want output files put directly into the output directory (or current directory), rather than into a subdirectory parallel to the input file. The --flat option does this. Note that this introduces the possibility that several input files might map to one output file. Cheetah checks for output file collisions before writing any files, and aborts if there are any collisions.

cheetah c sub/a.py            : writes sub/a.py
cheetah c --flat sub/a.py     : writes a.py
cheetah c --odir DEST sub/a.tmpl
                              : writes DEST/sub/a.py
cheetah c --flat --odir DEST sub/a.tmpl
                              : writes DEST/a.py
cheetah c --idir /home/henry sub/rollins.tmpl
                              : writes sub/rollins.py
cheetah c --flat --idir /home/henry sub/rollins.tmpl
                              : writes rollins.py
cheetah c --idir /home/henry --odir /home/henry sub/rollins.tmpl
                              : writes /home/henry/sub/rollins.py
cheetah c --flat --idir /home/henry --odir /home/henry sub/rollins.tmpl
                              : writes /home/henry/rollins.py

Whenever ``cheetah compile'' has to create an output directory or subdirectory, it also creates an __init__.py file in it. This file is necessary in order to make Python treat the directory as a Python package.

One of the advantages of .py template modules is that you don't lose any flexibility. The generated class contains all #attr values and #def/#block values as ordinary attributes and methods, so you can read the values individually from other Python tools for any kind of custom processing you want. For instance, you can extract the titles of all your templates into a database, or find all the servlets with a certain $author value.


4.3 ``cheetah fill''

You can compile and fill a large number of template definitions from the command line in one step using cheetah fill. This compiles the template in memory; it does not save the .py template module to disk. Instead it writes a finished output file, which has the extension .html by default. All the options to cheetah compile work the same way here, and there are also a couple additional options:

  --env : put the environment in the searchList
  --pickle FILE : unpickle FILE and put that object in the searchList

Because you can't provide a searchList on the command line, the templates must either contain or inherit all the variables it needs, or use the --env and --pickle options to provide additional variables.

Examples:

cheetah fill a.tmpl              : writes a.html
cheetah fill a.tmpl b.tmpl       : writes a.html and b.html
cheetah f --oext txt a           : writes a.txt (from a.tmpl)

Using --env may have security or reliability implications because the environment normally contains lots of variables you inherited rather than defining yourself. If any of these variables override any of yours (say a #def), you will get incorrect output, may reveal private information, and may get an exception due to the variable being an unexpected type (environmental variables are always strings). Your calling program may wish to clear out the environment before setting environmental variables for the template.

There are two other differences between ``cheetah compile'' and ``cheetah fill''. Cheetah doesn't create __init__.py files when creating directories in fill mode. Also, the source filenames don't have to be identifiers.


4.4 Some trivia about .py template modules

We won't look inside .py template modules in this Guide except to note that they are very different from template definitions. The following template definition fragment:

The number is $Test.unittest.main.

compiles to this:

write("The number is ")  
write(filter(VFN(VFS(SL,"Test.unittest",1),"main",0)
write(".")

The Cheetah Developers' Guide looks at .py template modules in depth, and shows what the various directives compile to. But you are welcome to take a peek at some .py template modules yourself if you're curious about what Cheetah does under the hood. It's all regular Python code: writing strings and function calls to a file-like object.

Looking at a .py template module may also help you see why something doesn't work, by seeing what Cheetah thought you meant. It also helps discourage you from modifying the .py file yourself, because who wants to keep all those function calls and arguments straight? Let the computer do the drudgery work.


4.5 Running a .py template module as a standalone program

In addition to importing your .py template module file into a Python script or using it as a Webware servlet, you can also run it from the command line as a standalone program. The program will print the filled template on standard output. This is useful while debugging the template, and for producing formatted output in shell scripts.

When running the template as a program, you cannot provide a searchList or set self. attributes in the normal way, so you must take alternative measures to ensure that every placeholder has a value. Otherwise, you will get the usual NameMapper.NotFound exception at the first missing value. You can either set default values in the template itself (via the #attr or #def directives) or in a Python superclass, or use the --env or --pickle command-line options, which work just like their ``cheetah fill'' counterparts.

Run python FILENAME.py --help to see all the command-line options your .py template module accepts.


4.6 Object-Oriented Documents

Because Cheetah documents are actually class definitions, templates may inherit from one another in a natural way, using regular Python semantics. For instance, consider this template, FrogBase.tmpl:

#def title
This document has not defined its title
#end def
#def htTitle
$title
#end def
<HTML><HEAD>
<TITLE>$title</TITLE>
</HEAD><BODY>
<H1>$htTitle</H1>
$body
</BODY></HTML>

And its subclassed document, Frog1.tmpl:

#from FrogBase import FrogBase
#extends FrogBase
#def title
The Frog Page
#end def
#def htTitle
The <IMG SRC="Frog.png"> page
#end def
#def body
... lots of info about frogs ...
#end def

This is a classic use of inheritance. The parent ``template'' is simply an abstract superclass. Each document specializes the output of its parent. For instance, here the parent defines $htTitle so that by default it's identical to whatever the $title is, but it can also be customized.

In many other templating systems, you'd have to use case statements or if-elseif blocks of some sort, repeated in many different sections of code.

While we show another Cheetah document inheriting from this parent, a Python class can inherit from it just as easily. This Python class could define its programmatically-driven value for $body and $title, simply by defining body() and title() methods that return a string. (Actually they can return anything, but we'll get into that later.)

from FrogBase import FrogBase
class Frog2(FrogBase):
	def title(self):
		return "Frog 2 Page"
	# We don't override .htTitle, so it defaults to "Frog 2 Page" too.
	def body(self):
		return " ... more info about frogs ..."

Similarly, the Cheetah document can inherit from an arbitrary class. That's how Cheetah makes templates usable as Webware servlets, by subclassing Servlet. This technique should be possible for non-Webware systems too.

(Note: FrogBase.tmpl could be improved by using the #block directive, section 8.8.)


5 Language Overview

Cheetah's basic syntax was inspired by the Java-based template engines Velocity and WebMacro. It has two types of tags: $placeholders and #directives. Both types are case-sensitive.

Placeholder tags begin with a dollar sign ($varName) and are similar to data fields in a form letter or to the %(key)s fields on the left side of Python's % operator. When the template is filled, the placeholders are replaced with the values they refer to.

Directive tags begin with a hash character (#) and are used for comments, loops, conditional blocks, includes, and all other advanced features. (Note: you can customize the start and end delimeters for placeholder and directive tags, but in this Guide we'll assume you're using the default.)

Placeholders and directives can be escaped by putting a backslash before them. \$var and \#if will be output as literal text.

A placeholder or directive can span multiple physical lines, following the same rules as Python source code: put a backslash (\) at the end of all lines except the last line. However, if there's an unclosed parenthesis, bracket or brace pending, you don't need the backslash.

#if $this_is_a_very_long_line and $has_lots_of_conditions \
    and $more_conditions:
<H1>bla</H1>
#end if

#if $country in ('Argentina', 'Uruguay', 'Peru', 'Colombia',
    'Costa Rica', 'Venezuela', 'Mexico')
<H1>Hola, senorita!</H1>
#else
<H1>Hey, baby!</H1>
#end if


5.1 Language Constructs - Summary

  1. Comments and documentation strings
    1. ## single line
    2. #* multi line *#

  2. Generation, caching and filtering of output
    1. plain text
    2. look up a value: $placeholder
    3. evaluate an expression: #echo ...
    4. same but discard the output: #silent ...
    5. one-line if: #if EXPR then EXPR else EXPR
    6. gobble the EOL: #slurp
    7. parsed file includes: #include ...
    8. raw file includes: #include raw ...
    9. verbatim output of Cheetah code: #raw ...#end raw
    10. cached placeholders: $*var, $*<interval>*var
    11. cached regions: #cache ...#end cache
    12. set the output filter: #filter ...
    13. control output indentation: #indent ...(not implemented yet)

  3. Importing Python modules and objects: #import ..., #from ...

  4. Inheritance
    1. set the base class to inherit from: #extends
    2. set the name of the main method to implement: #implements ...

  5. Compile-time declaration
    1. define class attributes: #attr ...
    2. define class methods: #def ...#end def
    3. #block ...#end block provides a simplified interface to #def ...#end def

  6. Run-time assignment
    1. local vars: #set ...
    2. global vars: #set global ...
    3. deleting local vars: #del ...

  7. Flow control
    1. #if ...#else ...#else if (aka #elif) ...#end if
    2. #unless ...#end unless
    3. #for ...#end for
    4. #repeat ...#end repeat
    5. #while ...#end while
    6. #break
    7. #continue
    8. #pass
    9. #stop

  8. error/exception handling
    1. #assert
    2. #raise
    3. #try ...#except ...#else ... #end try
    4. #try ...#finally ...#end try
    5. #errorCatcher ...set a handler for exceptions raised by $placeholder calls.

  9. Instructions to the parser/compiler
    1. #breakpoint
    2. #compiler-settings ...#end compiler-settings

  10. Escape to pure Python code
    1. evalute expression and print the output: <%= ... %>
    2. execute code and discard output: <% ...%>

  11. Fine control over Cheetah-generated Python modules
    1. set the source code encoding of compiled template modules: #encoding
    2. set the sh-bang line of compiled template modules: #shBang

The use of all these constructs will be covered in the next several chapters.


5.2 Placeholder Syntax Rules

The following are valid $placeholders:

$a $_ $var $_var $var1 $_1var $var2_ $dict.key $list[3]
$object.method $object.method() $object.method
$nest($nest($var))

These are not $placeholders but are treated as literal text:

$@var $^var $15.50 $$


5.3 Where can you use placeholders?

There are three places you can use placeholders: top-level position, expression position and LVALUE position. Each has slightly different syntax rules.

Top-level position means interspersed in text. This is the only place you can use the placeholder long form: ${var}.

Expression position means inside a Cheetah expression, which is the same as a Python expression. The placeholder names a searchList or other variable to be read. Expression position occurs inside () and $[]$ arguments within placeholder tags (i.e., a placeholder inside a placeholder), and in several directive tags.

LVALUE position means naming a variable that will be written to. LVALUE is a computer science term meaning ``the left side of an assignment statement''. The first argument of directives #set, #for, #def, #block and #attr is an LVALUE.

This stupid example shows the three positions. Top-level position is shown in courier, expression position is italic, and LVALUE position is bold.

#for $count in $range($ninetyNine, 0, -1)
#set $after = $count - 1
$count bottles of beer on the wall. $count bottles of beer!
    Take one down, pass it around. $after bottles of beer on the wall.
#end for
$hex($myVar, $default=None)

The output of course is:

99 bottles of beer on the wall.  99 bottles of beer!
    Take one down, pass it around.  98 bottles of beer on the wall.
98 bottles of beer on the wall.  98 bottles of beer!
    Take one down, pass it around.  97 bottles of beer on the wall.
...


5.4 Are all those dollar signs really necessary?

$ is a ``smart variable prefix''. When Cheetah sees $, it determines both the variable's position and whether it's a searchList value or a non-searchList value, and generates the appropriate Python code.

In top-level position, the $ is required. Otherwise there's nothing to distinguish the variable from ordinary text, and the variable name is output verbatim.

In expression position, the $ is required if the value comes from the searchList or a ``#set global'' variable, recommended for local/global/builtin variables, and not necessary for the special constants None, True and False. This works because Cheetah generates a function call for a searchList placeholder, but a bare variable name for a local/global/builtin variable.

In LVALUE position, the $ is recommended. Cheetah knows where an LVALUE is expected, so it can handle your variable name whether it has $ or not.

EXCEPTION: Do not use the $ prefix for intermediate variables in a Python list comprehensions. This is a limitation of Cheetah's parser; it can't tell which variables in a list comprehension are the intermediate variables, so you have to help it. For example:

#set $theRange = [x ** 2 for x in $range(10)]
$theRange is a regular #set variable. $range is a Python built-in function. But x is a scratch variable internal to the list comprehension: if you type $x, Cheetah will miscompile it.


5.5 NameMapper Syntax

One of our core aims for Cheetah was to make it easy for non-programmers to use. Therefore, Cheetah uses a simplified syntax for mapping placeholders in Cheetah to values in Python. It's known as the NameMapper syntax and allows for non-programmers to use Cheetah without knowing (a) the difference between an instance and a dictionary, (b) what functions and methods are, and (c) what 'self' is. A side benefit is that you can change the underlying data structure (e.g., instance to dictionary or vice-versa) without having to modify the templates.

NameMapper syntax is used for all variables in Cheetah placeholders and directives. If desired, it can be turned off via the Template class' 'useNameMapper' compiler setting. But it's doubtful you'd ever want to turn it off.


5.5.1 Example

Consider this scenario:

You are building a customer information system. The designers with you want to use information from your system on the client's website -AND- they want to understand the display code and so they can maintian it themselves.

You write a UI class with a 'customers' method that returns a dictionary of all the customer objects. Each customer object has an 'address' method that returns the a dictionary with information about the customer's address. The designers want to be able to access that information.

Using PSP, the display code for the website would look something like the following, assuming your servlet subclasses the class you created for managing customer information:

  <%= self.customer()[ID].address()['city'] %>   (42 chars)

With Cheetah's NameMapper syntax, you can use any of the following:

   $self.customers()[$ID].address()['city']       (39 chars)
   --OR--                                         
   $customers()[$ID].address()['city']           
   --OR--                                         
   $customers()[$ID].address().city              
   --OR--                                         
   $customers()[$ID].address.city                
   --OR--                                         
   $customers[$ID].address.city                   (27 chars)

Which of these would you prefer to explain to the designers, who have no programming experience? The last form is 15 characters shorter than the PSP version and - conceptually - far more accessible. With PHP or ASP, the code would be even messier than with PSP.

This is a rather extreme example and, of course, you could also just implement $getCustomer($ID).city and obey the Law of Demeter (search Google for more on that). But good object orientated design isn't the point of this example.


5.5.2 Dictionary Access

NameMapper syntax allows access to dictionary items with the same dotted notation used to access object attributes in Python. This aspect of NameMapper syntax is known as 'Unified Dotted Notation'. For example, with Cheetah it is possible to write:

   $customers()['kerr'].address()  --OR--  $customers().kerr.address()
where the second form is in NameMapper syntax.

This works only with dictionary keys that also happen to be valid Python identifiers.


5.5.3 Autocalling

Cheetah automatically detects functions and methods in Cheetah $variables and calls them if the parentheses have been left off. Our previous example can be further simplified to:

  $customers.kerr.address

As another example, if 'a' is an object, 'b' is a method

  $a.b

is equivalent to

  $a.b()

If b returns a dictionary, then following variations are possible

  $a.b.c  --OR--  $a.b().c  --OR--  $a.b()['c']
where 'c' is a key in the dictionary that a.b() returns.

Further notes:


5.6 Namespace cascading and the searchList

When Cheetah maps a variable name in a template to a Python value, it searches several namespaces in order:

  1. Local variables: created by #set, #for, or predefined by Cheetah.
  2. The searchList, consisting of:
    1. #set global variables.
    2. The searchList containers you passed to the Template constructor, if any.
    3. The Template instance (``self''). This contains any attributes you assigned, #def methods and #block methods, attributes/methods inherited via #extends, and other attributes/methods built into Template or inherited by it (there's a list of all these methods in section 13.5).
  3. Python globals: created by #import, #from ... import, or otherwise predefined by Cheetah.
  4. Python builtins: None, max, etc.

The first matching name found is used.

Remember, these namespaces apply only to the first identifier after the $. In a placeholder like $a.b, only `a' is looked up in the searchList and other namespaces. `b' is looked up only inside `a'.

A searchList container can be any Python object with attributes or keys: dictionaries, instances, classes or modules. If an instance contains both attributes and keys, its attributes are searched first, then its keys.

Because the Template instance is part of the searchList, you can access its attributes/methods without `self': $myAttr. However, use the `self' if you want to make sure you're getting the Template attribute and not a same-name variable defined in a higher namespace: $self.myAttr. This works because ``self'' itself is a local variable.

The final resulting value, after all lookups and function calls (but before the filter is applied) is called the placeholder value, no matter which namespace it was found in.

Note carefully: if you put an object `myObject' in the searchList, you cannot look up $myObject! You can look up only the attributes/keys inside `myObject'.

Earlier versions of Cheetah did not allow you to override Python builtin names, but this was fixed in Cheetah 0.9.15.

If your template will be used as a Webware servlet, do not override methods 'name' and 'log' in the Template instance or it will interfere with Webware's logging. However, it is OK to use those variables in a higher namespace, since Webware doesn't know about Cheetah namespaces.


5.7 Missing Values

If NameMapper can not find a Python value for a Cheetah variable name, it will raise the NameMapper.NotFound exception. You can use the #errorCatcher directive (section 10.2) or errorCatcher Template constructor argument (section 4.1) to specify an alternate behaviour. BUT BE AWARE THAT errorCatcher IS ONLY INTENDED FOR DEBUGGING!

To provide a default value for a placeholder, write it like this: $getVar('varName', 'default value'). If you don't specify a default and the variable is missing, NameMapper.NotFound will be raised.


5.8 Directive Syntax Rules

Directive tags begin with a hash character (#) and are used for comments, loops, conditional blocks, includes, and all other advanced features. Cheetah uses a Python-like syntax inside directive tags and understands any valid Python expression. However, unlike Python, Cheetah does not use colons (:) and indentation to mark off multi-line directives. That doesn't work in an environment where whitespace is significant as part of the text. Instead, multi-line directives like #for have corresponding closing tags (#end for). Most directives are direct mirrors of Python statements.

Many directives have arguments after the opening tag, which must be in the specified syntax for the tag. All end tags have the following syntax:

#end TAG_NAME [EXPR]
The expression is ignored, so it's essentially a comment.


5.8.1 Directive closures and whitespace handling

Directive tags can be closed explicitly with #, or implicitly with the end of the line if you're feeling lazy.

#block testBlock #
Text in the body of the
block directive
#end block testBlock #
is identical to:
#block testBlock
Text in the body of the
block directive
#end block testBlock

When a directive tag is closed explicitly, it can be followed with other text on the same line:

bah, bah, #if $sheep.color == 'black'# black#end if # sheep.

When a directive tag is closed implicitly with the end of the line, all trailing whitespace is gobbled, including the newline character:

"""
foo #set $x = 2 
bar
"""
outputs 
"""
foo bar
"""

while 
"""
foo #set $x = 2 #
bar
"""
outputs 
"""
foo 
bar
"""

When a directive tag is closed implicitly AND there is no other text on the line, the ENTIRE line is gobbled up including any preceeding whitespace:

"""
foo 
   #set $x = 2 
bar
"""
outputs 
"""
foo
bar
"""

while 
"""
foo 
 - #set $x = 2
bar
"""
outputs 
"""
foo 
 - bar
"""

The #slurp directive (section 7.7) also gobbles up whitespace.

Spaces outside directives are output exactly as written. In the black sheep example, there's a space before ``black'' and another before ``sheep''. So although it's legal to put multiple directives on one line, it can be hard to read.

#if $a# #echo $a + 1# #end if
      - There's a space between each directive, 
        or two extra spaces total.
#if $a##echo $a + 1##end if
      - No spaces, but you have to look closely
        to verify none of the ``##'' are comment markers.
#if $a##echo $a + 1##end if     ### A comment.
      - In ``###'', the first ``#'' ends the directive, 
        the other two begin the comment.  (This also shows
	how you can add extra whitespace in the directive
	tag without affecting the output.)
#if $a##echo $a + 1##end if     # ## A comment.
      - More readable, but now there's a space before the
        comment.


6 Comments

Comments are used to mark notes, explanations, and decorative text that should not appear in the output. Cheetah maintains the comments in the Python module it generates from the Cheetah source code. There are two forms of the comment directive: single-line and multi-line.

All text in a template definition that lies between two hash characters (##) and the end of the line is treated as a single-line comment and will not show up in the output, unless the two hash characters are escaped with a backslash.

##=============================  this is a decorative comment-bar
$var    ## this is an end-of-line comment
##=============================

Any text between #* and *# will be treated as a multi-line comment.

#*
   Here is some multiline
   comment text
*#

If you put blank lines around method definitions or loops to separate them, be aware that the blank lines will be output as is. To avoid this, make sure the blank lines are enclosed in a comment. Since you normally have a comment before the next method definition (right?), you can just extend that comment to include the blank lines after the previous method definition, like so:

#def method1
... lines ...
#end def
#*


   Description of method2.
   $arg1, string, a phrase.
*#
#def method2($arg1)
... lines ...
#end def


6.1 Docstring Comments

Python modules, classes, and methods can be documented with inline 'documentation strings' (aka 'docstrings'). Docstrings, unlike comments, are accesible at run-time. Thus, they provide a useful hook for interactive help utilities.

Cheetah comments can be transformed into doctrings by adding one of the following prefixes:

##doc: This text will be added to the method docstring
#*doc: If your template file is MyTemplate.tmpl, running "cheetah compile"
       on it will produce MyTemplate.py, with a class MyTemplate in it,
       containing a method .respond().  This text will be in the .respond()
       method's docstring. *#

##doc-method: This text will also be added to .respond()'s docstring
#*doc-method: This text will also be added to .respond()'s docstring *#

##doc-class: This text will be added to the MyTemplate class docstring
#*doc-class: This text will be added to the MyTemplate class docstring *#

##doc-module: This text will be added to the module docstring MyTemplate.py
#*doc-module: This text will be added to the module docstring MyTemplate.py*#


6.2 Header Comments

Cheetah comments can also be transformed into module header comments using the following syntax:

##header: This text will be added to the module header comment
#*header: This text will be added to the module header comment *#

Note the difference between ##doc-module: and header: : ``cheetah-compile'' puts ##doc-module: text inside the module docstring. header: makes the text go above the docstring, as a set of #-prefixed comment lines.


7 Generating, Caching and Filtering Output


7.1 Output from complex expressions: #echo

Syntax:

#echo EXPR

The #echo directive is used to echo the output from expressions that can't be written as simple $placeholders.

Here is my #echo ', '.join(['silly']*5) # example

This produces:

Here is my silly, silly, silly, silly, silly example.


7.2 Executing expressions without output: #silent

Syntax:

#silent EXPR

#silent is the opposite of #echo. It executes an expression but discards the output.

#silent $myList.reverse()
#silent $myList.sort()
Here is #silent $covertOperation() # nothing

If your template requires some Python code to be executed at the beginning; (e.g., to calculate placeholder values, access a database, etc), you can put it in a "doEverything" method you inherit, and call this method using #silent at the top of the template.


7.3 One-line #if

Syntax:

#if EXPR1 then EXPR2 else EXPR3#

The #if flow-control directive (section 9.4) has a one-line counterpart akin to Perl's and C's ?: operator. If EXPR1 is true, it evaluates EXPR2 and outputs the result (just like #echo EXPR2#). Otherwise it evaluates EXPR3 and outputs that result. This directive is short-circuiting, meaning the expression that isn't needed isn't evaluated.

You MUST include both 'then' and 'else'. If this doesn't work for you or you don't like the style use multi-line #if directives (section 9.4).

The trailing # is the normal end-of-directive character. As usual it may be omitted if there's nothing after the directive on the same line.


7.4 Caching Output


7.4.1 Caching individual placeholders

By default, the values of each $placeholder is retrieved and interpolated for every request. However, it's possible to cache the values of individual placeholders if they don't change very often, in order to speed up the template filling.

To cache the value of a single $placeholder, add an asterisk after the $; e.g., $*var. The first time the template is filled, $var is looked up. Then whenever the template is filled again, the cached value is used instead of doing another lookup.

The $* format caches ``forever''; that is, as long as the template instance remains in memory. It's also possible to cache for a certain time period using the form $*<interval>*variable, where <interval> is the interval. The time interval can be specified in seconds (5s), minutes (15m), hours (3h), days (2d) or weeks (1.5w). The default is minutes.

<HTML>
<HEAD><TITLE>$title</TITLE></HEAD>
<BODY>

$var ${var}           ## dynamic - will be reinterpolated for each request
$*var2 $*{var2}       ## static - will be interpolated only once at start-up
$*5*var3 $*5*{var3}   ## timed refresh - will be updated every five minutes.

</BODY>
</HTML>

Note that ``every five minutes'' in the example really means every five minutes: the variable is looked up again when the time limit is reached, whether the template is being filled that frequently or not. Keep this in mind when setting refresh times for CPU-intensive or I/O intensive operations.

If you're using the long placeholder syntax, ${}, the braces go only around the placeholder name: $*.5h*{var.func('arg')}.

Sometimes it's preferable to explicitly invalidate a cached item whenever you say so rather than at certain time intervals. You can't do this with individual placeholders, but you can do it with cached regions, which will be described next.


7.4.2 Caching entire regions

Syntax:

#cache [id=EXPR] [timer=EXPR] [test=EXPR]
#end cache

The #cache directive is used to cache a region of content in a template. The region is cached as a single unit, after placeholders and directives inside the region have been evaluated. If there are any $*<interval>*var placholders inside the cache region, they are refreshed only when both the cache region and the placeholder are simultaneously due for a refresh.

Caching regions offers more flexibility than caching individual placeholders. You can specify the refresh interval using a placeholder or expression, or refresh according to other criteria rather than a certain time interval.

#cache without arguments caches the region statically, the same way as $*var. The region will not be automatically refreshed.

To refresh the region at an interval, use the timer=EXPRESSION argument, equivalent to $*<interval>*. The expression should evaluate to a number or string that is a valid interval (e.g., 0.5, '3m', etc).

To refresh whenever an expression is true, use test=EXPRESSION. The expression can be a method/function returning true or false, a boolean placeholder, several of these joined by and and/or or, or any other expression. If the expression contains spaces, it's easier to read if you enclose it in (), but this is not required.

To refresh whenever you say so, use id=EXPRESSION. Your program can then call .refreshCache(ID) whenever it wishes. This is useful if the cache depends on some external condition that changes infrequently but has just changed now.

You can combine arguments by separating them with commas. For instance, you can specify both id= and interval=, or id= and test=. (You can also combine interval and test although it's not very useful.) However, repeating an argument is undefined.

#cache
This is a static cache.  It will not be refreshed.
$a $b $c
#end cache

#cache timer='30m', id='cache1'
#for $cust in $customers
$cust.name:
$cust.street - $cust.city
#end for
#end cache

#cache id='sidebar', test=$isDBUpdated
... left sidebar HTML ...
#end cache

#cache id='sidebar2', test=($isDBUpdated or $someOtherCondition)
... right sidebar HTML ...
#end cache

The #cache directive cannot be nested.

We are planning to add a 'varyBy' keyword argument in the future that will allow a separate cache instances to be created for a variety of conditions, such as different query string parameters or browser types. This is inspired by ASP.net's varyByParam and varyByBrowser output caching keywords.


7.5 #raw

Syntax:

#raw
#end raw

Any section of a template definition that is inside a #raw ... #end raw tag pair will be printed verbatim without any parsing of $placeholders or other directives. This can be very useful for debugging, or for Cheetah examples and tutorials.

#raw is conceptually similar to HTML's <PRE> tag and LaTeX's
verbatim{}
tag, but unlike those tags, #raw does not cause the body to appear in a special font or typeface. It can't, because Cheetah doesn't know what a font is.


7.6 #include

Syntax:

#include [raw] FILENAME_EXPR
#include [raw] source=STRING_EXPR

The #include directive is used to include text from outside the template definition. The text can come from an external file or from a $placeholder variable. When working with external files, Cheetah will monitor for changes to the included file and update as necessary.

This example demonstrates its use with external files:

#include "includeFileName.txt"
The content of "includeFileName.txt" will be parsed for Cheetah syntax.

And this example demonstrates use with $placeholder variables:

#include source=$myParseText
The value of $myParseText will be parsed for Cheetah syntax. This is not the same as simply placing the $placeholder tag ``$myParseText'' in the template definition. In the latter case, the value of $myParseText would not be parsed.

By default, included text will be parsed for Cheetah tags. The argument ``raw'' can be used to suppress the parsing.

#include raw "includeFileName.txt"
#include raw source=$myParseText

Cheetah wraps each chunk of #include text inside a nested Template object. Each nested template has a copy of the main template's searchList. However, #set variables are visible across includes only if the defined using the #set global keyword.

All directives must be balanced in the include file. That is, if you start a #for or #if block inside the include, you must end it in the same include. (This is unlike PHP, which allows unbalanced constructs in include files.)


7.7 #slurp

Syntax:

#slurp

The #slurp directive eats up the trailing newline on the line it appears in, joining the following line onto the current line.

It is particularly useful in #for loops:

#for $i in range(5)
$i #slurp
#end for
outputs:
0 1 2 3 4


7.8 #indent

This directive is not implemented yet. When/if it's completed, it will allow you to

  1. indent your template definition in a natural way (e.g., the bodies of #if blocks) without affecting the output
  2. add indentation to output lines without encoding it literally in the template definition. This will make it easier to use Cheetah to produce indented source code programmatically (e.g., Java or Python source code).

There is some experimental code that recognizes the #indent directive with options, but the options are purposely undocumented at this time. So pretend it doesn't exist. If you have a use for this feature and would like to see it implemented sooner rather than later, let us know on the mailing list.

The latest specification for the future #indent directive is in the TODO file in the Cheetah source distribution.


7.9 Ouput Filtering and #filter

Syntax:

#filter FILTER_CLASS_NAME
#filter $PLACEHOLDER_TO_A_FILTER_INSTANCE
#filter None

Output from $placeholders is passed through an ouput filter. The default filter merely returns a string representation of the placeholder value, unless the value is None, in which case the filter returns an empty string. Only top-level placeholders invoke the filter; placeholders inside expressions do not.

Certain filters take optional arguments to modify their behaviour. To pass arguments, use the long placeholder syntax and precede each filter argument by a comma. By convention, filter arguments don't take a $ prefix, to avoid clutter in the placeholder tag which already has plenty of dollar signs. For instance, the MaxLen filter takes an argument 'maxlen':

${placeholderName, maxlen=20}
${functionCall($functionArg), maxlen=$myMaxLen}

To change the output filter, use the 'filter' keyword to the Template class constructor, or the #filter directive at runtime (details below). You may use #filter as often as you wish to switch between several filters, if certain $placeholders need one filter and other $placeholders need another.

The standard filters are in the module Cheetah.Filters. Cheetah currently provides:

Filter
The default filter, which converts None to '' and everything else to str(whateverItIs). This is the base class for all other filters, and the minimum behaviour for all filters distributed with Cheetah.
ReplaceNone
Same.
MaxLen
Same, but truncate the value if it's longer than a certain length. Use the 'maxlen' filter argument to specify the length, as in the examples above. If you don't specify 'maxlen', the value will not be truncated.
Pager
Output a "pageful" of a long string. After the page, output HTML hyperlinks to the previous and next pages. This filter uses several filter arguments and environmental variables, which have not been documented yet.
WebSafe
Same as default, but convert HTML-sensitive characters ('$<$', '&', '$>$') to HTML entities so that the browser will display them literally rather than interpreting them as HTML tags. This is useful with database values or user input that may contain sensitive characters. But if your values contain embedded HTML tags you want to preserve, you do not want this filter.

The filter argument 'also' may be used to specify additional characters to escape. For instance, say you want to ensure a value displays all on one line. Escape all spaces in the value with '&nbsp', the non-breaking space:

${$country, also=' '}}

To switch filters using a class object, pass the class using the filter argument to the Template constructor, or via a placeholder to the #filter directive: #filter $myFilterClass. The class must be a subclass of Cheetah.Filters.Filter. When passing a class object, the value of filtersLib does not matter, and it does not matter where the class was defined.

To switch filters by name, pass the name of the class as a string using the filter argument to the Template constructor, or as a bare word (without quotes) to the #filter directive: #filter TheFilter. The class will be looked up in the filtersLib.

The filtersLib is a module containing filter classes, by default Cheetah.Filters. All classes in the module that are subclasses of Cheetah.Filters.Filter are considered filters. If your filters are in another module, pass the module object as the filtersLib argument to the Template constructor.

Writing a custom filter is easy: just override the .filter method.

    def filter(self, val, **kw):     # Returns a string.
Return the string that should be output for `val'. `val' may be any type. Most filters return `' for None. Cheetah passes one keyword argument: kw['rawExpr'] is the placeholder name as it appears in the template definition, including all subscripts and arguments. If you use the long placeholder syntax, any options you pass appear as keyword arguments. Again, the return value must be a string.

You can always switch back to the default filter this way: #filter None. This is easy to remember because "no filter" means the default filter, and because None happens to be the only object the default filter treats specially.

We are considering additional filters; see http://webware.colorstudy.net/twiki/bin/view/Cheetah/MoreFiltersfor the latest ideas.


8 Import, Inheritance, Declaration and Assignment


8.1 #import and #from directives

Syntax:

#import MODULE_OR_OBJECT [as NAME] [, ...]
#from MODULE import MODULE_OR_OBJECT [as NAME] [, ...]

The #import and #from directives are used to make external Python modules or objects available to placeholders. The syntax is identical to the import syntax in Python. Imported modules are visible globally to all methods in the generated Python class.

#import math
#import math as mathModule
#from math import sin, cos
#from math import sin as _sin
#import random, re
#from mx import DateTime         # ## Part of Egenix's mx package.

After the above imports, $math, $mathModule, $sin, $cos and $_sin, $random, $re and $DateTime may be used in $placeholders and expressions.


8.2 #extends

Syntax:

#extends CLASS

All templates are subclasses of Cheetah.Template.Template. However, it's possible for a template to subclass another template or a pure Python class. This is where #extends steps in: it specifies the parent class. It's equivalent to PSP's ``@page extends='' directive.

Cheetah imports the class mentioned in an #extends directive automatically if you haven't imported it yet. The implicit importing works like this:

#extends Superclass   
## Implicitly does '#from Superclass import Superclass'.

#extends Cheetah.Templates.SkeletonPage
## Implicitly does '#from Cheetah.Templates.SkeletonPage import SkeletonPage'.

If your superclass is in an unusual location or in a module named differently than the class, you must import it explicitly. There is no support for extending from a class that is not imported; e.g., from a template dynamically created from a string. Since the most practical way to get a parent template into a module is to precompile it, all parent templates essentially have to be precompiled.

There can be only one #extends directive in a template and it may list only one class. In other words, templates don't do multiple inheritance. This is intentional: it's too hard to initialize multiple base classes correctly from inside a template. However, you can do multiple inheritance in your pure Python classes.

If your pure Python class overrides any of the standard Template methods such as .__init__ or .awake, be sure to call the superclass method in your method or things will break. Examples of calling the superclass method are in section 13.4. A list of all superclass methods is in section 13.5.

In all cases, the root superclass must be Template. If your bottommost class is a template, simply omit the #extends in it and it will automatically inherit from Template. If your bottommost class is a pure Python class, it must inherit from Template explicitly:

from Cheetah.Template import Template
class MyPurePythonClass(Template):

If you're not keen about having your Python classes inherit from Template, create a tiny glue class that inherits both from your class and from Template.

Before giving any examples we'll stress that Cheetah does not dictate how you should structure your inheritance tree. As long as you follow the rules above, many structures are possible.

Here's an example for a large web site that has not only a general site template, but also a template for this section of the site, and then a specific template-servlet for each URL. (This is the ``inheritance approach'' discussed in the Webware chapter.) Each template inherits from a pure Python class that contains methods/attributes used by the template. We'll begin with the bottommost superclass and end with the specific template-servlet:

1.  SiteLogic.py (pure Python class containing methods for the site)
        from Cheetah.Template import Template
        class SiteLogic(Template):

2.  Site.tmpl/py  (template containing the general site framework;
                   this is the template that controls the output,
                   the one that contains "<HTML><HEAD>...", the one
                   that contains text outside any #def/#block.)
        #from SiteLogic import SiteLogic
        #extends SiteLogic
        #implements respond

3.  SectionLogic.py  (pure Python class with helper code for the section)
        from Site import Site
        class SectionLogic(Site)

4.  Section.tmpl/py  (template with '#def' overrides etc. for the section)
        #from SectionLogic import SectionLogic
        #extends SectionLogic

5.  page1Logic.py  (pure Python class with helper code for the template-servlet)
        from Section import Section
        class indexLogic(Section):

6.  page1.tmpl/py  (template-servlet for a certain page on the site)
        #from page1Logic import page1Logic
        #extends page1Logic

A pure Python classes might also contain methods/attributes that aren't used by their immediate child template, but are available for any descendant template to use if it wishes. For instance, the site template might have attributes for the name and e-mail address of the site administrator, ready to use as $placeholders in any template that wants it.

Whenever you use #extends, you often need #implements too, as in step 2 above. Read the next section to understand what #implements is and when to use it.


8.3 #implements

Syntax:

#implements METHOD

You can call any #def or #block method directly and get its outpt. The top-level content - all the text/placeholders/directives outside any #def/#block - gets concatenated and wrapped in a ``main method'', by default .respond(). So if you call .respond(), you get the ``whole template output''. When Webware calls .respond(), that's what it's doing. And when you do 'print t' or 'str(t)' on a template instance, you're taking advantage of the fact that Cheetah makes .__str__() an alias for the main method.

That's all fine and dandy, but what if your application prefers to call another method name rather than .respond()? What if it wants to call, say, .send_output() instead? That's where #implements steps in. It lets you choose the name for the main method. Just put this in your template definition:

#implements send_output

When one template extends another, every template in the inheritance chain has its own main method. To fill the template, you invoke exactly one of these methods and the others are ignored. The method you call may be in any of the templates in the inheritance chain: the base template, the leaf template, or any in between, depending on how you structure your application. So you have two problems: (1) calling the right method name, and (2) preventing an undesired same-name subclass method from overriding the one you want to call.

Cheetah assumes the method you will call is .respond() because that's what Webware calls. It further assumes the desired main method is the one in the lowest-level base template, because that works well with #block as described in the Inheritance Approach for building Webware servlets (section 14.2), which was originally the principal use for Cheetah. So when you use #extends, Cheetah changes that template's main method to .writeBody() to get it out of the way and prevent it from overriding the base template's .respond().

Unfortunately this assumption breaks down if the template is used in other ways. For instance, you may want to use the main method in the highest-level leaf template, and treat the base template(s) as merely a library of methods/attributes. In that case, the leaf template needs #implements respond to change its main method name back to .respond() (or whatever your application desires to call). Likewise, if your main method is in one of the intermediate templates in an inheritance chain, that template needs #implements respond.

The other way the assumption breaks down is if the main method is in the base template but that template extends a pure Python class. Cheetah sees the #extends and dutifully but incorrectly renames the method to .writeBody(), so you have to use #implements respond to change it back. Otherwise the dummy .respond() in Cheetah.Template is found, which outputs... nothing. So if you're using #extends and get no output, the first thing you should think is, ``Do I need to add #implements respond somewhere?''


8.4 #set

Syntax:

#set [global] $var = EXPR

#set is used to create and update local variables at run time. The expression may be any Python expression. Remember to preface variable names with $ unless they're part of an intermediate result in a list comprehension.

Here are some examples:

#set $size = $length * 1096
#set $buffer = $size + 1096
#set $area = $length * $width
#set $namesList = ['Moe','Larry','Curly']
#set $prettyCountry = $country.replace(' ', '&nbsp;')

#set variables are useful to assign a short name to a $deeply.nested.value, to a calculation, or to a printable version of a value. The last example above converts any spaces in the 'country' value into HTML non-breakable-space entities, to ensure the entire value appears on one line in the browser.

#set variables are also useful in #if expressions, but remember that complex logical routines should be coded in Python, not in Cheetah!

#if $size > 1500
  #set $adj = 'large'
#else
  #set $adj = 'small'
#end if
Or Python's one-line equivalent, "A and B or C". Remember that in this case, B must be a true value (not None, '', 0, [] or ).
#set $adj = $size > 1500 and 'large' or 'small'
(Note: Cheetah's one-line #if will not work for this, since it produces output rather than setting a variable.

You can also use the augmented assignment operators:

## Increment $a by 5.
#set $a += 5

By default, #set variables are not visible in method calls or include files unless you use the global attribute: #set global $var = EXPRESSION. Global variables are visible in all methods, nested templates and included files. Use this feature with care to prevent surprises.


8.5 #del

Syntax:

#del $var

#del is the opposite of #set. It deletes a local variable. Its usage is just like Python's del statement:

#del $myVar
#del $myVar, $myArray[5]

Only local variables can be deleted. There is no directive to delete a #set global variable, a searchList variable, or any other type of variable.


8.6 #attr

Syntax:

#attr $var = EXPR

The #attr directive creates class attributes in the generated Python class. It should be used to assign simple Python literals such as numbers or strings. In particular, the expression must not depend on searchList values or #set variables since those are not known at compile time.

#attr $title = "Rob Roy"
#attr $author = "Sir Walter Scott"
#attr $version = 123.4

This template or any child template can output the value thus:

$title, by $author, version $version

If you have a library of templates derived from etexts (http://www.gutenberg.org/), you can extract the titles and authors and put them in a database (assuming the templates have been compiled into .py template modules):


8.7 #def

Syntax:

#def METHOD[(ARGUMENTS)]
#end def

Or the one-line variation:

#def METHOD[(ARGUMENTS)] : TEXT_AND_PLACEHOLDERS

The #def directive is used to define new methods in the generated Python class, or to override superclass methods. It is analogous to Python's def statement. The directive is silent, meaning it does not itself produce any output. However, the content of the method will be inserted into the output (and the directives executed) whenever the method is later called by a $placeholder.

#def myMeth()
This is the text in my method 
$a $b $c(123)  ## these placeholder names have been defined elsewhere
#end def

## and now use it...
$myMeth()

The arglist and parentheses can be omitted:

#def myMeth
This is the text in my method 
$a $b $c(123)
#end def

## and now use it...
$myMeth

Methods can have arguments and have defaults for those arguments, just like in Python. Remember the $ before variable names:

#def myMeth($a, $b=1234)
This is the text in my method 
$a - $b
#end def

## and now use it...
$myMeth(1)

The output from this last example will be:

This is the text in my method 
1 - 1234

There is also a single line version of the #def directive. Unlike the multi-line directives, it uses a colon (:) to delimit the method signature and body:

#attr $adj = 'trivial'
#def myMeth: This is the $adj method 
$myMeth
Leading and trailing whitespace is stripped from the method. This is in contrast to:
#def myMeth2
This is the $adj method
#end def
where the method includes a newline after "method". If you don't want the newline, add #slurp:
#def myMeth3
This is the $adj method#slurp
#end def

Because #def is handled at compile time, it can appear above or below the placeholders that call it. And if a super