summaryrefslogtreecommitdiff
path: root/docs/users_guide_src/howItWorks.tex
blob: 4efa22f9d3de46924f66d00c2175c2f32d8cb4f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
\section{How Cheetah Works}
\label{howWorks}

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
\ref{gettingStarted.tutorial} (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 \ref{webware}
(Webware).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Constructing Template Objects}
\label{howWorks.templateClass}
\label{howWorks.constructing}

The heart of Cheetah is the \code{Template} class in the
\code{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.)

\begin{description}
\item{{\bf source}}
     The template definition as a string.  You may omit the \code{source=}
     prefix {\em 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.
\item{{\bf 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
     {\bf .tmpl}.
\item{{\bf searchList}}
     A list of objects to add to the searchList.  The attributes/keys of these
     objects will be consulted for \code{\$placeholder} lookup.
\item{{\bf filter}}
     A class that will format every \code{\$placeholder} value.  You may
     specify a class object or string.  If a class object,
     it must be a subclass of \code{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 \code{\#filter} directive (section
     \ref{output.filter}) to switch filters at runtime.)
\item{{\bf filtersLib}}
     A module containing the filters Cheetah should look up by name.  The
     default is \code{Cheetah.Filters}.  All classes in this module that are
     subclasses of \code{Cheetah.Filters.Filter} are considered filters.
\item{{\bf errorCatcher}}
     A class to handle \code{\$placeholder} errors.  You may
     specify a class object or string.  If a class object,
     it must be a subclass of \code{Cheetah.ErrorCatchers.ErrorCatcher}.  
     If a string, it must be the name of one of the error catchers in
     \code{Cheetah.ErrorCatchers}.  This is similar to the 
     \code{\#errorCatcher} directive 
     (section \ref{errorHandling.errorCatcher}).
\item{{\bf compilerSettings}}
     A dictionary (or dictionary hierarchy) of settings that change Cheetah's
     behavior.  Not yet documented.
\end{description}

To use \code{Template} directly, you {\em must} specify either \code{source}
or \code{file}, but not both.  To use a precompiled template, you 
{\em 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:
\begin{description}
\item{\code{t = Template("The king is a \$placeholder1.")}}
     \\ Pass the template definition as a string.
\item{\code{t = Template(file="fink.tmpl")}}
     \\ Read the template definition from a file named "fink.tmpl".  
\item{\code{t = Template(file=f)}}
     \\ Read the template definition from file-like object 'f'.
\item{\code{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'.
\item{\code{t = Template(file="fink.txt", searchList=[dict, obj])}}
     \\ Same, but pass a filename instead of a string.
\item{\code{t = Template(file=f, searchList=[dict, obj])}}
     \\ Same with a file object.
\end{description}

If you use \code{Template} directly, the template definition will be compiled
the first time it's filled.  Compilation creates a template-specific class
called the {\bf generated class}, which is a subclass of \code{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.

% By convention, you give a file containing a template definition the extension
% {\bf .tmpl}.

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 \code{Template}.  We call the generated
module a {\bf .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.

\code{Template} subclasses Webware's \code{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 {\bf main method}.  This is normally 
\code{.respond()}, but under certain circumstances it's \code{.writeBody()} or
a user-defined name.  (Section \ref{inheritanceEtc.implements} explains why
the method name is not always the same.)  However, \code{.\/\_\_str\_\_()} is
always an alias for the main method, so you can always use
\code{print\ myTemplateInstance} or \code{str(myTempateInstance)} to fill it.
You can also call any \code{\#def} or \code{\#block} method and it will fill
just that portion of the template, although this feature is not often used.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{``cheetah compile'' and .py template modules}
\label{howWorks.cheetah-compile}

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

\begin{verbatim}
cheetah compile [options] [FILES ...]
cheetah c [options] [FILES ...]
\end{verbatim}

The following options are supported:
\begin{verbatim}
  --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)
\end{verbatim}

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

The most basic usage is:
\begin{verbatim}
cheetah compile a.tmpl           : writes a.py
cheetah compile a.tmpl b.tmpl    : writes a.py and b.py
\end{verbatim}

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):
\begin{verbatim}
cheetah compile a                : writes a.py (from a.tmpl)
cheetah compile a b              : writes a.py and b.py
\end{verbatim}

You can override the default input extension and output extension
(\code{py}) using \code{--iext} and \code{--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 \code{-R} option to recurse subdirectories:
\begin{verbatim}
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
\end{verbatim}
When recursing, only regular files that end in the input extension (.tmpl) are
considered source files.  All other filenames are ignored.

The options \code{--idir} and \code{--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):
\begin{verbatim}
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
\end{verbatim}

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

For the same reason, if your template requires custom Python methods or
other Python code, don't put it in the \code{FILENAME.py} file.  Instead, put
it in a separate base class and use the \code{\#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, \code{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
{\em directory} it's in does not have to be an identifier.  ({\em 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 \code{--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.
\begin{verbatim}
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
\end{verbatim}

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 \code{\#attr} values and
\code{\#def}/\code{\#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
\code{\$author} value.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{``cheetah fill''}
\label{howWorks.cheetah-fill}

You can compile and fill a large number of template definitions from the
command line in one step using \code{cheetah fill}.  This compiles the template
in memory; it does {\em not} save the .py template module to disk.  Instead it
writes a finished output file, which has the extension \code{.html} by default.
All the options to \code{cheetah compile} work the same way here, and there are
also a couple additional options:
\begin{verbatim}
  --env : put the environment in the searchList
  --pickle FILE : unpickle FILE and put that object in the searchList
\end{verbatim}

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 \code{--env} and \code{--pickle} options to
provide additional variables.  

Examples:
\begin{verbatim}
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)
\end{verbatim}

Using \code{--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
\code{\#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.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Some trivia about .py template modules}
\label{howWorks.pyTrivia}

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:

\begin{verbatim}
The number is $Test.unittest.main.
\end{verbatim}

compiles to this:

\begin{verbatim}
write("The number is ")  
write(filter(VFN(VFS(SL,"Test.unittest",1),"main",0)
write(".")
\end{verbatim}

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.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Running a .py template module as a standalone program}
\label{howWorks.standalone}

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 \code{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 \code{NameMapper.NotFound} exception at
the first missing value.  You can either set default values in the template
itself (via the \code{\#attr} or \code{\#def} directives) or in a Python
superclass, or use the \code{--env} or \code{--pickle} command-line options,
which work just like their ``cheetah fill'' counterparts.

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


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Object-Oriented Documents}
\label{howWorks.objoriented}

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:

\begin{verbatim}
#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>
\end{verbatim}

And its subclassed document, Frog1.tmpl:
\begin{verbatim}
#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
\end{verbatim}

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
\code{\$htTitle} so that by default it's identical to whatever the 
\code{\$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 \code{\$body} and \code{\$title}, simply by
defining body() and title() methods that return a string.  (Actually they
can return anything, but we'll get into that later.)  

\begin{verbatim}
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 ..."
\end{verbatim}

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

({\em Note:}\ \code{FrogBase.tmpl} could be improved by using the
\code{\#block} directive, section \ref{inheritanceEtc.block}.)

% Local Variables:
% TeX-master: "users_guide"
% End: