diff options
Diffstat (limited to 'docs/users_guide_src/howItWorks.tex')
-rwxr-xr-x | docs/users_guide_src/howItWorks.tex | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/docs/users_guide_src/howItWorks.tex b/docs/users_guide_src/howItWorks.tex new file mode 100755 index 0000000..4efa22f --- /dev/null +++ b/docs/users_guide_src/howItWorks.tex @@ -0,0 +1,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: + |