Commit 4bf04d3d authored by Guido van Rossum's avatar Guido van Rossum

- Fix use-macro expansion to properly retain the use-macro attribute

  value.  This affects TALCompiler.py and TALInterpreter.py, and
  affects the output of the non-local-macro expansion tests.  The
  TALVisitor.py module is *not* yet fixed to do this.

- In order to do this, I had to change the "program code" format for
  the attribute list: the 3rd item of an attribute description tuple,
  if present, now names an action, and the remaining tuple items are
  arguments for that action.  Two actions are recognized: "replace"
  replaces the attribute with the outcome of evaluating the expression
  given by the next tuple  item; "macroHack" replaces the attribute
  name with "use-macro" and its value with the current macro, but
  only if we're inside macro expansion and the attribute name ends in
  ":define-macro".

- The test suite is now error-free for "./runtest.py -c" but shows some
  errors for "./runtest.py".

- Added a primitive debugging flag to the TALInterpreter class.

- Update the README.
parent cc2e1475
...@@ -76,12 +76,9 @@ TO DO ...@@ -76,12 +76,9 @@ TO DO
Here are some things that should be done. Here are some things that should be done.
- Fix the tweaking of the define-macro attribute on macro expansion so - Add calls to an expression compiler
that:
(1) it is only tweaked if the proper prefix is used; and
(2) the argument is taken from the use-macro attribute.
- Provide a framework for error messages (currently it just prints to - Raise exceptions for all errors (currently it just prints to
stdout). stdout).
- Provide a dummy implementation of evaluateStructure()? - Provide a dummy implementation of evaluateStructure()?
......
...@@ -84,9 +84,6 @@ ...@@ -84,9 +84,6 @@
############################################################################## ##############################################################################
""" """
Compile a DOM tree for efficient METAL and TAL expansion. Compile a DOM tree for efficient METAL and TAL expansion.
XXX TO DO:
- get macro define->use substitution in output right (currently ignores prefix)
""" """
import string import string
...@@ -169,12 +166,14 @@ class METALCompiler(DOMVisitor): ...@@ -169,12 +166,14 @@ class METALCompiler(DOMVisitor):
elif attr.prefix == "xmlns": elif attr.prefix == "xmlns":
self.newNS(attr.localName, attr.value) self.newNS(attr.localName, attr.value)
list = [] list = []
# Add namespace declarations for the node itself
if node.namespaceURI: if node.namespaceURI:
if self.newNS(node.prefix, node.namespaceURI): if self.newNS(node.prefix, node.namespaceURI):
if node.prefix: if node.prefix:
list.append(("xmlns:" + node.prefix, node.namespaceURI)) list.append(("xmlns:" + node.prefix, node.namespaceURI))
else: else:
list.append(("xmlns", node.namespaceURI)) list.append(("xmlns", node.namespaceURI))
# Add namespace declarations for each attribute
for attr in node.attributes.values(): for attr in node.attributes.values():
if attr.namespaceURI: if attr.namespaceURI:
if self.newNS(attr.prefix, attr.namespaceURI): if self.newNS(attr.prefix, attr.namespaceURI):
...@@ -185,6 +184,7 @@ class METALCompiler(DOMVisitor): ...@@ -185,6 +184,7 @@ class METALCompiler(DOMVisitor):
("xmlns:" + attr.prefix, attr.namespaceURI)) ("xmlns:" + attr.prefix, attr.namespaceURI))
else: else:
list.append(("xmlns", node.namespaceURI)) list.append(("xmlns", node.namespaceURI))
# Add the node's attributes
list.extend(self.getAttributeList(node)) list.extend(self.getAttributeList(node))
return list return list
...@@ -283,7 +283,11 @@ class METALCompiler(DOMVisitor): ...@@ -283,7 +283,11 @@ class METALCompiler(DOMVisitor):
return [] return []
attrList = [] attrList = []
for attrNode in node.attributes.values(): for attrNode in node.attributes.values():
attrList.append((attrNode.nodeName, attrNode.nodeValue)) item = attrNode.nodeName, attrNode.nodeValue
if (attrNode.namespaceURI == ZOPE_METAL_NS and
attrNode.localName == "define-macro"):
item = item + ("macroHack",)
attrList.append(item)
return attrList return attrList
class TALCompiler(METALCompiler): class TALCompiler(METALCompiler):
...@@ -295,12 +299,12 @@ class TALCompiler(METALCompiler): ...@@ -295,12 +299,12 @@ class TALCompiler(METALCompiler):
if not attrDict: if not attrDict:
return attrList return attrList
list = [] list = []
for key, value in attrList: for item in attrList:
key, value = item[:2]
if attrDict.has_key(key): if attrDict.has_key(key):
list.append((key, value, attrDict[key])) item = (key, value, "replace", attrDict[key])
del attrDict[key] del attrDict[key]
else: list.append(item)
list.append((key, value))
return list return list
# Overriding METAL method to compile TAL statements # Overriding METAL method to compile TAL statements
......
...@@ -95,25 +95,35 @@ from TALCompiler import TALCompiler ...@@ -95,25 +95,35 @@ from TALCompiler import TALCompiler
class TALInterpreter: class TALInterpreter:
def __init__(self, program, macros, engine, stream=None): def __init__(self, program, macros, engine, stream=None, debug=0):
self.program = program self.program = program
self.macros = macros self.macros = macros
self.engine = engine self.engine = engine
self.stream = stream or sys.stdout self.stream = stream or sys.stdout
self.debug = debug
self.slots = {} self.slots = {}
self.inMacro = 0 self.currentMacro = None
def __call__(self): def __call__(self):
self.stream.write('<?xml version="1.0" ?>\n') self.stream.write('<?xml version="1.0" ?>\n')
self.interpret(self.program) self.interpret(self.program)
self.stream.write("\n") self.stream.write("\n")
level = 0
def interpret(self, program): def interpret(self, program):
self.level = self.level + 1
for item in program: for item in program:
methodName = "do_" + item[0] methodName = "do_" + item[0]
args = item[1:] args = item[1:]
if self.debug:
s = "%s%s%s\n" % (" "*self.level, methodName, repr(args))
if len(s) > 80:
s = s[:76] + "...\n"
sys.stderr.write(s)
method = getattr(self, methodName) method = getattr(self, methodName)
apply(method, args) apply(method, args)
self.level = self.level - 1
def do_startEndTag(self, name, attrList): def do_startEndTag(self, name, attrList):
self.do_startTag(name, attrList, "/>") self.do_startTag(name, attrList, "/>")
...@@ -124,16 +134,16 @@ class TALInterpreter: ...@@ -124,16 +134,16 @@ class TALInterpreter:
return return
self.stream.write("<" + name) self.stream.write("<" + name)
for item in attrList: for item in attrList:
name = item[0] name, value = item[:2]
if self.inMacro and name[-13:] == ":define-macro": if len(item) > 2:
# XXX should check namespaceURI too action = item[2]
if action == "replace" and len(item) > 3:
value = self.engine.evaluateText(item[3])
elif (action == "macroHack" and self.currentMacro and
name[-13:] == ":define-macro"):
name = name[:-13] + ":use-macro" name = name[:-13] + ":use-macro"
if len(item) == 2: value = self.currentMacro
self.stream.write(' %s=%s' % (name, quote(item[1]))) self.stream.write(' %s=%s' % (name, quote(value)))
else:
assert len(item) >= 3
value = self.engine.evaluateText(item[2])
self.stream.write(' %s=%s' % (item[0], quote(value)))
self.stream.write(end) self.stream.write(end)
def do_endTag(self, name): def do_endTag(self, name):
...@@ -194,11 +204,11 @@ class TALInterpreter: ...@@ -194,11 +204,11 @@ class TALInterpreter:
def do_useMacro(self, macroName, compiledSlots): def do_useMacro(self, macroName, compiledSlots):
macro = self.engine.evaluateMacro(macroName) macro = self.engine.evaluateMacro(macroName)
save = self.slots, self.inMacro save = self.slots, self.currentMacro
self.slots = compiledSlots self.slots = compiledSlots
self.inMacro = 1 self.currentMacro = macroName
self.interpret(macro) self.interpret(macro)
self.slots, self.inMacro = save self.slots, self.currentMacro = save
def do_fillSlot(self, slotName, program): def do_fillSlot(self, slotName, program):
self.interpret(program) self.interpret(program)
......
<?xml version="1.0" ?> <?xml version="1.0" ?>
<html> <html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="body"> <body xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/test5.xml/body">
<h1>This is the body of test5</h1> <h1>This is the body of test5</h1>
......
<?xml version="1.0" ?> <?xml version="1.0" ?>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="myTable"> <table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/test7.xml/myTable">
<!-- macro definition with slots --> <!-- macro definition with slots -->
<tr> <tr>
<td>Top Left</td> <td>Top Left</td>
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
</tr> </tr>
<tr> <tr>
<td>Bottom left</td> <td>Bottom left</td>
<td><span m:fill-slot="bottomRight"> <td><span xmlns:m="http://xml.zope.org/namespaces/metal" m:fill-slot="bottomRight">
<h1>Some headline</h1> <h1>Some headline</h1>
<p>This is the real contents of the bottom right slot.</p> <p>This is the real contents of the bottom right slot.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab. <p>It is supposed to contain a lot of text. Blah, blah, blab.
......
<?xml version="1.0" ?> <?xml version="1.0" ?>
<html> <html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="body"> <body xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/test5.xml/body">
<h1>This is the body of test5</h1> <h1>This is the body of test5</h1>
......
<?xml version="1.0" ?> <?xml version="1.0" ?>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="myTable"> <table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/test7.xml/myTable">
<!-- macro definition with slots --> <!-- macro definition with slots -->
<tr> <tr>
<td>Top Left</td> <td>Top Left</td>
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
</tr> </tr>
<tr> <tr>
<td>Bottom left</td> <td>Bottom left</td>
<td><span m:fill-slot="bottomRight"> <td><span xmlns:m="http://xml.zope.org/namespaces/metal" m:fill-slot="bottomRight">
<h1>Some headline</h1> <h1>Some headline</h1>
<p>This is the real contents of the bottom right slot.</p> <p>This is the real contents of the bottom right slot.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab. <p>It is supposed to contain a lot of text. Blah, blah, blab.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment