summaryrefslogtreecommitdiff
path: root/docs/users_guide_2_src/08_inheritanceEtc.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/users_guide_2_src/08_inheritanceEtc.txt')
-rwxr-xr-xdocs/users_guide_2_src/08_inheritanceEtc.txt564
1 files changed, 564 insertions, 0 deletions
diff --git a/docs/users_guide_2_src/08_inheritanceEtc.txt b/docs/users_guide_2_src/08_inheritanceEtc.txt
new file mode 100755
index 0000000..3e76ce2
--- /dev/null
+++ b/docs/users_guide_2_src/08_inheritanceEtc.txt
@@ -0,0 +1,564 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Import, Inheritance, Declaration and Assignment}
+\label{inheritanceEtc}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#import and \#from directives}
+\label{inheritanceEtc.import}
+
+Syntax:
+\begin{verbatim}
+#import MODULE_OR_OBJECT [as NAME] [, ...]
+#from MODULE import MODULE_OR_OBJECT [as NAME] [, ...]
+\end{verbatim}
+
+
+The \code{\#import} and \code{\#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.
+
+\begin{verbatim}
+#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.
+\end{verbatim}
+
+After the above imports, \code{\$math}, \code{\$mathModule},
+\code{\$sin}, \code{\$cos} and \code{\$\_sin}, \code{\$random}, \code{\$re}
+and \code{\$DateTime} may be used in \code{\$placeholders} and expressions.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#extends}
+\label{inheritanceEtc.extends}
+
+Syntax:
+\begin{verbatim}
+#extends CLASS
+\end{verbatim}
+
+
+All templates are subclasses of \code{Cheetah.Template.Template}. However,
+it's possible for a template to subclass another template or a pure Python
+class. This is where \code{\#extends} steps in: it
+specifies the parent class. It's equivalent to PSP's \code{``@page extends=''}
+directive.
+
+Cheetah imports the class mentioned in an \code{\#extends} directive
+automatically if you haven't imported it yet. The implicit importing works
+like this:
+
+\begin{verbatim}
+#extends Superclass
+## Implicitly does '#from Superclass import Superclass'.
+
+#extends Cheetah.Templates.SkeletonPage
+## Implicitly does '#from Cheetah.Templates.SkeletonPage import SkeletonPage'.
+\end{verbatim}
+
+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 \code{\#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 \code{Template}
+methods such as \code{.\_\_init\_\_} or \code{.awake}, be sure to call
+the superclass method in your method or things will break. Examples of calling
+the superclass method are in section \ref{tips.callingSuperclassMethods}.
+A list of all superclass methods is in section
+\ref{tips.allMethods}.
+
+In all cases, the root superclass must be \code{Template}. If your
+bottommost class is a template, simply omit the \code{\#extends} in it and it
+will automatically inherit from \code{Template}. {\em If your bottommost class
+is a pure Python class, it must inherit from \code{Template} explicitly: }
+\begin{verbatim}
+from Cheetah.Template import Template
+class MyPurePythonClass(Template):
+\end{verbatim}
+
+If you're not keen about having your Python classes inherit from
+\code{Template}, create a tiny glue class that inherits both from your
+class and from \code{Template}.
+
+Before giving any examples we'll stress that Cheetah does {\em 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:
+
+\begin{verbatim}
+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
+\end{verbatim}
+
+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.
+
+{\em Whenever you use \code{\#extends}, you often need \code{\#implements}
+too,} as in step 2 above. Read the next section to understand what
+\code{\#implements} is and when to use it.
+
+% @@MO: Edmund suggests making some diagrams of inheritance chains.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#implements}
+\label{inheritanceEtc.implements}
+
+Syntax:
+\begin{verbatim}
+#implements METHOD
+\end{verbatim}
+
+You can call any \code{\#def} or \code{\#block} method directly and get its
+outpt. The top-level content -- all the text/placeholders/directives outside any
+\code{\#def}/\code{\#block} -- gets concatenated and wrapped in a ``main
+method'', by default \code{.respond()}. So if you call \code{.respond()}, you
+get the ``whole template output''. When Webware calls \code{.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
+\code{.\_\_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 \code{.respond()}? What if it wants to call, say,
+\code{.send\_output()} instead? That's where \code{\#implements} steps in. It
+lets you choose the name for the main method. Just put this in your template
+definition:
+\begin{verbatim}
+#implements send_output
+\end{verbatim}
+
+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 \code{.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
+\code{\#block} as described in the Inheritance Approach for building Webware
+servlets (section \ref{webware.inheritance}), which was originally the
+principal use for Cheetah. So when you use \code{\#extends}, Cheetah changes
+that template's main method to \code{.writeBody()} to get it out of the way and
+prevent it from overriding the base template's \code{.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 \code{\#implements
+respond} to change its main method name back to \code{.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
+\code{\#implements respond}.
+
+The other way the assumption breaks down is if the main method {\em is} in
+the base template but that template extends a pure Python class. Cheetah sees
+the \code{\#extends} and dutifully but incorrectly renames the method to
+\code{.writeBody()}, so you have to use \code{\#implements respond} to change
+it back. Otherwise the dummy \code{.respond()} in \code{Cheetah.Template}
+is found, which outputs... nothing. {\bf So if you're using \code{\#extends}
+and get no output, the {\em first} thing you should think is, ``Do I need to
+add \code{\#implements respond} somewhere?'' }
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#set}
+\label{inheritanceEtc.set}
+
+Syntax:
+\begin{verbatim}
+#set [global] $var = EXPR
+\end{verbatim}
+
+\code{\#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:
+\begin{verbatim}
+#set $size = $length * 1096
+#set $buffer = $size + 1096
+#set $area = $length * $width
+#set $namesList = ['Moe','Larry','Curly']
+#set $prettyCountry = $country.replace(' ', '&nbsp;')
+\end{verbatim}
+
+\code{\#set} variables are useful to assign a short name to a
+\code{\$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.
+
+\code{\#set} variables are also useful in \code{\#if} expressions, but
+remember that complex logical routines should be coded in Python, not in
+Cheetah!
+\begin{verbatim}
+#if $size > 1500
+ #set $adj = 'large'
+#else
+ #set $adj = 'small'
+#end if
+\end{verbatim}
+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 {}).
+\begin{verbatim}
+#set $adj = $size > 1500 and 'large' or 'small'
+\end{verbatim}
+(Note: Cheetah's one-line \code{\#if} will not work for this, since it
+produces output rather than setting a variable.
+
+You can also use the augmented assignment operators:
+\begin{verbatim}
+## Increment $a by 5.
+#set $a += 5
+\end{verbatim}
+
+By default, \code{\#set} variables are not visible in method calls or include
+files unless you use the \code{global} attribute: \code{\#set global \$var =
+EXPRESSION}. Global variables are visible in all methods, nested templates and
+included files. Use this feature with care to prevent surprises.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#del}
+\label{inheritanceEtc.del}
+
+Syntax:
+\begin{verbatim}
+#del $var
+\end{verbatim}
+
+\code{\#del} is the opposite of \code{\#set}. It deletes a {\em local}
+variable. Its usage is just like Python's \code{del} statement:
+\begin{verbatim}
+#del $myVar
+#del $myVar, $myArray[5]
+\end{verbatim}
+
+Only local variables can be deleted. There is no directive to delete a
+\code{\#set global} variable, a searchList variable, or any other type of
+variable.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#attr}
+\label{inheritanceEtc.attr}
+
+Syntax:
+\begin{verbatim}
+#attr $var = EXPR
+\end{verbatim}
+
+The \code{\#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 {\em not} depend on searchList
+values or \code{\#set} variables since those are not known at compile time.
+
+\begin{verbatim}
+#attr $title = "Rob Roy"
+#attr $author = "Sir Walter Scott"
+#attr $version = 123.4
+\end{verbatim}
+
+This template or any child template can output the value thus:
+\begin{verbatim}
+$title, by $author, version $version
+\end{verbatim}
+
+If you have a library of templates derived from etexts
+(\url{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):
+
+%\begin{verbatim}
+%import glob
+%
+%\end{verbatim}
+%
+% @@MO: Finish this example.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#def}
+\label{inheritanceEtc.def}
+
+Syntax:
+\begin{verbatim}
+#def METHOD[(ARGUMENTS)]
+#end def
+\end{verbatim}
+
+Or the one-line variation:
+\begin{verbatim}
+#def METHOD[(ARGUMENTS)] : TEXT_AND_PLACEHOLDERS
+\end{verbatim}
+
+
+The \code{\#def} directive is used to define new methods in the generated
+Python class, or to override superclass methods. It is analogous to Python's
+\code{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.
+
+\begin{verbatim}
+#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()
+\end{verbatim}
+
+The arglist and parentheses can be omitted:
+\begin{verbatim}
+#def myMeth
+This is the text in my method
+$a $b $c(123)
+#end def
+
+## and now use it...
+$myMeth
+\end{verbatim}
+
+Methods can have arguments and have defaults for those arguments, just like
+in Python. Remember the \code{\$} before variable names:
+\begin{verbatim}
+#def myMeth($a, $b=1234)
+This is the text in my method
+$a - $b
+#end def
+
+## and now use it...
+$myMeth(1)
+\end{verbatim}
+
+The output from this last example will be:
+
+\begin{verbatim}
+This is the text in my method
+1 - 1234
+\end{verbatim}
+
+There is also a single line version of the \code{\#def} directive.
+{\bf Unlike the multi-line directives, it uses a colon (:) to delimit the method
+signature and body}:
+\begin{verbatim}
+#attr $adj = 'trivial'
+#def myMeth: This is the $adj method
+$myMeth
+\end{verbatim}
+Leading and trailing whitespace is stripped from the method. This is in
+contrast to:
+\begin{verbatim}
+#def myMeth2
+This is the $adj method
+#end def
+\end{verbatim}
+where the method includes a newline after "method". If you don't want the
+newline, add \code{\#slurp}:
+\begin{verbatim}
+#def myMeth3
+This is the $adj method#slurp
+#end def
+\end{verbatim}
+
+Because \code{\#def} is handled at compile time, it can appear above or
+below the placeholders that call it. And if a superclass placeholder
+calls a method that's overridden in a subclass, it's the subclass method
+that will be called.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{\#block ... \#end block}
+\label{inheritanceEtc.block}
+
+
+The \code{\#block} directive allows you to mark a section of your template that
+can be selectively reimplemented in a subclass. It is very useful for
+changing part of a template without having to copy-paste-and-edit
+the entire thing. The output from a template definition that uses blocks will
+be identical to the output from the same template with the \code{\#block \ldots
+\#end block} tags removed.
+
+({\em Note:} don't be confused by the generic word `block'' in this Guide,
+which means a section of code inside {\em any} \code{\#TAG \ldots \#end TAG}
+pair. Thus, an if-block, for-block, def-block, block-block etc. In this
+section we are talking only of block-blocks.)
+
+To reimplement the block, use the \code{\#def} directive. The magical effect
+is that it appears to go back and change the output text {\em at the point the
+original block was defined} rather than at the location of the
+reimplementation.
+
+\begin{verbatim}
+#block testBlock
+Text in the contents
+area of the block directive
+#if $testIt
+$getFoo()
+#end if
+#end block testBlock
+\end{verbatim}
+
+You can repeat the block name in the \code{\#end block} directive or not, as
+you wish.
+
+\code{\#block} directives can be nested to any depth.
+
+\begin{verbatim}
+#block outerBlock
+Outer block contents
+
+#block innerBlock1
+inner block1 contents
+#end block innerBlock1
+
+#block innerBlock2
+inner block2 contents
+#end block innerBlock2
+
+#end block outerBlock
+\end{verbatim}
+
+Note that the name of the block is optional for the \code{\#end block} tag.
+
+Technically, \code{\#block} directive is equivalent to a \code{\#def} directive
+followed immediately by a \code{\#placeholder} for the same name. In fact,
+that's what Cheetah does. Which means you can use \code{\$theBlockName}
+elsewhere in the template to output the block content again.
+
+There is a one-line \code{\#block} syntax analagous to the one-line
+\code{\#def}.
+
+The block must not require arguments because the implicit placeholder that's
+generated will call the block without arguments.
+
+
+% Local Variables:
+% TeX-master: "users_guide"
+% End:
+
+
+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::
+
+ #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 \ref{inheritanceEtc.block}.)
+
+