Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

232 lines (199 sloc) 11.291 kB
Cheetah TODO list
* If you are working on a task please put your initials at the end of the
* When a task is completed please remember to note it in the CHANGES file
* Unresolved bugs are listed in the BUGS file. Resolved bugs are be listed
in the CHANGES file if the bug is considered significant enough and it
affected a released version of Cheetah.
Requirements for 1.0
- CheetahWrapper bugs: suppress verbose output if --stdout/-p. (MO)
- NameMapper attributes before keys, both Python and C versions. NM should
look for a key first, then an attribute. But if (1) this is the first
component after $, and (2) isinstance(OBJ, dictTypes), *ignore the
attributes* to prevent matching methods like .update, .keys, etc.
"dictTypes" is a new compiler setting with the default value
(types.DictType, UserDict). (TR)
- update User's Guide about changes to SkeletonPage (no more #settings,
etc) (TR)
- Decide on Cheetah's 1.0 license and update the Users' Guide. (TR)
- Add an example in the distribution of a simplified SkeletonPage
that used #block but does not have fancy esoteric methods like
style stuff. (MO)
- fix the --stdout option of CheetahWrapper so that it only prints
the generated python code.(TR)
Other TODO Items
- CheetahWrapper stuff: (MO)
* "cheetah compile --shbang '#!/usr/bin/python2.2'"
* "cheetah code [options] [FILES]" print template-specific portion of main
method(s) to stdout, with line numbers.
* Refactor, make compile/fill/code routines callbacks using a bundle arg.
- Debugging tools. See section below.
- revisit parsed #include directives. Are they necessary at all??
(This is a rhetorical question. They are necessary. However, the
Users' Guide needs better examples about when and when not to use
#include. Also, consider making '#include' do a raw include, and
something else do a parsed include ('#include parsed', '#include cheetah'?),
so that users get parsing only if they explicitly request it.
- implement some better error handling for misformed #for, #if, #try directives,
etc. At the moment these errors are not caught until Python executes the
- create better error message for bad code such as:
This is a cached region. $voom
#end cache
- create a better error message for invalid syntax when a $var inside a
directive is enclosed in ${} or $(). E.g.:
#include raw source=${x}
- Delete whitespace before a comment on the same line. The methods are
Parser.eatComment() and Parser.eatMultiLineComment(). It's already
working if the line contains 'STUFF#slurp ## comment'. Need to make
it work for 'STUFF ## comment' (but retain the EOL newline).
- 'python uninstall'. This may require hacking an uninstall feature
into distutils.
- 'errorCatcher None' to stop catching errors in the middle of a template.
Dump Tools
It would be nice to provide debugging tools for users who can't figure
out why a certain placeholder value isn't found or is being overridden.
My idea is to define $dumpSearchList() and $dumpSearchListFlat() in
Template, which would print a stanza in the output showing all searchList
variables and their values. $dumpSearchList would group by searchList
element; $dumpSearchListFlat would combine all into a single
alphabetical listing.
I made an experimental version but it printed only instance variables,
not methods and not inherited attributes. Also, it wouldn't print right
using the usual pattern of write-to-custom-StringIO-object-and-return-
the-.getvalue() and I couldn't figure out why.
The stanza should be set apart by a row of stars with the words
"BEGIN/END SEARCH LIST DUMP". Then for $dumpSearchList, precede each
group with "*** searchList[i], type <element type>, 142 variables ***".
Because some elements like 'self' may have hundreds of inherited
methods that would create a forest-through-trees situation for the user,
we may need an option to supress the variable listing for elements with
> 20 variables (just print the summary line instead). ?
The final version should be in Template so it has implicit
access to the searchList and perhaps later to other variables (locals,
globals, "#set global"s, builtins) too. This is such a central
debugging tool that you should not have to monopolize an #extends
(the template's only #extends) to use it. You could import it, however,
if you pass in the searchList explicitly as an argument. In that case,
perhaps we can base it on a generic module for dumping variables/values.
Note that we cannot simply depend on str() and pprint, because
we need to show instances as dictionaries. Likewise, dir() and vars()
may get us part of the distance, but only if they show methods and
inherited attributes too.
These functions should print only top-level variables, not
the subelements of collections. I.e, if the first searchList element
is a dictionary, show its keys/values, but do not expand any
subvalues if they are dictionaries too, unless the display tool happens
to default to that.
Rewrite the caching framework
- add #cache varyBy= (tied to Tavis' proposed caching framework for Webware)
- #cache test= with a one-variable test produces invalid Python (an empty
if-block). Example in Cheetah Developers' Guide, section
"#cache with test: expression and method conditions".
- #cache id= seems to be ignoring the ID and generating a random numeric
ID instead. Is it working? Do cache IDs have to be numeric?
- Other ideas in Tavis' head.
- Have an option to refresh the cache whenever an external
file is updated. This would allow a data structure to be kept in
sync whenever its text configuration file is changed.
#entry $func($arg1, $arg2="default", $**kw)
Make a wrapper function in the .py template module that builds a searchList
from its positional arguments, then instantiates and fills a template and
returns the result. The preceding example would create a function thus:
def func(arg1, arg2="default", searchList=None, **kw):
"""Function docstring."""
sl = {'arg1': arg1, 'arg2': arg2}
if searchList is None:
searchList = [sl]
elif type(searchList) == types.ListType:
searchList.insert(0, sl)
raise TypeError("arg 'searchList'")
t = TheTemplate(searchList=searchList, **kw)
return str(t)
##doc-entry: and #*doc-entry: comments are appended to the function docstring.
Finally, make this function accessible directly from the shell.
If there are any non-option arguments on the command line, call the function
instead of filling the template the normal way.
This would perhaps make more sense as arguments to .respond(). But
.respond() has that pesky 'trans' argument that mustn't be interfered with,
and other programs may assume .respond() takes only one argument. Also,
when called via str(), str() cannot take arguments.
The current indenter is a kludge that has an indentation object, with
implicit placeholder calls added at each line to generate the indentation,
and #silent calls to adjust the object. It should be reimplemented to
generate code to call the indentation object directly. Also, the user
interface should be cleaned up, the implementation and Users' Guide
synchronized, and test cases built.
The desired implementation revolves around self._indenter, which knows the
current indentation level (a non-negative integer), chars (the string output
per level, default four spaces), and stack (the previous indentation levels).
The .indent() method returns the indentation string currently appropriate.
The desired interface so far:
#indent strip ; strip leading whitespace from input lines
#indent add ; add indentation to output lines as appropriate
#indent on ; do both
#indent off ; do neither
#indent reset ; set level to 0 and clear stack
#indent ++ ; increment level
#indent -- ; decrement level
#indent pop [EXPR] ; revert to Nth previous level (default 1)
; if pop past end of stack, set level to 0 and
; clear stack. All +/-/= operations push the old level
; onto the stack.
#indent debug ; dump level, chars and stack to template output
Possible extensions:
#indent =EXPR ; set level to N
#indent +EXPR ; add N to level (not very necessary)
#indent -EXPR ; subtract N from level (not very necessary)
There should be one indentation object per Template instance, shared by
methods and include files.
Upload File
A mixin method in Cheetah.Utils (for Template) that handles file uploads --
these are too complicated for .webInput(). The method should do a "safe"
file upload; e.g., ,
within the limitations of Python's cgi module. The user has the choice of
three destinations for the file contents: (A) copied to a local
path you specify, (B) placed in a namespace variable like .cgiImport()
does, or (C) returned. (B) parallels .webInput, but (A) will certainly be
desirable situations where we just want to save the file, not read it into
memory. Reject files larger than a user-specified size or not in a list of
user-approved MIME types. Define appropriate exceptions for typical
file-upload errors. Method name .webUploadFileAsString?
One situation to support is when form has a text(area) field
related to a file-upload control on the same form, and the user has the choice
of typing into the field or uploading a text file. We need a method that
updates the text field's value if there is an uploaded file, but not if there
isn't. This may be handled by the regular method(s) or may require a separate
Test Suite
- test cases for the SkeletonPage framework
- add cases that test the cheetah-compile script
- add cases that test the integration with WebKit. Since these must be called
from a running WebKit server, make a servlet that runs the tests and outputs
diagnostics to the browser.
- automate the documentation update
- See if we can get WebKit working on Sourceforge...
- create some non-html code generation examples
- LaTeX
- form email
- Template definitions in a database. .py template modules in a
database? Caching template classes and/or instances extracted from
a database.
- Pickled templates?
Jump to Line
Something went wrong with that request. Please try again.