Thread: Re: [Cheetahtemplate-discuss] using compiled template as CGI script
Brought to you by:
rtyler,
tavis_rudd
From: <ir...@ms...> - 2002-05-22 18:26:45
|
On Wed, May 22, 2002 at 07:47:00PM +1000, Paul Sorenson wrote: > I mightn't have explained myself very well. > > All the .py files work just fine. It is only when I upload the .tmpl file > to the remote server that the cgi script returns a blank screen, actually: > > <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> > <HTML><HEAD> > <META http-equiv=Content-Type content="text/html; > charset=windows-1252"></HEAD> > <BODY><XMP></XMP></BODY></HTML> That was probably generated by the browser, since I get something like that in certain browsers if I use a file: URL on a zero-length file. I tried making an x.tmpl file, compiling it, waiting a minute, then touching x.tmpl so it's modification time would be later than x.py, then "chmod 000 x.tmpl" (removing all read permission), then running x.py. It failed with: Traceback (most recent call last): File "x.py", line 120, in ? x().runAsMainProgram() File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Template.py", line 331, in runAsMainProgram CmdLineIface(templateObj=self).run() File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/TemplateCmdLineIface.py", line 59, in run print self._template File "x.py", line 88, in respond self.compile(file=self._filePath) File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Template.py", line 230, in compile settings=self._compilerSettings, File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Compiler.py", line 929, in __init__ f = open(file) # Raises IOError. IOError: [Errno 13] Permission denied: '/tmp/x.tmpl' Perhaps this is what's happening to you, and through some quirk of the webserver setup you're not getting the "Internal server error". The traceback should appear in the webserver error log. In any case, Cheetah should handle the situation more gracefully, and fall back to the precompiled template if it can't open the .tmpl file. The exchange today got me thinking that perhaps when we have "cheetah fill" implemented (which compiles and fills a template in one step), we can make .tmpl files self executable. If the user puts something like #!/usr/bin/cheetah shbang at the top of the .tmpl file and gives it execute permission, Cheetah could read the template definition, chop off the first line, compile and fill it. This coupled with Tavis' suggestion for a .cgiHeaders method, would allow .tmpl files (with or without the .tmpl extension) to run as CGI scripts. Plus it may be useful during debugging or in other places too. Although for the highest efficiency, precompiled .py templates still rule. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: Ian B. <ia...@co...> - 2002-05-22 18:29:35
|
On Wed, 2002-05-22 at 13:34, Mike Orr wrote: > On Wed, May 22, 2002 at 07:47:00PM +1000, Paul Sorenson wrote: > > I mightn't have explained myself very well. > > > > All the .py files work just fine. It is only when I upload the .tmpl file > > to the remote server that the cgi script returns a blank screen, actually: > > > > <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> > > <HTML><HEAD> > > <META http-equiv=Content-Type content="text/html; > > charset=windows-1252"></HEAD> > > <BODY><XMP></XMP></BODY></HTML> > > That was probably generated by the browser, since I get something like > that in certain browsers if I use a file: URL on a zero-length file. I know for certain that view source on IE doesn't show the actual source -- it inserts TBODY elements and such, and I imagine all the other tags to make it a valid HTML page. Ian |
From: Paul S. <so...@us...> - 2002-05-22 23:30:15
|
No problemo - I will only upload the .py files for now. What I was hoping to do was that I could upload just the .tmpl files and that if they were newer, they would force a recompile and I would automagically have new .py files (sounds kind of like JSP doesn't it). In that case presumably I would need to have world write permission on the .py files which sounds like a recipe for getting seriously hacked. I would get the speed of .py files without having to worry so much about additional configuration management issues of which .py files are uptodate. Cheers BTW if anyone is after a basic makefile for their web site the this one seems to work (gnu make) (careful with spaces and tabs that might have got mangled at the start of lines). BBTW is there a more appropriate place for this sort of contribution? #---------------------- ROOT = menuch.html LEAVES = home.html broadband.html contact.html digital_filter.html \ home.html java.html links.html linux.html ontrak.html optus_home.html PAGES = $(ROOT) $(LEAVES) #CHEETAH = c:/usr/Cheetah-0.9.13/bin/cheetah CHEETAH = /usr/bin/cheetah .SUFFIXES: .tmpl .py .html all: $(PAGES) py: $(PAGES:.html=.py) $(LEAVES:.html=.py): $(ROOT:.html=.py) .tmpl.py: $(CHEETAH) -c $< .py.html: python $*.py > $*.html #---------------------- ----- Original Message ----- From: "Mike Orr" <ir...@ms...> To: "Cheetah Template List" <che...@li...> Sent: Thursday, May 23, 2002 4:34 AM Subject: Re: [Cheetahtemplate-discuss] using compiled template as CGI script > On Wed, May 22, 2002 at 07:47:00PM +1000, Paul Sorenson wrote: > > I mightn't have explained myself very well. > > > > All the .py files work just fine. It is only when I upload the .tmpl file > > to the remote server that the cgi script returns a blank screen, actually: > > > > <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> > > <HTML><HEAD> > > <META http-equiv=Content-Type content="text/html; > > charset=windows-1252"></HEAD> > > <BODY><XMP></XMP></BODY></HTML> > > That was probably generated by the browser, since I get something like > that in certain browsers if I use a file: URL on a zero-length file. > > I tried making an x.tmpl file, compiling it, waiting a minute, then > touching x.tmpl so it's modification time would be later than x.py, > then "chmod 000 x.tmpl" (removing all read permission), then running > x.py. It failed with: > > Traceback (most recent call last): > File "x.py", line 120, in ? > x().runAsMainProgram() > File > "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Template.py", > line 331, in runAsMainProgram > CmdLineIface(templateObj=self).run() > File > "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/TemplateCmdLi neIface.py", > line 59, in run > print self._template > File "x.py", line 88, in respond > self.compile(file=self._filePath) > File > "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Template.py", > line 230, in compile > settings=self._compilerSettings, > File > "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Compiler.py", > line 929, in __init__ > f = open(file) # Raises IOError. > IOError: [Errno 13] Permission denied: '/tmp/x.tmpl' > > Perhaps this is what's happening to you, and through some quirk of the > webserver setup you're not getting the "Internal server error". The > traceback should appear in the webserver error log. > > In any case, Cheetah should handle the situation more gracefully, and > fall back to the precompiled template if it can't open the .tmpl file. > > The exchange today got me thinking that perhaps when we have "cheetah fill" > implemented (which compiles and fills a template in one step), we can > make .tmpl files self executable. If the user puts something like > #!/usr/bin/cheetah shbang > at the top of the .tmpl file and gives it execute permission, Cheetah > could read the template definition, chop off the first line, compile and > fill it. This coupled with Tavis' suggestion for a .cgiHeaders method, > would allow .tmpl files (with or without the .tmpl extension) to run as > CGI scripts. Plus it may be useful during debugging or in other places > too. > > Although for the highest efficiency, precompiled .py templates still > rule. > > -- > -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) > http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol > > _______________________________________________________________ > > Don't miss the 2002 Sprint PCS Application Developer's Conference > August 25-28 in Las Vegas -- http://devcon.sprintpcs.com/adp/index.cfm > > _______________________________________________ > Cheetahtemplate-discuss mailing list > Che...@li... > https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss > |
From: <ir...@ms...> - 2002-05-23 00:11:15
|
On Thu, May 23, 2002 at 09:30:08AM +1000, Paul Sorenson wrote: > No problemo - I will only upload the .py files for now. What I was hoping > to do was that I could upload just the .tmpl files and that if they were > newer, they would force a recompile and I would automagically have new .py > files (sounds kind of like JSP doesn't it). In that case presumably I would > need to have world write permission on the .py files which sounds like a > recipe for getting seriously hacked. You'd have to give write permission to the webserver user, which sounds like a recipe for getting seriously hacked. > BTW if anyone is after a basic makefile for their web site the this one > seems to work (gnu make) (careful with spaces and tabs that might have got > mangled at the start of lines). > > BBTW is there a more appropriate place for this sort of contribution? Either here or on the wiki. It could go under CheetahRecipies or MiscTips. Anything that's generally usefull wil eventually get copied into the Users' Guide. BTW, I have also started using a Makefile in my current project. It produces two static HTML files, New.html and Renew.html. (Actually, it produces several others too, but they all follow this pattern.) The inheritance hierarchy is: HTMLTemplate.tmpl -> BaseLogic.py -> Base.tmpl -> top-level templates (HTMLTemplate has methods for generic HTML controls, BaseLogic has Python methods, and Base is the "site page" template.) The script forms.py sets up all the search lists and fills all the templates. The printlist target is for debugging; it prints a Postscript version of the source files. ### BEGIN Makefile ### all: forms .PHONY: all forms printlist printlist: a2ps Base.tmpl BaseLogic.py HTMLTemplate.tmpl New.tmpl Renew.tmpl \ forms.py Base.py: Base.tmpl cheetah compile Base.tmpl HTMLTemplate.py: HTMLTemplate.tmpl cheetah compile HTMLTemplate.tmpl New.py: New.tmpl cheetah compile New.tmpl Renew.py: Renew.tmpl cheetah compile Renew.tmpl forms: Base.py HTMLTemplate.py New.py Renew.py ./forms.py ### END Makefile ### -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: Paul S. <so...@us...> - 2002-05-23 13:21:02
|
Ok so now I have my skeleton web site running from .py files. How do I get my cheetah output to run with mod_python? I have read the mod_python example a couple of times and it wasn't clear to me whether I just have to write a small wrapper "handler" that then loaded templates - or whether I would need to modify the .py files (bad). If anyone has done this some tips would be most appreciated. If not, I will just have to RTFM tomorrow. Cheers |
From: <ir...@ms...> - 2002-05-23 16:07:31
|
On Thu, May 23, 2002 at 11:20:55PM +1000, Paul Sorenson wrote: > Ok so now I have my skeleton web site running from .py files. > > How do I get my cheetah output to run with mod_python? I have read the > mod_python example a couple of times and it wasn't clear to me whether I > just have to write a small wrapper "handler" that then loaded templates - or > whether I would need to modify the .py files (bad). .py template modules do not conform to mod_python's structure, so they can't be used as is. At the same time, you don't want to modify the .py template module because you'd have to do all your changes again if you modify the template and recompile the module. Your best choice would be to make a wrapper script that invokes the template. This can probably be generic (identical for all servlets) if it uses the URL to look up the specific template module. Actually, that's part of what Webware does, so you can borrow ideas from Webware or WebwareExpRefactoring. If you come up with a good generic handler that can be used on other sites, we can put it in Cheetah's examples directory. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: <rob...@ya...> - 2002-05-25 13:12:59
|
hi guys, being absent for sometime, cause i was looking for a more "pure" java templating solution (aka velocity) i now return ashamed (cheetah is so much more poweful). i do have some ideas/suggestions i would like to discuss with you. before i begin some initial explanations about the context i want to work within. generally i want to generate code (mostly java and python). i dont work within any jsp/psp or whatever context. when writing the generating code i want to stay within the programming-system i'm in all the time. as long the environment exhibts all the possebilities of writing encapsulated, modular code i dont see the need to escape to a different environment when writing business-logic (as advised by the velocity people). especially when there is no "business-logic" only an informationmodel (that is treelike) that needs to be transformed into a different representation. when writing the code i want to this be facts to be true a) the generatorcode (that is the cheetah-source) must be indented properly. showing the structure of the code. this is something cheetah does anyway cause of its python heritage. b) the generated code (that is not the resulting code but the code embedded within the cheetah code) must be indented properly too. so that i can see both the structure of the generator _AND_ the structure of the result (to be). so what i need is absolute power about whitespaces issues. even so cheetah is more powerful then velocity on this front it still lacks some features needed when especially generating python code (or for that matter cheetah-code ;-) ). on the java-front the whitespace issues is "only" an inconvenience (but sometimes really a pita). i will show you some examples to illustrate my point (the generated code is java, so that it you dont get confused about wat is generator-code and what is generated-code. whitespaces will be shown as a dot "." where necessary) lets say i have the following simple model: class -->0..* class |---->* method -->* Statement a class has zero to many classes (inner). a class has one to many methods. a method has one to many Statements. a concrete example might look like this class parent method foo class child method bar the template will be given the the root of this tree as "modelroot". !!!SOURCE #def printClass(self, cls): ..class $cls.Name ..{ ....#foreach($child in $cls.Children): ......//inner classes ......#printClass($child) ....#end for ....#foreach($method in cls.Methods): ......//method implementations ......#printMethod($method) ....#end for ..} #end def #def printMethod(self, meth): ..public $meth.ReturnType $meth.Name() ..{ ....//here the statements go ..} #end def #printClass($modelRoot) !!!END SOURCE obviously you can see within each of the defs the first two spaces are just to show the structure of the code. this happens with the java-comment-lines within the foreach loops too. !!!OUTPUT ..class parent ..{ ......//inner classes ........class child ..{ ........public void bar() ..{ ....//here the statements go ..} ..} ......//method implementations ........public void foo() ..{ ....//here the statements go ..} ..} !!!END OUTPUT this output might not be very visually pleasing but anyhow it is valid compilable java-code. and could use a beautifier to get it right. hmm. not so fast! the problems with this are: - if i want to generate python code the beautifier-solution will possibly not work - or might generate code that does not what was intended. - if i want to generate other whitespace-aware results (most internet-stuff like email is) there is no beautifier. - if a want to generate java-code most beautifiers only work on the complete compilation-unit. where as i sometimes only want to generate code-bits for visualization. (like klicking on a uml-model-method-node and seeing the method-signature in java). so what could i do? at the moment the only possebility would be to use #echo# but that would be contrary to my demand to have both the genarator-code and the generated-code clearly visible. #def printMethod(self, meth): #echo $indentfunc(5) public void foo()# #end def this simply doesnt cut it. this is way to close to what could be done in pure python. the following two links are from the python cookbook showing string interpolation. http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52305 so what might be a solution? at the moment i am thinking of three ideas i would like to introduce to you. 1) implicit whitespace removal. implicit whitespace removal means that existing whitespaces are removed and reintroduces from the stream according to the runtime-structural-level during merging the template. !!!EXAMPLE ## all the same as before only in printMethod ## two additional spaces are introduced. #def printMethod(self, meth): ....public $meth.ReturnType $meth.Name() ....{ ......//here the statements go ....} #end def ##here we define the whitespacehandling ##as being two spaces #indention(space=2) #printClass($modelRoot) !!!END EXAMPLE ok i admit this solution might be a little far fetched ;-) 2) explict global whitespacehandling introducing a new directive that tells cheetah to ignore leading whitespaces and instead insert the actual defined whitespaces. the directive should support two modes absolute insertion and relative !!!SOURCE #def printClass(self, cls): ..class $cls.Name ..{ ....#foreach($child in $cls.Children): ......##increment indentention for one tab ......##could also be #indent++ ......#indent(inc=1) ......//inner classes ......#printClass($child) ......#indent-- ....#end for ....#foreach($method in cls.Methods): ......#indent++ ......//method implementations ......#printMethod($method) ......#indent-- ....#end for ..} #end def #def printMethod(self, meth): ..public $meth.ReturnType $meth.Name() ..{ ....#indent++ ....//here the statements go ....#indent-- ..} #end def ##begin indention at absolut columnpos 0. #indent(absolut=0) #printClass($modelRoot) !!!END SOURCE 3) preprocessor this is probably the solution, that is most easely done. make a pluggable preprocessor that gets handled the stream before it is compiled. then both version one and two could get implemented by the user of cheetah. this is possible to a degree even at the moment but only for the root-template (the template i explictly feed to the template class). templates being loaded by #include or by extending the template are not accessible that way. i guess thats all for now (seems this post has become much longer that anticipated before). ciao robertj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: <ir...@ms...> - 2002-05-25 17:48:59
|
On Sat, May 25, 2002 at 03:13:26PM +0200, rob...@ya... wrote: > being absent for sometime, cause i was looking > for a more "pure" java templating solution (aka velocity) > i now return ashamed (cheetah is so much more poweful). <diabolical laugh> Robert, thanks for your excellent description of the problems Cheetah's whitespace handling is causing you, and your suggestions. However, there is a tradeoff between whitespace handling in these cases and Cheetah's other syntax features, and we cannot resolve it to everybody's complete satisfaction. > generally i want to generate code (mostly java and python). And we want Cheetah to be a general templating solution for these cases too (but see below). > !!!SOURCE > #def printClass(self, cls): > ..class $cls.Name > ..{ > ....#foreach($child in $cls.Children): > ......//inner classes > ......#printClass($child) > ....#end for > > ....#foreach($method in cls.Methods): > ......//method implementations > ......#printMethod($method) > ....#end for > ..} > #end def I have also discovered it's a pain to do nested clauses in Cheetah. You can't indent the directives because the indentation will be output. On the other hand, maybe you *want* that. Cheetah doesn't know, so it assumes that all indentations should be sent to output. One possible response is that Cheetah simply wasn't designed to make complex nesting of loops readable. See section 11.2 ("When to use Python methods") in the Users' Guide. There are tradeoffs both ways. In my current project, I use a Python method whenever I have more than one or two 1-level or 2-level if/for constructs. The tradeoff is that in a Python method you can't access the searchList concisely (so pass all searchList items as method arguments), and you can't just print something and have it concatenate onto the output (so use a StringIO object). Another possible response is to make Cheetah's whitespace handling more flexible, as you suggest below. > at the moment the only possebility would be to use #echo# > but that would be contrary to my demand to have both > the genarator-code and the generated-code clearly visible. > > #def printMethod(self, meth): > #echo $indentfunc(5) public void foo()# > #end def > this simply doesnt cut it. especially since it's *less* readable than the equivalent Python methods: def printMethod(self, meth, indentfunc): indent = indentfunc(5) expr = "public void %s()" % meth return indent + expr def printMethod(self, meth, indentfunc): sio = StringIO() sio.write( indentfunc(5) ) sio.write("public void(") sio.write(meth) sio.write(")") return sio.getValue() $printMethod("foo", $indentfunc) # Or define 'indentfunc' globally in the module containing # printMethod. BTW, I don't think that method you wrote will work. Try: #def printMethod($meth) #echo $indentfunc(5)#public void ${foo}() #end def 1) 'self' should not be specified on the #def line. It's automatic, and it's already defined in the searchList. Perhaps Tavis has code to handle either 'self' or no 'self', I'm not sure. 2) You cannot put literal text in an echo statement. Instead you'd have to use a quoted string and the "+" operator. So I moved the end of the echo statement to the end of the indentfunc call. > 1) implicit whitespace removal. > implicit whitespace removal means that existing > whitespaces are removed and reintroduces from the > stream according to the runtime-structural-level > during merging the template. > > !!!EXAMPLE > ## all the same as before only in printMethod > ## two additional spaces are introduced. > #def printMethod(self, meth): > ....public $meth.ReturnType $meth.Name() > ....{ > ......//here the statements go > ....} > #end def > > ##here we define the whitespacehandling > ##as being two spaces > #indention(space=2) This could almost be done with a compiler setting: #compiler indentation = 2 #compiler indentation = 4 #compiler reset which would just compile to: write(" ") write(" ") whenever Cheetah sees a new line. But what about placeholders that output multiple lines? Would it have to catch those lines and indent them too? > 2) explict global whitespacehandling > introducing a new directive that tells > cheetah to ignore leading whitespaces and instead > insert the actual defined whitespaces. > the directive should support two modes > absolute insertion and relative Isn't that the same thing? > 3) preprocessor > this is probably the solution, that is most easely done. > make a pluggable preprocessor that gets handled the > stream before it is compiled. then both version one and > two could get implemented by the user of cheetah. this > is possible to a degree even at the moment but only for > the root-template (the template i explictly feed to the > template class). templates being loaded by #include or > by extending the template are not accessible that way. Tavis will have to answer that. A feature I've suggested in the past is a #sed directive, which would take one of the output filters (#filter filters) but apply it to each line of the final output rather than to each placeholder. The initial goal was to strip each line of leading/trailing whitespace, but it could also add indentation. It was never implemented because it seems more work than it's worth. If you look at a .py template module and the Template and Servlet classes, it already does some complicated magic. Every placeholder has two nested function calls (filter + the NameMapper call + possibly nested NameMapper calls) #def methods are essentially subtemplates. #errorCatcher wraps every placeholder in a method that does try/except in case the value is missing -- which is why #errorCatcher is so slow. To implement '#compiler indent = 2" or "#sed Indent(2)" and have it handle multiline placeholder values properly, you'd pretty much have to go the way of #errorCatcher, I think, and divert all the code it applies to into a separate method, get the output, split it into lines, and then run the filter on each line. A recipe for complicated programming, possible bugs, and slow performance. For a feature that may not be widely used. To indent the entire template output, one can just pipe it into 'sed' itself, or into a Python script that does the indenting. But that wouldn't help indent portions of the output differently. Perhaps we could have a compiler setting: #compiler noindent-directives True that ignores whitespace before directives. Then you could do: #for ... #if ... #end if #end for But what if a certain line *wants* whitespace before a directive? Changing compiler settings frequently is too verbose. Perhaps we could make an exception for #slurp, and say that "[spaces]#slurp" always means indent. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: <rob...@ya...> - 2002-05-26 17:49:21
|
hi, > <diabolical laugh> yeah i know. it serves ne right. <sigh> > And we want Cheetah to be a general templating solution for > these cases too (but see below). doesnt that include whitespace-aware solutions too? imo the available solutions (that is cheetah too) are only good at generating tagged-output, that is xml, html and the like. the only solution that does realy allow for almost ok (not realy good) whitespace-handling is mysteriously xsl. but this is obviously contrary to my demand not to be to verbose. > I have also discovered it's a pain to do nested clauses in Cheetah. > You can't indent the directives because the indentation will be > output. On the other hand, maybe you *want* that. Cheetah doesn't > know, so it assumes that all indentations should be sent to output. i dont mind being that the standard behaviour. it only hurts not being able to change that behaviour. > One possible response is that Cheetah simply wasn't designed to > make complex nesting of loops readable. See section 11.2 ("When to > use Python methods") in the Users' Guide. uh, uh! that i dont realy like. this very much the same line of argument the velocity-people give when being confronted with this problem. i'd say a "general" templating solution not being able to handle ws and/or indention is simply not well designed. (i guess that was really hard now, wasn't it ;-) ) >There are tradeoffs >both ways. In my current project, I use a Python method whenever >I have more than one or two 1-level or 2-level if/for constructs. >The tradeoff is that in a Python method you can't access the searchList >concisely (so pass all searchList items as method arguments), and you >can't just print something and have it concatenate onto the output (so >use a StringIO object). as i said i would very much prefer to stay within the programming environment (and templating is programming on my part) if possible. even so i must confess it is by far not so hard to switch from cheetah to python, than it is to switch from velocity to java. > Another possible response is to make Cheetah's whitespace handling > more flexible, as you suggest below. i really dont see another possibility when justifing cheetah as a "general" solution. > especially since it's *less* readable than the equivalent > Python methods: > def printMethod(self, meth, indentfunc): > indent = indentfunc(5) > expr = "public void %s()" % meth > return indent + expr > > def printMethod(self, meth, indentfunc): > sio = StringIO() > sio.write( indentfunc(5) ) > sio.write("public void(") > sio.write(meth) > sio.write(")") > return sio.getValue() > > $printMethod("foo", $indentfunc) that i dont understand. are you being sacrastic here? i dont think that a pure python solution would be so much less readable. if you imagine a callable object,that is being inited with with the module and that nows how to interpolate a string it could look like this. class Echo: def __init__(self, _map, _output = DefaultStream, _indent = 0): self.Map = _map self.Output = _output self.Indent = _indent def __call__(self, _istr, **kw): ## interpolates the string with the map and append ## the indention to write to the output def inc(self, _size=1): self.Indent += _size def dec(self, _size=1): self.Indent -= _size echo = Echo({"root": umlmodel.class}) ## this is the business-method. def printMethod(self, meth): echo.inc() echo("public void $meth()", methoddef = meth) echo.dec() i dont think, that this is less readable that the cheetah solution using #echo. with python 2.2 it should almost be possible to get rid of the keyword-arguments (guess that might be a nice pattern i have to explore in more detail). > 1) 'self' should not be specified on the #def line. It's automatic, > and it's already defined in the searchList. Perhaps Tavis has code > to handle either 'self' or no 'self', I'm not sure. i must admit i have only tinkered with cheetah in the last few days and what i have written is almost only knowledge from the very proffesional docs that are available (once again one more point where you guys shine in contrast to v.) > 2) You cannot put literal text in an echo statement. Instead you'd > have to use a quoted string and the "+" operator. So I moved the > end of the echo statement to the end of the indentfunc call. ah, i see. > > > 1) implicit whitespace removal. > > implicit whitespace removal means that existing > > whitespaces are removed and reintroduces from the > > stream according to the runtime-structural-level > > during merging the template. > This could almost be done with a compiler setting: > > #compiler indentation = 2 > #compiler indentation = 4 > #compiler reset > > which would just compile to: > > write(" ") > write(" ") i guess you misunderstood my solution. what i was proposing is that cheetah always knows during runtime within which actual indention level it is and removes the whitespaces according to this level. or to put it another way: cheetah knows the stack and at which indention level it is at the the current stack position. (maybe you now anderstand why i said it might be a _little_ far fetched ;-) ) > whenever Cheetah sees a new line. But what about placeholders that > output multiple lines? Would it have to catch those lines and > indent them too? that is simply something i havent thought about i must admit. simply because, that does not happen with code i write. the solution might be to have more indention-directives. one for simple indent, one for placeholder-interpolation and one for both. > > 2) explict global whitespacehandling > > introducing a new directive that tells > > cheetah to ignore leading whitespaces and instead > > insert the actual defined whitespaces. > > the directive should support two modes > > absolute insertion and relative > > Isn't that the same thing? nope. see above. > > 3) preprocessor > > this is probably the solution, that is most easely done. > > make a pluggable preprocessor that gets handled the > > stream before it is compiled. then both version one and > > two could get implemented by the user of cheetah. this > > is possible to a degree even at the moment but only for > > the root-template (the template i explictly feed to the > > template class). templates being loaded by #include or > > by extending the template are not accessible that way. > > Tavis will have to answer that. > > A feature I've suggested in the past is a #sed directive, > which would take one of the output filters (#filter filters) > but apply it to each line of the final output rather than > to each placeholder. my preference would not be to make postprocessor, cause it the resulting text might be more complicated to parse than the original generator-code. >The initial goal was to strip each line of >leading/trailing whitespace, but it could also add indentation. It was >never implemented because it seems more work than it's worth. >If you look at a .py template module and the Template and Servlet >classes, it already does some complicated magic. Every >placeholder has two nested function calls (filter + the >NameMapper call + possibly nested NameMapper calls) >#def methods are essentially subtemplates. #errorCatcher >wraps every placeholder in a method that does try/except >in case the value is missing -- which is why #errorCatcher is >so slow. i have looked a little bit around but its hard to grasp the innerworks of cheetah without something like a architectural blueprint. > To implement '#compiler indent = 2" or "#sed Indent(2)" and > have it handle multiline placeholder values properly, you'd > pretty much have to go the way of #errorCatcher, I think, and > divert all the code it applies to into a separate method, get > the output, split it into lines, and then run the filter on each > line. A recipe for complicated programming, possible bugs, and > slow performance. For a feature that may not be widely used. slow performance is not so much of an issues within the realm of code-generation as it might be for web-apps. > To indent the entire template output, one can just pipe it into > 'sed' itself, or into a Python script that does the indenting. > But that wouldn't help indent portions of the output differently. this i dont want to do cause sed might not be available on the system at hand or might not be accessible. > But what if a certain line *wants* whitespace before a directive? > Changing compiler settings frequently is too verbose. Perhaps we > could make an exception for #slurp, and say that > "[spaces]#slurp" always means indent. i'd say we would need the possibility to set whitespacehandling either blockwise or linewise. something like that #indent(4) ##indention is now 4 spaces for for every single line in the outputstream ..#for ....#if ......#indent(2) ##indent is now only 2 spaces ......#ws(10)#FOOBAR ##indent FOOBAR with 10 spaces ....#end if ..#for #indent(default) ciao robertj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: <ir...@ms...> - 2002-05-26 19:15:08
|
On Sun, May 26, 2002 at 07:51:13PM +0200, rob...@ya... wrote: > > One possible response is that Cheetah simply wasn't designed to > > make complex nesting of loops readable. See section 11.2 ("When to > > use Python methods") in the Users' Guide. > uh, uh! that i dont realy like. this very much the same line of > argument the velocity-people give when being confronted with > this problem. i'd say a "general" templating solution not being > able to handle ws and/or indention is simply not well designed. > (i guess that was really hard now, wasn't it ;-) ) Off the top of my head, Cheetah's priorities are (in order): 1) provide templating for Webware servlets 2) provide templating for other HTML output 3) provide SIMPLE display logic. This is why the directives exist. Of course, "simple" is in the eye of the beholder. 4) The language should be easy to understand and teach, and it should be easy to look at a construct and immediately know how Cheetah will interpret it. 5) Add features that help conciseness and readability in the templates. 6) Clean coding. 7) Add features to make Cheetah usable in other situations (Python/ Java generation in this case), as long as they don't conflict with the other priorities. Not conflicting means the features must not interfere with Webware/HTML output, cause negligable performance penalty if not used, be implementable cleanly and straightforwardly, and not make the template harder to interpret (by the human maintainer). > i really dont see another possibility when justifing cheetah as a > "general" solution. You can't please everybody. If we make an effort to make it usable in a variety of situations, it's a "general" solution. > > especially since it's *less* readable than the equivalent > > Python methods: > > > def printMethod(self, meth, indentfunc): > > indent = indentfunc(5) > > expr = "public void %s()" % meth > > return indent + expr > > > > def printMethod(self, meth, indentfunc): > > sio = StringIO() > > sio.write( indentfunc(5) ) > > sio.write("public void(") > > sio.write(meth) > > sio.write(")") > > return sio.getValue() > > > > $printMethod("foo", $indentfunc) > that i dont understand. are you being sacrastic here? > i dont think that a pure python solution would be > so much less readable. No, I'm not sarcastic. "Readable" in this case is perhaps in the eye of the beholder. I'd say the sio.write method is the most readable, because you can go down line by line and see quickly what it's outputting each line, and imagine each chunk being output visually. The other strategies are more abstract. The $printMethod line was just to show how to call it from a template. I wouldn't necessarily handle indentation through 'indentfunc' this way, but I was copying your code as closely as possible. > if you imagine a callable object,that is being inited > with with the module and that nows how to interpolate > a string it could look like this. > > class Echo: > def __init__(self, _map, _output = DefaultStream, _indent = 0): > self.Map = _map > self.Output = _output > self.Indent = _indent > def __call__(self, _istr, **kw): > ## interpolates the string with the map and append > ## the indention to write to the output > def inc(self, _size=1): > self.Indent += _size > def dec(self, _size=1): > self.Indent -= _size > > echo = Echo({"root": umlmodel.class}) > > ## this is the business-method. > def printMethod(self, meth): > echo.inc() > echo("public void $meth()", methoddef = meth) > echo.dec() > > i dont think, that this is less readable that the cheetah > solution using #echo. That's another possibility. Perhaps we can do something with those .inc() and .dec() methods. I'm not fond of that 'Echo' class though, simply because Cheetah is already complicated enough in terms of echoing output, and I don't think one wants another complicating layer, especially one with a similar name as a directive. Also, Cheetah's convention is for methods to return all their output, not to output it incrementally to a stream. Although it's true that would be convenient for some methods. Hmm, what if we sneak a stringio wrapper method into Servlet? Python methods that want to output incrementally to a stream could be called from that: $stringio($realFunc, $*args, $**kw) def stringio(self, realFunc, *args, **kw): sio = StringIO() args = (sio.write ,) + args returnval = apply(realFunc, args, kw) if returnval not in (None, ''): raise RuntimeError("realFunc mustn't return anything") return sio.getvalue() def realFunc(self, write, ..args as desired.. ): write('A') write('B') I might just implement that since it's so simple. > with python 2.2 it should almost be possible to get rid > of the keyword-arguments (guess that might be a nice > pattern i have to explore in more detail). What do you mean by this? We're definitely not implementing 2.2's property or __slots__ objects anytime soon, since they are so experimental. > > 2) You cannot put literal text in an echo statement. Instead you'd > > have to use a quoted string and the "+" operator. So I moved the > > end of the echo statement to the end of the indentfunc call. > ah, i see. In fact the argument to #echo is a Python expression, just with $ before the variable names. > i guess you misunderstood my solution. what i was proposing is > that cheetah always knows during runtime within which actual > indention level it is and removes the whitespaces according to > this level. or to put it another way: cheetah knows the stack > and at which indention level it is at the the current stack > position. This might be possible, but we'd need a much more precise implementation spec. Really, it'd be up to Tavis, since he's the only one with enough expertise to write it. > > whenever Cheetah sees a new line. But what about placeholders that > > output multiple lines? Would it have to catch those lines and > > indent them too? > that is simply something i havent thought about i must admit. simply > because, that does not happen with code i write. the solution > might be to have more indention-directives. one for simple indent, > one for placeholder-interpolation and one for both. Upon contemplation, I'd say we should NOT try to do indentation inside placeholder values. If the user wants that, s/he can write a Filter. Perhaps the filter can read the current indentation level through the compiler setting and act accordingly. > i have looked a little bit around but its hard to grasp > the innerworks of cheetah without something like a architectural > blueprint. The Developers' Guide tries to explain it at a behavioral level. That should be enough to get you started. It needs an overview of the different modules/classes and how they interact, but I haven't had the time to research and write it. Would you like to help with this? Essentially, one has to follow all the calls in Template.__init__ and Template.respond recursively and see what they do, and then describe it in an overview. Then do the same for cheetah-compile. That will lead through the lexer, parser and compiler. I don't think we care about the intermediate low-level details: just the first part (how the lexer determines which characters form a placeholder, or a directive expression) and the last part (how the compiler converts each directive into Python). > #indent(4) ##indention is now 4 spaces for for every single line in the > outputstream > ..#for > ....#if > ......#indent(2) ##indent is now only 2 spaces > ......#ws(10)#FOOBAR ##indent FOOBAR with 10 spaces > ....#end if > ..#for > #indent(default) As you said before, automatically indenting and dedenting would be preferable to #indent(2). -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: <rob...@ya...> - 2002-05-27 08:54:40
|
hi mike, > Off the top of my head, Cheetah's priorities are (in order): > 1) provide templating for Webware servlets > 2) provide templating for other HTML output > 3) provide SIMPLE display logic. This is why the directives exist. > Of course, "simple" is in the eye of the beholder. > 4) The language should be easy to understand and teach, and it should > be easy to look at a construct and immediately know how Cheetah > will interpret it. > 5) Add features that help conciseness and readability in the > templates. > 6) Clean coding. > 7) Add features to make Cheetah usable in other situations (Python/ > Java generation in this case), as long as they don't conflict > with the other priorities. so then it is obviously a tagging/web-based solution primary. isn't it? ;-) > Not conflicting means the features must not interfere with Webware/HTML > output, cause negligable performance penalty if not used, be > implementable cleanly and straightforwardly, and not make the template > harder to interpret (by the human maintainer). oh, i can signed that too. i wouldnt mind having a slower implemetation for whitespaceaware solutions (aka codegeneration). basicly cause execution speed is of no concern. at least as long i dont generate complete runnable programms from any uml-model. > You can't please everybody. If we make an effort to make it usable > in a variety of situations, it's a "general" solution. isn't your definition of "variety" somehow very tight? <g> > No, I'm not sarcastic. "Readable" in this case is perhaps in the > eye of the beholder. I'd say the sio.write method is the most > readable, because you can go down line by line and see quickly > what it's outputting each line, and imagine each chunk being > output visually. The other strategies are more abstract. that is right, but as i said the reason for using a templating system is to have both the generator-code and the generated-code easely visible. > That's another possibility. Perhaps we can do something with > those .inc() and .dec() methods. I'm not fond of that 'Echo' > class though, simply because Cheetah is already complicated > enough in terms of echoing output, and I don't think one wants > another complicating layer, especially one with a similar name > as a directive. Also, Cheetah's convention is for methods to > return all their output, not to output it incrementally to a > stream. Although it's true that would be convenient for some > methods. my echo-solution wasn't meant for incooperation into cheetah but more for illustration-purposes of how one could build a "pure" python solution. > Hmm, what if we sneak a stringio wrapper method into Servlet? that i dont understand? what is the sevlet within that context? > $stringio($realFunc, $*args, $**kw) > > def stringio(self, realFunc, *args, **kw): > sio = StringIO() > args = (sio.write ,) + args > returnval = apply(realFunc, args, kw) > if returnval not in (None, ''): > raise RuntimeError("realFunc mustn't return anything") > return sio.getvalue() > > def realFunc(self, write, ..args as desired.. ): > write('A') > write('B') actually i wouldn't do that and i don't like it. i don't like it cause i don't want to explictly escape to python from cheetah. if i had to do this i'd rather try to escape from cheetah completly. the explanation for this is that i simply would introduce new subsystem into my solution only if and _only_ if those subsystem do yield an obvious benefit. if i would use cheetah and had to escape to python so often due the ws-issues i would simply scratch cheetah (as i have done with velo - i'll explain that just in a minute). what is realy sad at the moment (but by no means a complete knock out) ist that cheetah is so powerful at all the other fronts (oo, modules etc.). everything i need and expect from my programming environment is there and defenitly no reason to escape to python when "only" doing webbased stuff. back to the subsystem stuff. for every subsystem i do introduce into my solution my design will get more brittle. it is completely irrelevant if the introducing ssys is good design. simply the fact of being there endangers the stability of any solution. so my problem is that i have a java solution what i now introduce is at first jython and the on top cheetah. this will make my system defenitly harder to handle. programmingwise as deploymentwise. the reason i scratched velocity was simply that it was a new subsystem that didnt gave much of a benefit. > > with python 2.2 it should almost be possible to get rid > > of the keyword-arguments (guess that might be a nice > > pattern i have to explore in more detail). > What do you mean by this? We're definitely not implementing > 2.2's property or __slots__ objects anytime soon, since they > are so experimental. no but one could build a metaclasse that intercepts every method lookup gets the names and values of the parameters puts it into a dict sets the to the echo-instance and then calls the method. so one coud simply write: def foo(self, bar, baz): self.echo("that is $bar and that is $baz") wouldn't be exactly fast as hell, due the constant lookups. > > i guess you misunderstood my solution. what i was proposing is > > that cheetah always knows during runtime within which actual > > indention level it is and removes the whitespaces according to > > this level. or to put it another way: cheetah knows the stack > > and at which indention level it is at the the current stack > > position. > > This might be possible, but we'd need a much more precise > implementation spec. Really, it'd be up to Tavis, since he's the > only one with enough expertise to write it. that might be somehow possible but i dont know if it's really feasable cause sometime one might want to escape from that too. > Upon contemplation, I'd say we should NOT try to do indentation > inside placeholder values. If the user wants that, s/he can write > a Filter. Perhaps the filter can read the current indentation level > through the compiler setting and act accordingly. i'd say one should be able to steer that that it pleases her/him. but best being steered from within cheetah. that is using directives. > The Developers' Guide tries to explain it at a behavioral level. > That should be enough to get you started. It needs an overview of > the different modules/classes and how they interact, but I haven't > had the time to research and write it. Would you like to help with > this? i can try. but at the moment i am writing two articles (one about configuration in .net and one about a pattern/process in java). and i think of maybe (but this is a big maybe) of giving a talk on euro-python. but this is just a ridiclious idea at the moment and will certainly break due the time-constraits. but if i do cheetah is on the list of themes ;-) >Essentially, one has to follow all the calls in Template.__init__ >and Template.respond recursively and see what they do, and then describe >it in an overview. Then do the same for cheetah-compile. That will >lead through the lexer, parser and compiler. I don't think we care >about the intermediate low-level details: just the first part (how the >lexer determines which characters form a placeholder, or a directive >expression) and the last part (how the compiler converts each directive >into Python). what i can do is to read and try to get into cheetah and then give you feedback. > > #indent(4) ##indention is now 4 spaces for for every single line in the > > outputstream > > ..#for > > ....#if > > ......#indent(2) ##indent is now only 2 spaces > > ......#ws(10)#FOOBAR ##indent FOOBAR with 10 spaces > > ....#end if > > ..#for > > #indent(default) > > As you said before, automatically indenting and dedenting would be > preferable to #indent(2). as i said i'd prefer the this solution cause one has complete power of whitespaces and does not need to depend on implicit handling that might not work for him/her. ciao robertj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: <ir...@ms...> - 2002-05-27 15:01:52
|
On Mon, May 27, 2002 at 10:55:11AM +0200, rob...@ya... wrote: > so then it is obviously a tagging/web-based solution primary. > isn't it? ;-) It's obviously a web-based solution primarily, yes. I'm not sure what you mean by "tagging". If there happen to be tags in the template, they are output. If there aren't, they aren't. > > You can't please everybody. If we make an effort to make it usable > > in a variety of situations, it's a "general" solution. > isn't your definition of "variety" somehow very tight? <g> It's been tested with Servlets, HTML, text, articles, etc. Theoretically it could work with SQL output, Postscript, code generation, etc. But for each type of use, we need somebody in the real world to try it out and note the unique challenges, which you are doing. That's why Cheetah is not at 1.0 yet, so we have more flexibility to modify it for real-world situations. With high-demand web servers, the problem is not being able to share template instances across threads, and thus not being able to share #cache regions across threads. For code output, the problem is indentation. For multilingual use, there are problems of localization as the $_('text') guy posted today, and there are no doubt other i18n, l10n issues too that we don't know about yet. > > Hmm, what if we sneak a stringio wrapper method into Servlet? > that i dont understand? what is the sevlet within that context? Servlet in Cheetah tends to be the dumping ground for miscellaneous convenience features. It's inherited by Template. It uses a real Webware.Transaction object if it can find one (that is, if the template was called from Webware); otherwise it uses a dummy Transaction object to satisfy the inheritance. We could just as easily put .stringio into Template instead, or make a separate mixin for miscellaneous stuff. > > def realFunc(self, write, ..args as desired.. ): > > write('A') > > write('B') > actually i wouldn't do that and i don't like it. i don't > like it cause i don't want to explictly escape to python from > cheetah. if i had to do this i'd rather try to escape from > cheetah completly. Well, I would have found it useful in an application I was working on last week, but I hadn't thought about it then. I personally don't have any problem with keeping simple methods directly in the template itself but moving them into Python if they become more complicated. > back to the subsystem stuff. for every subsystem i do introduce > into my solution my design will get more brittle. I completely understand that. You'll have to decide whether Cheetah is for you. In my case, I'm going from a hodgepodge of nested %-operator format blocks and files with %(key)s syntax (don't forget to double all literal "%%" or you'll get "TypeError: not enough arguments for format string"), so Cheetah is definitely a big advantage. > > > with python 2.2 it should almost be possible to get rid > > > of the keyword-arguments (guess that might be a nice > > > pattern i have to explore in more detail). > no but one could build a metaclasse that intercepts every method > lookup gets the names and values of the parameters puts it into > a dict sets the to the echo-instance and then calls the method. > > so one coud simply write: > > def foo(self, bar, baz): > self.echo("that is $bar and that is $baz") > > wouldn't be exactly fast as hell, due the constant > lookups. I still don't understand. Python 2.2 doesn't do variable interpolation. It's only been proposed for the future. http://www.python.org/peps/pep-0215.html > > > #indent(4) ##indention is now 4 spaces for for every single line in the > > > outputstream > > > ..#for > > > ....#if > > > ......#indent(2) ##indent is now only 2 spaces > > > ......#ws(10)#FOOBAR ##indent FOOBAR with 10 spaces > > > ....#end if > > > ..#for > > > #indent(default) > > > > As you said before, automatically indenting and dedenting would be > > preferable to #indent(2). > as i said i'd prefer the this solution cause one has complete > power of whitespaces and does not need to depend on implicit > handling that might not work for him/her. You would? In that case we could just as easily offer both. I suppose what we're looking at now is: 1) #compiler indentString = ' ' ## String to use for each indent level (to accommodate ## spaces, tabs, "..." prefixes, "> " prefixes, etc). 2) #compiler indentAuto True ## Turn on autoindentation. Every '#D...#end D' pair ## causes an indent level inside it. When indent level ## > 0, remove all leading whitespace from each line and ## add 'indentString * indentLevel'. 3) #indent, #dedent, '#indent reset' ## Increment/decrement the indentation level arbitrarily, ## or set it to zero. But I'd rather not encourage the ## multiplication of directives. Perhaps ## '#compiler indent'? 4) #filter AutoIndentFilter ## Make autoindentation apply inside multiline placeholder ## values too. This would allow only one type of indentation at a time. E.g., it's either spaces or tabs or "> " prefixes, but not a combination. That wouldn't do; e.g., for nested quoting of an e-mail message inside several blockquote levels, for instance. But it would work in many cases. That's what I mean by, you can make a general solution for a variety of cases but it still might not please everybody. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: <rob...@ya...> - 2002-05-27 16:58:46
|
hi mike, > It's obviously a web-based solution primarily, yes. I'm not sure what > you mean by "tagging". If there happen to be tags in the template, they > are output. If there aren't, they aren't. a solution that relies on some kind of tagging-system to be interpreted by an output system the most prominent being html and a browser. > It's been tested with Servlets, HTML, text, articles, etc. > Theoretically it could work with SQL output, Postscript, code > generation, etc. But for each type of use, we need somebody in the > real world to try it out and note the unique challenges, which you > are doing. That's why Cheetah is not at 1.0 yet, i wouldn't wait any longer for cheetah to be released as 1.0. as other solutions are for less flexible than cheetah is at the moment. other (no so obvious) demands could be incoorporated later on. even so that might mean breaking backward compatibillity. i think this overrated anyhow. the only thing one would need to switch back to an older mode. >so we have more > flexibility to modify it for real-world situations. With high-demand > web servers, the problem is not being able to share template > instances across threads, and thus not being able to share #cache > regions across threads. For code output, the problem is indentation. > For multilingual use, there are problems of localization as the > $_('text') guy posted today, and there are no doubt other i18n, l10n > issues too that we don't know about yet. sure, but i guess you guys won't be ready then anytime. cause the more people are going to use cheetah the more problems willshow up. so just go forward release 1.0 and think about a way on how to drive the evolution of cheetah (i think the python way import __future__ is a nice way to do so). > Well, I would have found it useful in an application I was working > on last week, but I hadn't thought about it then. I personally > don't have any problem with keeping simple methods directly in the > template itself but moving them into Python if they become more > complicated. as said before i prefer stayed with what i am. > I completely understand that. You'll have to decide whether > Cheetah is for you. In my case, I'm going from a hodgepodge > of nested %-operator format blocks and files with %(key)s > syntax (don't forget to double all literal "%%" or you'll get > "TypeError: not enough arguments for format string"), so > Cheetah is definitely a big advantage. yep but problematic in other ways. > I still don't understand. Python 2.2 doesn't do variable > interpolation. It's only been proposed for the future. > http://www.python.org/peps/pep-0215.html nope. but one could use the recipe from the cookbook from alex martelli).that was one of the links i posted earlier. > You would? In that case we could just as easily offer both. > I suppose what we're looking at now is: > > 1) #compiler indentString = ' ' > ## String to use for each indent level (to accommodate > ## spaces, tabs, "..." prefixes, "> " prefixes, etc). > 2) #compiler indentAuto True > ## Turn on autoindentation. Every '#D...#end D' pair > ## causes an indent level inside it. When indent level > ## > 0, remove all leading whitespace from each line and > ## add 'indentString * indentLevel'. > 3) #indent, #dedent, '#indent reset' > ## Increment/decrement the indentation level arbitrarily, > ## or set it to zero. But I'd rather not encourage the > ## multiplication of directives. Perhaps > ## '#compiler indent'? > 4) #filter AutoIndentFilter > ## Make autoindentation apply inside multiline placeholder > ## values too. > > This would allow only one type of indentation at a time. E.g., it's > either spaces or tabs or "> " prefixes, but not a combination. That > wouldn't do; e.g., for nested quoting of an e-mail message inside > several blockquote levels, for instance. But it would work in many > cases. That's what I mean by, you can make a general solution for > a variety of cases but it still might not please everybody. something like that would be perfectly ok with me (maybe the directive could be shorter). ciao robertj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: <ir...@ms...> - 2002-05-27 18:08:34
|
On Mon, May 27, 2002 at 06:58:12PM +0200, rob...@ya... wrote: > > It's obviously a web-based solution primarily, yes. I'm not sure what > > you mean by "tagging". If there happen to be tags in the template, they > > are output. If there aren't, they aren't. > a solution that relies on some kind of tagging-system to be > interpreted by an output system the most prominent being html and > a browser. Then no, it's not intentionally a tagging system. It just happens that its most common output format (HTML) is tagged. > > 1) #compiler indentString = ' ' > > ## String to use for each indent level (to accommodate > > ## spaces, tabs, "..." prefixes, "> " prefixes, etc). > > 2) #compiler indentAuto True > > ## Turn on autoindentation. Every '#D...#end D' pair > > ## causes an indent level inside it. When indent level > > ## > 0, remove all leading whitespace from each line and > > ## add 'indentString * indentLevel'. > > 3) #indent, #dedent, '#indent reset' > > ## Increment/decrement the indentation level arbitrarily, > > ## or set it to zero. But I'd rather not encourage the > > ## multiplication of directives. Perhaps > > ## '#compiler indent'? > > 4) #filter AutoIndentFilter > > ## Make autoindentation apply inside multiline placeholder > > ## values too. Actually, if you have auto indent, would you need #indent and #dedent at all? -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: <rob...@ya...> - 2002-05-27 18:53:18
|
hi mike, > Then no, it's not intentionally a tagging system. It just happens > that its most common output format (HTML) is tagged. isnt that the difference between theory and practice? ;-) practically it is so, that most templating systems do have a really hard time to serve whitespace-aware solutions. where we can divide ws-aware solutions into two subcategories solutions where it simply inconvinient to have no control about ws (java, sql) and solutions where it simply generates errors (python, nearly all internet stuff like emali, http-headers etc.) > > > > 1) #compiler indentString = ' ' > > > ## String to use for each indent level (to accommodate > > > ## spaces, tabs, "..." prefixes, "> " prefixes, etc). > > > 2) #compiler indentAuto True > > > ## Turn on autoindentation. Every '#D...#end D' pair > > > ## causes an indent level inside it. When indent level > > > ## > 0, remove all leading whitespace from each line and > > > ## add 'indentString * indentLevel'. > > > 3) #indent, #dedent, '#indent reset' > > > ## Increment/decrement the indentation level arbitrarily, > > > ## or set it to zero. But I'd rather not encourage the > > > ## multiplication of directives. Perhaps > > > ## '#compiler indent'? > > > 4) #filter AutoIndentFilter > > > ## Make autoindentation apply inside multiline placeholder > > > ## values too. > > Actually, if you have auto indent, would you need #indent and > #dedent at all? this is a little bit hard. let me phrase it this way. i would go for an automatic solution if it would do exactly what i want. i simply do not belive that this is feasable technically and conceptually. this is cause i am not sure that my demands are allways fully consistent within themselfs. so a solution that gives me the full power of wsh is better cause it is safer. ciao robertj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: Tavis R. <ta...@re...> - 2002-05-27 19:58:37
|
Hi Robert, On May 25, 2002 06:13 am, rob...@ya... wrote: > being absent for sometime, cause i was looking > for a more "pure" java templating solution (aka velocity) > i now return ashamed (cheetah is so much more poweful). good to hear :) Do you have any other observations from your experience = with=20 Velocity that could help improve Cheetah? Before I get into the details, thanks for the excellent overview of the=20 problem! =20 > generally i want to generate code (mostly java and python). > i dont work within any jsp/psp or whatever context. =2E.. > when writing the code i want to this be facts to be true > a) the generatorcode (that is the cheetah-source) > must be indented properly. showing the structure of > the code. this is something cheetah > does anyway cause of its python heritage. > b) the generated code (that is not the resulting code > but the code embedded within the cheetah code) must > be indented properly too. > so that i can see both the structure of the generator > _AND_ the structure of the result (to be). =2E.. [Java code-generation example] ... > this output might not be very visually pleasing > but anyhow it is valid compilable java-code. and > could use a beautifier to get it right. > hmm. not so fast! > > the problems with this are: > - if i want to generate python code the beautifier-solution > will possibly not work - or might generate code that > does not what was intended. > - if i want to generate other whitespace-aware results > (most internet-stuff like email is) there is no > beautifier. > - if a want to generate java-code most beautifiers only > work on the complete compilation-unit. where as i > sometimes only want to generate code-bits for visualization. > (like klicking on a uml-model-method-node and seeing the > method-signature in java). > so what might be a solution? > at the moment i am thinking of three ideas i would like > to introduce to you. > > 1) implicit whitespace removal. =2E.. > ok i admit this solution might be a little far fetched ;-) I agree, this sounds too ambitious. > 2) explict global whitespacehandling > introducing a new directive that tells > cheetah to ignore leading whitespaces and instead > insert the actual defined whitespaces. > the directive should support two modes > absolute insertion and relative Would you do this at compile-time or run-time? > 3) preprocessor > this is probably the solution, that is most easely done. > make a pluggable preprocessor that gets handled the > stream before it is compiled. then both version one and > two could get implemented by the user of cheetah. this > is possible to a degree even at the moment but only for > the root-template (the template i explictly feed to the > template class). templates being loaded by #include or > by extending the template are not accessible that way. Options 2 (assuming compile-time execution) and 3 are essentially the sam= e. =20 They only vary in syntax and implementation details. Thus, I see the options as: a) compile-time preprocessing of the Cheetah source b) run-time postprocessing of the Cheetah output Option (a) can't deal with output that comes from $methods or #includes.=20 Option (b) can. I prefer option (b) as I've been bitten by compile-time=20 limitations too many times. Both solutions would require explicit declarations from the template auth= or:=20 i.e. [indent] and [dedent] commands in the source. To be complete, an=20 implementation of either option would also include [set IndentLevel =3D 1= ],=20 [set IndentChars =3D ""], [handleIndentation On] and [handleIndentation O= ff]=20 commands. The syntax here is just an example. Both options are possible without requiring any modification of the Cheet= ah=20 Compiler. Furthermore, if the solution was independent of the Cheetah=20 Compiler it could be used as (a) a preprocessor OR (b) a postprocessor. I= t is=20 also possible to implement both options directly in Cheetah's Compiler. =20 I favour starting with a independent line-based postprocessor with a flex= ible=20 syntax. Once that's implemented we can decide the next step from there. Cheers, Tavis |
From: <rob...@ya...> - 2002-05-28 08:16:25
|
hi tavis, >>good to hear :) Do you have any other observations from your experience with >>Velocity that could help improve Cheetah? nope! besides the technical differences both solutions do have (that is cheetah being python based and therefore inheriting a lot of python goodies and velocity being something completely different) i find the biggest difference is more philosophical in nature. velocity is like it is and there is a lot of resistance for change if there is even the slightest possibillity of breaking backward-compatibility. imo this brings any evolution to a halt. and since velo has a lot irks and quirks (ws-handling and handling if null-refs in $) i think it needs a major conceptual-rework. but is i said there is a lot of resistence against such a stance (the usual argument being - most users of v. are designers, complicating the language wont work for them - i personally dont buy this argument). >> 1) implicit whitespace removal. >>... >> ok i admit this solution might be a little far fetched ;-) >I agree, this sounds too ambitious. maybe you could incoorporate that into version 3.5 ;-) >> 2) explict global whitespacehandling >> introducing a new directive that tells >> cheetah to ignore leading whitespaces and instead >> insert the actual defined whitespaces. >> the directive should support two modes >> absolute insertion and relative >Would you do this at compile-time or run-time? whats the difference? (in cheetahs context of course) >Option (a) can't deal with output that comes from $methods or #includes. >Option (b) can. I prefer option (b) as I've been bitten by compile-time >limitations too many times. as i told mike before, since my code is almost allways structured it such a way that i dont have placeholders that expand to multiple lines i could live with boths ways. >>Both solutions would require explicit declarations from the template author: >>i.e. [indent] and [dedent] commands in the source. To be complete, an >>implementation of either option would also include [set IndentLevel = 1], >>[set IndentChars = ""], [handleIndentation On] and [handleIndentation Off] >>commands. The syntax here is just an example. that is exactly what i had in mind. the automatic indention is simply to dangerous. we could do that if more experience is provided by the usage of the explict declarations. >>Both options are possible without requiring any modification of the Cheetah >>Compiler. Furthermore, if the solution was independent of the Cheetah >>Compiler it could be used as (a) a preprocessor OR (b) a postprocessor. It is >>also possible to implement both options directly in Cheetah's Compiler. >>I favour starting with a independent line-based postprocessor with a flexible >>syntax. Once that's implemented we can decide the next step from there. i'll try your example as soon as possible. ciao robertj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: <ir...@ms...> - 2002-05-28 10:52:47
|
On Tue, May 28, 2002 at 10:08:48AM +0200, rob...@ya... wrote: > >> 2) explict global whitespacehandling > >> introducing a new directive that tells > >> cheetah to ignore leading whitespaces and instead > >> insert the actual defined whitespaces. > >> the directive should support two modes > >> absolute insertion and relative > >Would you do this at compile-time or run-time? > whats the difference? (in cheetahs context of course) > > >Option (a) can't deal with output that comes from $methods or #includes. > >Option (b) can. I prefer option (b) as I've been bitten by compile-time > >limitations too many times. First off, compile time means generating Python source code that's equivalent to the template definition. Run time means running that Python code. There is no searchList at compile time, so you can't do anything that involves looking up placeholder values. The advantage of doing things at compile time is that you do them once no matter how many times the template instance is filled over the lifetime of the application. You can even precompile and factor out the compilation overhead completely. The advantage of doing things at run time is flexibility. In Java, all the attributes of an object are fixed at compile time. In Python, you can add and delete attributes any time you want. Example: we used to do partial placeholder lookup at compile time in the name of efficiency, but found it was too limiting. 1) You couldn't change the types of the placeholder values or the generated Python code would break. 2) The placeholder values had better exist at the time of compilation or you'll get a Not Found error. That prevented common usages where you provide the values at the latest possible moment. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: Tavis R. <ta...@re...> - 2002-05-27 20:35:46
Attachments:
IndentFormatter.py
|
I've attached a very basic implementation of a postprocessor. On May 27, 2002 12:58 pm, Tavis Rudd wrote: > I favour starting with a independent line-based postprocessor with a > flexible syntax. Once that's implemented we can decide the next step f= rom > there. |
From: <rob...@ya...> - 2002-05-28 08:16:30
|
hi tavis, >>I've attached a very basic implementation of a postprocessor. i'll have a look as soon as possible. but at the moment i have to finish this article about .net-config-files and there are other things to do. hopefully latest at friday i will have a closer look. ciao robertj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: <rob...@ya...> - 2002-06-03 11:16:26
|
hi tavis, this works fine so far. i would only suggest making the method format a module-level function and dropping the class. i dont see the need to have an instance holding state. beside the fact that it might cause errors when being called multiple times with the same instance if the indention is not "closed" properly. anyway what is really great on the sources you wrote is that one could see very easely how to extend cheetah by a means of a postprocessor and how one can extend cheetah with own directives. i think that should go into the documentation. ciao robertj ps: i will now go and try to get my code-generator running. i'll report to you all. thanks. ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty ----- Original Message ----- From: "Tavis Rudd" <ta...@re...> To: <rob...@ya...>; "Cheetah Template List" <che...@li...> Sent: Monday, May 27, 2002 10:35 PM Subject: Re: [Cheetahtemplate-discuss] (implict) #indent or preprocessor I've attached a very basic implementation of a postprocessor. On May 27, 2002 12:58 pm, Tavis Rudd wrote: > I favour starting with a independent line-based postprocessor with a > flexible syntax. Once that's implemented we can decide the next step from > there. |
From: Tavis R. <ta...@re...> - 2002-06-04 00:06:39
|
On June 3, 2002 04:11 am, rob...@ya... wrote: > hi tavis, > > this works fine so far. Good. It could also extended to do relative indentation in addition to t= he=20 absolute indents it does now. > i would only suggest making the method > format a module-level function and dropping > the class. i dont see the need to have an > instance holding state.=20 That's just a matter style. I try to stay away from managing state with=20 global vars. Code written that way tends to break easily and is hard to=20 extend. However, one could write a module-level wrapper function that=20 automatically creates the IndentFormatter instance. > anyway what is really great on the sources you > wrote is that one could see very easely how > to extend cheetah by a means of a postprocessor > and how one can extend cheetah with own directives. > > i think that should go into the documentation. > ----- Original Message ----- > From: "Tavis Rudd" <ta...@re...> > To: <rob...@ya...>; "Cheetah Template List" > <che...@li...> > Sent: Monday, May 27, 2002 10:35 PM > Subject: Re: [Cheetahtemplate-discuss] (implict) #indent or preprocesso= r > > > I've attached a very basic implementation of a postprocessor. > > On May 27, 2002 12:58 pm, Tavis Rudd wrote: > > I favour starting with a independent line-based postprocessor with a > > flexible syntax. Once that's implemented we can decide the next step > > from there. |
From: <ir...@ms...> - 2002-06-04 03:06:20
|
On Mon, Jun 03, 2002 at 05:06:31PM -0700, Tavis Rudd wrote: > On June 3, 2002 04:11 am, rob...@ya... wrote: > > hi tavis, > > > > this works fine so far. > > Good. It could also extended to do relative indentation in addition to the > absolute indents it does now. > > > i would only suggest making the method > > format a module-level function and dropping > > the class. i dont see the need to have an > > instance holding state. > > That's just a matter style. I try to stay away from managing state with > global vars. Code written that way tends to break easily and is hard to > extend. However, one could write a module-level wrapper function that > automatically creates the IndentFormatter instance. Let me know when it's stabilized and I'll put a howto in the Users' Guide. We should also put it in Python's bin directory if it's a standalone program, or under Cheetah.Tools if it's optional, or under Cheetah.Utils if it'll be automatically called. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: <rob...@ya...> - 2002-06-06 15:49:36
|
hi, i have now experimented with the #indent-syntax (and the postprecessor). so here are my findings. i think postprocessing is not always feasable (to be true i think it is feasable rather seldom). especially if one is working with cheetah makros which use selfdefined #directives it might happen that those #dirs are written somewhere into the stream which makes parsing very much harder. i have written a preprocessor for the indent stuff (which should be appended at this msg). during writing and testing i had some ideas i would like to propose to you. when creating a template it should be possible to define a postprocessor or even better a chain of processors. so one could build a piping-architecture (for every nonstandard #dir one would have to supply the corresponding preprocessor) i would imagine something like this tpl = Template(txt, searchList=[mapper], preprocessors = [IndentProcessor, ObfuscationProcessor, ...]) all processors should exhibit the following protocol class Processor: def process(self, text): """returns the processed text. usually this means the directives are substituted with something different.""" def getHandlerObject(self): """returns a handlerobject that is capable of supporting the runtime behaviour of the substituted directives.""" def getHandlerName(self): """returns the name of the placeholder within the templatetext that was substituted for the #dir. this should correspond to the name the processor uses when substituting own #dirs""" maybe a concrete example helps a little. this is sort of what i am doing in my processor class IndentProcessor: def __init__(self) self.HandlerName = "indent__" self.HandlerObject = IndentFormatter() def process(self, txt): for line in txt.splitlines(): #here happens all the substitution stuff #this is only for explanation if line.matches("[ \t]#indent ++"): line = "#silent $indent__.inc()" result.append(line) return Sep.join(result) def getHandlerName(self): return self.HandlerName def getHanderObject(self): return self.HandlerObject when such an processor is handed over to the template, the template looks if a handlerobject is defined and if it finds such an object it ads the object under the given name to searchList. well there are some other ideas circling in my brain but i guess those have to mature a little longer. anyway maybe we could add this example to the documentation. ciao roberj ------------------------------------------------------------ Robert Kuzelj Gaissacherstrasse 7 email: rob...@ya... 81371 Muenchen tel: 0177/5302230 the trinity of desirables of (software) architecture: Firmitas, Utilitas, Venustas (marcus vitruvius 20 BC) strength, utility, beauty |
From: <ir...@ms...> - 2002-06-06 16:55:14
|
On Thu, Jun 06, 2002 at 05:51:31PM +0200, rob...@ya... wrote: > when creating a template it should be possible to > define a postprocessor or even better a chain of > processors. so one could build a piping-architecture > (for every nonstandard #dir one would have to supply > the corresponding preprocessor) > > i would imagine something like this > tpl = Template(txt, searchList=[mapper], preprocessors = [IndentProcessor, > ObfuscationProcessor, ...]) > > class IndentProcessor: > def __init__(self) > self.HandlerName = "indent__" > self.HandlerObject = IndentFormatter() > def process(self, txt): > for line in txt.splitlines(): > #here happens all the substitution stuff > #this is only for explanation > if line.matches("[ \t]#indent ++"): > line = "#silent $indent__.inc()" > result.append(line) > return Sep.join(result) > def getHandlerName(self): return self.HandlerName > def getHanderObject(self): return self.HandlerObject Where does the indentation itself happen? It looks like you're just injecting increment/decrement calls into the stream. I can see the value of a pipeline of preprocessors. On the other hand, I'm not sure Template needs to be taught about them. This could be done to the source template before Cheetah ever sees it. On the other hand, precompiled templates will want to specify the preprocessors inside the template, a la '#preprocessors IndentProcessor, ObfuscationProcessor'. Of course, that would mean an extra pass through the source, once to look for #preprocessor and again to interpret the result. But how would Cheetah find the preprocessors? "from preprocessor import preprocessor"? How similar are preprocessors to Cheetah filters? If the filter interface can be made the same, or perhaps extended, we can just put preprocessors under Cheetah.Filters. One would like to factor out that common 'splitlines ... append' loop. Perhaps the processor could override either .process(text) or .processLine(line), the latter taking "line with \n" and returning one line, several lines or '' to replace it. Of course, calling a method on each line would be time consuming, but that's what precompiled templates are for. And those directives that don't have to go line by line can just be regular expressions. This won't do exactly what you want, but it could be adequate for other directives: I'm also not sure preprocessor directives should use the same syntax as Cheetah directives. "[indent]" (and "[/indent]" if necessary) shows clearly that it's not a Cheetah directive or an HTML tag, so it must be something else. Whereas #indent makes you wonder if the template writer knew what he was doing, thought there was an #indent directive, or meant to write $indent . If we do preprocessors, we should think about the examples of the C preprocessor and the troff preprocessors. The C preprocessor syntax is a bit jarring alongside the C syntax, and nobody wants to remember to do "tbl DOC.troff | eqn | groff" on certain documents. Although I think groff gets around that by automatically guessing which preprocessors to invoke, but I don't think we want to do that. We could also consider the possibility of plug-in directives for extending Cheetah, which would just be a type of string substitution. That would work for replacing '#indent ++' with something else, but it wouldn't be able to process the entire document. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@oz...) http://iron.cx/ English * Esperanto * Russkiy * Deutsch * Espan~ol |