[Twisted-Python] Zope PageTemplates for Twisted
Sune Kirkeby
sune-twisted at mel.interspace.dk
Thu May 30 15:13:02 MDT 2002
Whee!
In a fit of God-how-I-hate-all-other-template-languages I decided to
take another look at Zopes PageTemplates (TAL, METAL and friends).
I ended up liking the beast so much I decided to start porting it to
Twisted, which resulted in the attached t.w.tal module. It is still
very incomplete, and most likely also very buggy. But, in the
interest of feedback I post it here.
It dislikes it when I reuse deferreds (t.w.w.RenderSession becomes
very confused and claims to be "rendering unknown" for all but the
first instances).
Other than that the only problem I have had so far was that I had to
remove a str'ing in the TAL-engine.
--
Sune Kirkeby | 5 out of 4 people have trouble with fractions.
-------------- next part --------------
# I need a license.
"""
TAL interpreter for Twisted.
"""
import string, types
from twisted.web import widgets
from twisted.web.server import NOT_DONE_YET
from TAL.TALDefs import quote
from TAL.TALDefs import TAL_VERSION, isCurrentVersion, getProgramMode
from TAL.TALDefs import TALError, METALError
from TAL.TALParser import TALParser
from TAL.TALInterpreter import TALInterpreter
from TAL.TALGenerator import TALGenerator
#from TAL.DummyEngine import DummyEngine
from PageTemplates.Expressions import getEngine
class TwistedTALInterpreter:
def __init__(self, engine):
self.engine = engine
self.mode = None
def interpret(self, program):
lst = []
for (opcode, args) in program:
handler = getattr(self, 'do_' + opcode, None)
if not handler:
raise TALError, ("Unknown opcode: %s (%r)" % (opcode, args))
result = handler(args)
if isinstance(result, types.ListType):
lst.extend(result)
elif result:
lst.append(result)
return lst
def do_version(self, version):
assert version == TAL_VERSION
def do_mode(self, mode):
assert mode in ("html", "xml")
self.mode = mode
def do_rawtextOffset(self, (text, somenumber)):
return text
def do_rawtextColumn(self, (text, somenumber)):
return text
def do_startTag(self, (name, attributes)):
txt = '<%s' % name
def format_attribute(attr):
if len(attr) == 2:
return attr[1]
elif attr[2] == 0:
return '%s=%s' % (attr[0], quote(attr[1]))
attributes = map(format_attribute, attributes)
formatted = string.join([ a for a in attributes if a ], ' ')
if formatted:
txt = txt + ' ' + formatted
txt = txt + '>'
return txt
def do_optTag(self, foo):
return self.interpret(foo[5])
def do_loop(self, (name, expr, block)):
iterator = self.engine.setRepeat(name, expr)
lst = []
while iterator.next():
lst.extend(self.interpret(block))
return lst
def do_beginScope(self, attrs):
self.engine.beginScope()
def do_endScope(self, nothing):
self.engine.endScope()
def do_insertText(self, (text, insteadOf)):
val = self.engine.evaluateText(text)
if not val:
return
if val is self.engine.getDefault():
self.interpret(insteadOf)
return val
def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)):
macro = self.engine.evaluateMacro(macroExpr)
if macro is self.engine.getDefault():
macro = block
else:
if not isCurrentVersion(macro):
raise METALError("macro %s has incompatible version %s" %
(`macroName`, `getProgramVersion(macro)`),
self.position)
mode = getProgramMode(macro)
if not mode == self.mode:
raise METALError("macro %s has incompatible mode %s" %
(`macroName`, `mode`), self.position)
return self.interpret(macro)
def do_defineMacro(self, (macroName, macro)):
pass
class TALWidget(widgets.Widget):
def preDisplay(self, request):
pass
def getTemplates(self, request):
raise UnimplementedError
def getContext(self, request):
return {}
def display(self, request):
self.preDisplay(request)
ctx = {
'request': request,
'here': self,
'macros': {},
}
ctx.update(self.getContext(request))
engine = getEngine()
context = engine.getContext(ctx)
generator = TALGenerator(engine)
result = []
for template in self.getTemplates(request):
parser = TALParser(generator)
parser.parseString(template)
program, macros = parser.getCode()
ctx['macros'].update(macros)
interpreter = TwistedTALInterpreter(context)
result.extend(interpreter.interpret(program))
return result
if __name__ == '__main__':
import sys
from twisted.web import widgets
from TAL.TALParser import TALParser
from TAL.DummyEngine import DummyEngine
parser = TALParser()
engine = DummyEngine()
interpreter = TwistedTALInterpreter(engine)
engine.setGlobal('here/title', 'TITLE, GOD DAMMIT!')
file = sys.argv[1]
parser.parseFile(file)
program, macros = parser.getCode()
result = interpreter.interpret(program)
class Request:
def write(self, txt):
print txt
def finish(self):
pass
widgets.RenderSession(result, Request())
More information about the Twisted-Python
mailing list