[ZPT] CVS: Packages/TAL - TALInterpreter.py:1.27

guido@digicool.com guido@digicool.com
Mon, 26 Mar 2001 17:32:19 -0500 (EST)


Update of /cvs-repository/Packages/TAL
In directory korak:/tmp/cvs-serv4230

Modified Files:
	TALInterpreter.py 
Log Message:
Add opcode implementation for "mode".

Properly implement tal:replace="structure ..." combined with
tal:attributes="...", both in HTML and in XML mode.  This is pretty
tricky, and requires instantiating a parser with a modified code
generator which suppresses any TAL/METAL interpretation but does the
attribute replacement on the first encountered start tag as required
by the TAL 1.0 specs.



--- Updated File TALInterpreter.py in package Packages/TAL --
--- TALInterpreter.py	2001/03/26 17:02:50	1.26
+++ TALInterpreter.py	2001/03/26 22:32:19	1.27
@@ -96,8 +96,8 @@
 except ImportError:
     from StringIO import StringIO
 
-from XMLParser import XMLParser
 from TALDefs import TALError, TALESError, quote, TAL_VERSION
+from TALGenerator import TALGenerator
 
 BOOLEAN_HTML_ATTRS = [
     # List of Boolean attributes in HTML that should be rendered in
@@ -118,6 +118,35 @@
     "input", "col", "basefont", "isindex", "frame", 
 ]
 
+class AltTALGenerator(TALGenerator):
+
+    def __init__(self, repldict, expressionCompiler=None, xml=0):
+        self.repldict = repldict
+        self.enabled = 1
+        TALGenerator.__init__(self, expressionCompiler, xml)
+
+    def enable(self, enabled):
+        self.enabled = enabled
+
+    def emit(self, *args):
+        if self.enabled:
+            apply(TALGenerator.emit, (self,) + args)
+
+    def emitStartElement(self, name, attrlist, taldict, metaldict,
+                         position=(None, None), isend=0):
+        metaldict = {}
+        taldict = {}
+        if self.enabled and self.repldict:
+            taldict["attributes"] = ""
+        TALGenerator.emitStartElement(self, name, attrlist,
+                                      taldict, metaldict, position, isend)
+
+    def replaceAttrs(self, attrlist, repldict):
+        if self.enabled and self.repldict:
+            repldict = self.repldict
+            self.repldict = None
+        return TALGenerator.replaceAttrs(self, attrlist, repldict)
+
 class TALInterpreter:
 
     def __init__(self, program, macros, engine, stream=None,
@@ -180,6 +209,10 @@
     def do_version(self, version):
         assert version == TAL_VERSION
 
+    def do_mode(self, mode):
+        assert mode in ["html", "xml"]
+        self.html = (mode == "html")
+
     def do_setPosition(self, position):
         self.position = position
 
@@ -262,19 +295,32 @@
         structure = self.engine.evaluateStructure(expr)
         if structure is None:
             return
-        if repldict:
-            raise TALError("replace structure with attribute replacements "
-                           "not yet implemented", self.position)
         text = str(structure)
-        self.checkXMLSyntax(text)
-        self.stream_write(text) # No quoting -- this is intentional
+        if self.html:
+            self.insertHTMLStructure(text, repldict)
+        else:
+            self.insertXMLStructure(text, repldict)
 
-    def checkXMLSyntax(self, text):
-        # XXX This is a bit of a hack!
-        text = '<!DOCTYPE foo PUBLIC "foo" "bar"><foo>%s</foo>' % text
-        p = XMLParser()
+    def insertHTMLStructure(self, text, repldict):
+        from HTMLTALParser import HTMLTALParser
+        gen = AltTALGenerator(repldict, self.engine, 0)
+        p = HTMLTALParser(gen) # Raises an exception if text is invalid
         p.parseString(text)
-        # If this succeeds without errors, we're fine
+        program, macros = p.getCode()
+        self.interpret(program)
+
+    def insertXMLStructure(self, text, repldict):
+        from TALParser import TALParser
+        gen = AltTALGenerator(repldict, self.engine, 0)
+        p = TALParser(gen)
+        gen.enable(0)
+        p.parseFragment('<!DOCTYPE foo PUBLIC "foo" "bar"><foo>')
+        gen.enable(1)
+        p.parseFragment(text) # Raises an exception if text is invalid
+        gen.enable(0)
+        p.parseFragment('</foo>', 1)
+        program, macros = gen.getCode()
+        self.interpret(program)
 
     def do_loop(self, name, expr, block):
         if not self.tal: