Commit 63cab4c1 authored by Guido van Rossum's avatar Guido van Rossum

Renamed the test subdirectory to tests. Do cvs update -d -P to get all the changes.

parent 98884e26
...@@ -92,13 +92,15 @@ import string ...@@ -92,13 +92,15 @@ import string
from TALDefs import NAME_RE, TALError, TALESError from TALDefs import NAME_RE, TALError, TALESError
CancelAction = []
class DummyEngine: class DummyEngine:
def __init__(self, macros=None): def __init__(self, macros=None):
if macros is None: if macros is None:
macros = {} macros = {}
self.macros = macros self.macros = macros
dict = {} dict = {'nothing': None}
self.locals = self.globals = dict self.locals = self.globals = dict
self.stack = [dict] self.stack = [dict]
...@@ -120,10 +122,12 @@ class DummyEngine: ...@@ -120,10 +122,12 @@ class DummyEngine:
if self.locals is self.stack[-1]: if self.locals is self.stack[-1]:
# Unmerge this scope's locals from previous scope of first set # Unmerge this scope's locals from previous scope of first set
self.locals = self.locals.copy() self.locals = self.locals.copy()
self.locals[name] = value if value is not CancelAction:
self.locals[name] = value
def setGlobal(self, name, value): def setGlobal(self, name, value):
self.globals[name] = value if value is not CancelAction:
self.globals[name] = value
def evaluate(self, expression): def evaluate(self, expression):
expression = self.uncompile(expression) expression = self.uncompile(expression)
...@@ -221,6 +225,9 @@ class DummyEngine: ...@@ -221,6 +225,9 @@ class DummyEngine:
def getTALESError(self): def getTALESError(self):
return TALESError return TALESError
def getCancelAction(self):
return CancelAction
class Iterator: class Iterator:
def __init__(self, name, seq, engine): def __init__(self, name, seq, engine):
......
...@@ -36,18 +36,18 @@ How To Play ...@@ -36,18 +36,18 @@ How To Play
The script driver.py takes an XML file with TAL markup as argument and The script driver.py takes an XML file with TAL markup as argument and
writes the expanded version to standard output. The filename argument writes the expanded version to standard output. The filename argument
defaults to test/test1.xml. defaults to tests/input/test01.xml.
Regression test Regression test
--------------- ---------------
There are a number of test files in the test subdirectory, named There are a number of test files in the 'tests' subdirectory, named
test/input/test<number>.xml and test/input/test<number>.html. The tests/input/test<number>.xml and tests/input/test<number>.html. The
Python script ./runtest.py calls driver.main() for each test file, and Python script ./runtest.py calls driver.main() for each test file, and
should print "<file> OK" for each one. should print "<file> OK" for each one.
In addition, there are unit test suites in the test subdirectory; In addition, there are unit test suites in the 'tests' subdirectory;
these can be run with test/run.py. This should print a number of these can be run with tests/run.py. This should print a number of
testcase names plus progress info, ending with a line saying "OK". testcase names plus progress info, ending with a line saying "OK".
It requires that ../unittest.py exists. It requires that ../unittest.py exists.
...@@ -67,7 +67,7 @@ setpath.py hack to set sys.path and import ZODB ...@@ -67,7 +67,7 @@ setpath.py hack to set sys.path and import ZODB
__init__.py empty file that makes this directory a package __init__.py empty file that makes this directory a package
runtest.py Python script to run regression tests runtest.py Python script to run regression tests
ndiff.py helper for runtest.py to produce diffs ndiff.py helper for runtest.py to produce diffs
test/ drectory with test files and output tests/ drectory with test files and output
Author and License Author and License
------------------ ------------------
......
...@@ -157,6 +157,7 @@ class TALInterpreter: ...@@ -157,6 +157,7 @@ class TALInterpreter:
self.macros = macros self.macros = macros
self.engine = engine self.engine = engine
self.TALESError = engine.getTALESError() self.TALESError = engine.getTALESError()
self.CancelAction = engine.getCancelAction()
self.stream = stream or sys.stdout self.stream = stream or sys.stdout
self.debug = debug self.debug = debug
self.wrap = wrap self.wrap = wrap
...@@ -268,6 +269,8 @@ class TALInterpreter: ...@@ -268,6 +269,8 @@ class TALInterpreter:
value = self.engine.evaluateText(item[3]) value = self.engine.evaluateText(item[3])
if value is None: if value is None:
continue continue
if value is self.CancelAction:
value = item[1]
elif (action == "metal" and self.currentMacro and elif (action == "metal" and self.currentMacro and
name[-13:] == ":define-macro" and self.metal): name[-13:] == ":define-macro" and self.metal):
name = name[:-13] + ":use-macro" name = name[:-13] + ":use-macro"
...@@ -314,6 +317,9 @@ class TALInterpreter: ...@@ -314,6 +317,9 @@ class TALInterpreter:
text = self.engine.evaluateText(expr) text = self.engine.evaluateText(expr)
if text is None: if text is None:
return return
if text is self.CancelAction:
self.interpret(block)
return
text = cgi.escape(text) text = cgi.escape(text)
self.stream_write(text) self.stream_write(text)
...@@ -324,6 +330,9 @@ class TALInterpreter: ...@@ -324,6 +330,9 @@ class TALInterpreter:
structure = self.engine.evaluateStructure(expr) structure = self.engine.evaluateStructure(expr)
if structure is None: if structure is None:
return return
if structure is self.CancelAction:
self.interpret(block)
return
text = str(structure) text = str(structure)
if not repldict and not self.strictinsert: if not repldict and not self.strictinsert:
# Take a shortcut, no error checking # Take a shortcut, no error checking
...@@ -378,6 +387,9 @@ class TALInterpreter: ...@@ -378,6 +387,9 @@ class TALInterpreter:
self.interpret(block) self.interpret(block)
return return
macro = self.engine.evaluateMacro(macroExpr) macro = self.engine.evaluateMacro(macroExpr)
if macro is self.CancelAction:
self.interpret(block)
return
if not isCurrentVersion(macro): if not isCurrentVersion(macro):
raise METALError("macro %s has incompatible version %s" % raise METALError("macro %s has incompatible version %s" %
(`macroName`, `getProgramVersion(macro)`), (`macroName`, `getProgramVersion(macro)`),
......
...@@ -184,7 +184,7 @@ class TALParser(XMLParser): ...@@ -184,7 +184,7 @@ class TALParser(XMLParser):
def test(): def test():
import sys import sys
p = TALParser() p = TALParser()
file = "test/test1.xml" file = "tests/input/test01.xml"
if sys.argv[1:]: if sys.argv[1:]:
file = sys.argv[1] file = sys.argv[1]
p.parseFile(file) p.parseFile(file)
......
...@@ -103,7 +103,7 @@ except ImportError: ...@@ -103,7 +103,7 @@ except ImportError:
import TALDefs import TALDefs
from DummyEngine import DummyEngine from DummyEngine import DummyEngine
FILE = "test/input/test01.xml" FILE = "tests/input/test01.xml"
def main(): def main():
versionTest = 1 versionTest = 1
......
...@@ -125,7 +125,7 @@ def main(): ...@@ -125,7 +125,7 @@ def main():
opts.append(args[0]) opts.append(args[0])
del args[0] del args[0]
if not args: if not args:
prefix = os.path.join("test", "input", "test*.") prefix = os.path.join("tests", "input", "test*.")
xmlargs = glob.glob(prefix + "xml") xmlargs = glob.glob(prefix + "xml")
xmlargs.sort() xmlargs.sort()
htmlargs = glob.glob(prefix + "html") htmlargs = glob.glob(prefix + "html")
......
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"DTD/xhtml1-transitional.dtd">
<html>
<head>dadada</head>
<body xmlns:z="http://xml.zope.org/namespaces/tal" z:define="foo python:1">
<h1 z:condition="python:0">This title is not displayed</h1>
<h1 z:condition="python:1" z:content="str:This
Is
The
Replaced
Title">Title</h1>
<!-- test entity references -->
&nbsp;&HarryPotter;
<!-- examples adapted from TemplateAttributeLanguageSyntax -->
<span z:content="str:here/id"/>
<p z:define="x str:template/title; global five python:2+3;" z:content="text var:five"/>
<p z:repeat="car python:['honda', 'subaru', 'acura']">
<span z:replace="var:car"/>
</p>
<p xml:foo="bar">foo bar</p>
<!-- more examples -->
<ul>
<span z:repeat="car python:['honda', 'subaru', 'acura']">
<li z:content="var:car">Car Name</li>
</span>
</ul>
<!-- test attribute expansion -->
<a href="foo" z:attributes="href python:'http://python.org' ">python</a>
<a z:attributes="href python:'http://python.org' ">python</a>
<!-- test insert/replace structure -->
<span z:content="structure python:None" />
<span z:replace="structure python:None" />
<span z:define="global x str:&lt;h3&gt;Header Level 3&lt;/h3&gt;" />
<span z:define="global x python:'&amp;' + 'nbsp;;' + x" />
<span z:replace="structure x" />
<span z:content="structure x" />
</body>
</html>
<?xml version="1.0" ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"DTD/xhtml1-transitional.dtd">
<html>
<head>dadada</head>
<body xmlns:z="http://xml.zope.org/namespaces/tal" z:define="foo python:1">
<h1 z:condition="python:0">This title is not displayed</h1>
<h1 z:condition="python:1" z:content="str:This
Is
The
Replaced
Title">Title</h1>
<!-- test entity references -->
&nbsp;&HarryPotter;
<!-- examples adapted from TemplateAttributeLanguageSyntax -->
<span z:content="str:here/id"/>
<p z:define="x str:template/title; global five python:2+3;" z:content="text var:five"/>
<p z:repeat="car python:['honda', 'subaru', 'acura']">
<span z:replace="var:car"/>
</p>
<p xml:foo="bar">foo bar</p>
<!-- more examples -->
<ul>
<span z:repeat="car python:['honda', 'subaru', 'acura']">
<li z:content="var:car">Car Name</li>
</span>
</ul>
<!-- test attribute expansion -->
<a href="foo" z:attributes="href python:'http://python.org' ">python</a>
<a z:attributes="href python:'http://python.org' ">python</a>
<!-- test insert/replace structure -->
<span z:content="structure python:None" />
<span z:replace="structure python:None" />
<span z:define="global x str:&lt;h3&gt;Header Level 3&lt;/h3&gt;" />
<span z:define="global x python:'&amp;' + 'nbsp;;' + x" />
<span z:replace="structure x" />
<span z:content="structure x" />
</body>
</html>
<biztalk_1 xmlns="urn:schemas-biztalk-org:biztalk:biztalk_1">
<foo:header xmlns:foo="whomping-willow" plain="guido" quote='"' apostrophe="'" both="&quot;'" lt="&lt;" gt="&gt;" amp="&amp;" foo="">
<manifest>
<document>
<name>sample1</name>
<description>a simple invoice</description>
</document>
</manifest>
</foo:header>
<body>
<!-- sample1.xml is an example of a simple invoice for a small restaurant supplies order -->
<Invoice xmlns="urn:http://schemas.biztalk.org/united_rest_com/yw7sg15x.xml">
<Header>
<InvoiceNumber>01786</InvoiceNumber>
<InvoiceDate>2000-03-17</InvoiceDate> <!-- March 17th, 2000 -->
<OrderNo>55377</OrderNo>
<OrderDate>2000-03-15</OrderDate> <!-- March 15th, 2000 -->
<CustomerPO>GJ03405</CustomerPO>
<ShipMethod>DAVE 1</ShipMethod>
<ShipDate>2000-03-17</ShipDate> <!-- March 17th, 2000 -->
<CustomerID>K5211(34)</CustomerID>
<SalesPersonCode>23</SalesPersonCode>
<TaxID>23</TaxID>
</Header>
<InvoiceTo>
<Name>SHIPWRIGHT RESTAURANTS LIMITED</Name>
<AddressLine>125 NORTH SERVICE ROAD W</AddressLine>
<AddressLine>WESTLAKE ACCESS</AddressLine>
<City>NORTH BAY</City>
<PostCode>L8B1O5</PostCode>
<State>ONTARIO</State>
<Country>CANADA</Country>
</InvoiceTo>
<ShipTo>
<Name/>
<AddressLine>ATTN: PAULINE DEGRASSI</AddressLine>
<City/>
<PostCode/>
<State/>
<Country/>
</ShipTo>
<DetailLines>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>CS</UnitOfMeasure>
<PartNumber>DM 5309</PartNumber>
<PartDescription>#1013 12 OZ.MUNICH STEIN</PartDescription>
<UnitPrice>37.72</UnitPrice>
<LineTotal>37.72</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>6</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6420</PartNumber>
<PartDescription>PROVINCIAL DINNER FORK</PartDescription>
<UnitPrice>17.98</UnitPrice>
<LineTotal>107.88</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>72</QuantityShipped>
<UnitOfMeasure>EA</UnitOfMeasure>
<PartNumber>JR20643</PartNumber>
<PartDescription>PLASTIC HANDLED STEAK KNIFE</PartDescription>
<UnitPrice>.81</UnitPrice>
<LineTotal>58.32</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>6</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6410</PartNumber>
<PartDescription>PROVINCIAL TEASPOONS</PartDescription>
<UnitPrice>12.16</UnitPrice>
<LineTotal>72.96</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>0</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6411</PartNumber>
<PartDescription>PROVINCIAL RD BOWL SPOON</PartDescription>
<QuantityBackOrdered>6</QuantityBackOrdered>
<UnitPrice>17.98</UnitPrice>
<LineTotal>0.00</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>EA</UnitOfMeasure>
<PartNumber>DO 3218</PartNumber>
<PartDescription>34 OZ DUAL DIAL SCALE AM3218</PartDescription>
<UnitPrice>70.00</UnitPrice>
<DiscountPercentage>5.0</DiscountPercentage>
<LineTotal>66.50</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>CS</UnitOfMeasure>
<PartNumber>DM 195</PartNumber>
<PartDescription>20 OZ.BEER PUB GLASS</PartDescription>
<UnitPrice>55.90</UnitPrice>
<LineTotal>55.90</LineTotal>
</DetailLine>
</DetailLines>
<Totals>
<SubTotal>399.28</SubTotal>
<DiscountTotal>3.50</DiscountTotal>
<FreightTotal>23.75</FreightTotal>
<GSTTotal>29.61</GSTTotal>
<ProvTaxTotal>33.84</ProvTaxTotal>
<OtherTotal>33.84</OtherTotal>
<InvoiceTotal>486.48</InvoiceTotal>
</Totals>
</Invoice>
</body>
</biztalk_1>
<?xml version="1.0" ?>
<biztalk_1 xmlns="urn:schemas-biztalk-org:biztalk:biztalk_1">
<foo:header xmlns:foo="whomping-willow" plain="guido" quote='"' apostrophe="'" both="&quot;'" lt="&lt;" gt="&gt;" amp="&amp;" foo="">
<manifest>
<document>
<name>sample1</name>
<description>a simple invoice</description>
</document>
</manifest>
</foo:header>
<body>
<!-- sample1.xml is an example of a simple invoice for a small restaurant supplies order -->
<Invoice xmlns="urn:http://schemas.biztalk.org/united_rest_com/yw7sg15x.xml">
<Header>
<InvoiceNumber>01786</InvoiceNumber>
<InvoiceDate>2000-03-17</InvoiceDate> <!-- March 17th, 2000 -->
<OrderNo>55377</OrderNo>
<OrderDate>2000-03-15</OrderDate> <!-- March 15th, 2000 -->
<CustomerPO>GJ03405</CustomerPO>
<ShipMethod>DAVE 1</ShipMethod>
<ShipDate>2000-03-17</ShipDate> <!-- March 17th, 2000 -->
<CustomerID>K5211(34)</CustomerID>
<SalesPersonCode>23</SalesPersonCode>
<TaxID>23</TaxID>
</Header>
<InvoiceTo>
<Name>SHIPWRIGHT RESTAURANTS LIMITED</Name>
<AddressLine>125 NORTH SERVICE ROAD W</AddressLine>
<AddressLine>WESTLAKE ACCESS</AddressLine>
<City>NORTH BAY</City>
<PostCode>L8B1O5</PostCode>
<State>ONTARIO</State>
<Country>CANADA</Country>
</InvoiceTo>
<ShipTo>
<Name/>
<AddressLine>ATTN: PAULINE DEGRASSI</AddressLine>
<City/>
<PostCode/>
<State/>
<Country/>
</ShipTo>
<DetailLines>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>CS</UnitOfMeasure>
<PartNumber>DM 5309</PartNumber>
<PartDescription>#1013 12 OZ.MUNICH STEIN</PartDescription>
<UnitPrice>37.72</UnitPrice>
<LineTotal>37.72</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>6</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6420</PartNumber>
<PartDescription>PROVINCIAL DINNER FORK</PartDescription>
<UnitPrice>17.98</UnitPrice>
<LineTotal>107.88</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>72</QuantityShipped>
<UnitOfMeasure>EA</UnitOfMeasure>
<PartNumber>JR20643</PartNumber>
<PartDescription>PLASTIC HANDLED STEAK KNIFE</PartDescription>
<UnitPrice>.81</UnitPrice>
<LineTotal>58.32</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>6</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6410</PartNumber>
<PartDescription>PROVINCIAL TEASPOONS</PartDescription>
<UnitPrice>12.16</UnitPrice>
<LineTotal>72.96</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>0</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6411</PartNumber>
<PartDescription>PROVINCIAL RD BOWL SPOON</PartDescription>
<QuantityBackOrdered>6</QuantityBackOrdered>
<UnitPrice>17.98</UnitPrice>
<LineTotal>0.00</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>EA</UnitOfMeasure>
<PartNumber>DO 3218</PartNumber>
<PartDescription>34 OZ DUAL DIAL SCALE AM3218</PartDescription>
<UnitPrice>70.00</UnitPrice>
<DiscountPercentage>5.0</DiscountPercentage>
<LineTotal>66.50</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>CS</UnitOfMeasure>
<PartNumber>DM 195</PartNumber>
<PartDescription>20 OZ.BEER PUB GLASS</PartDescription>
<UnitPrice>55.90</UnitPrice>
<LineTotal>55.90</LineTotal>
</DetailLine>
</DetailLines>
<Totals>
<SubTotal>399.28</SubTotal>
<DiscountTotal>3.50</DiscountTotal>
<FreightTotal>23.75</FreightTotal>
<GSTTotal>29.61</GSTTotal>
<ProvTaxTotal>33.84</ProvTaxTotal>
<OtherTotal>33.84</OtherTotal>
<InvoiceTotal>486.48</InvoiceTotal>
</Totals>
</Invoice>
</body>
</biztalk_1>
<p xmlns:z="http://xml.zope.org/namespaces/tal">
<span z:define="local x str:hello brave new world">
<span z:content="text local:x">outer variable x, first appearance</span>
<span z:define="local x str:goodbye cruel world">
<span z:content="text local:x">inner variable x</span>
</span>
<span z:content="text local:x">outer variable x, second appearance</span>
</span>
</p>
<?xml version="1.0" ?>
<p xmlns:z="http://xml.zope.org/namespaces/tal">
<span z:define="local x str:hello brave new world">
<span z:content="text local:x">outer variable x, first appearance</span>
<span z:define="local x str:goodbye cruel world">
<span z:content="text local:x">inner variable x</span>
</span>
<span z:content="text local:x">outer variable x, second appearance</span>
</span>
</p>
<html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" xmlns:z="http://xml.zope.org/namespaces/tal" m:define-macro="body" z:define="global count python:0">
<ul m:define-macro="whoops">
<li z:repeat="item python:range(count)">
<span z:replace="item">1</span>
<span z:replace="global:message"/>
</li>
</ul>
<span z:define="global count python:2; global message str:hello world"/>
<p m:use-macro="whoops">use-macro</p>
<span z:define="global message str:goodbye cruel world"/>
<p m:use-macro="whoops">use-macro</p>
<p m:define-slot="whoops">define-slot</p>
<p m:fill-slot="whoops">fill-slot</p>
</body>
</html>
<?xml version="1.0" ?>
<html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" xmlns:z="http://xml.zope.org/namespaces/tal" m:define-macro="body" z:define="global count python:0">
<ul m:define-macro="whoops">
<li z:repeat="item python:range(count)">
<span z:replace="item">1</span>
<span z:replace="global:message"/>
</li>
</ul>
<span z:define="global count python:2; global message str:hello world"/>
<p m:use-macro="whoops">use-macro</p>
<span z:define="global message str:goodbye cruel world"/>
<p m:use-macro="whoops">use-macro</p>
<p m:define-slot="whoops">define-slot</p>
<p m:fill-slot="whoops">fill-slot</p>
</body>
</html>
<html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" m:define-macro="body">
<h1>This is the body of test5</h1>
</body>
</html>
<?xml version="1.0" ?>
<html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" m:define-macro="body">
<h1>This is the body of test5</h1>
</body>
</html>
<html>
<body xmlns:m="http://xml.zope.org/namespaces/metal"
m:use-macro="test/input/test05.html/body">
dummy body in test6
</body>
</html>
<?xml version="1.0" ?>
<html>
<body xmlns:m="http://xml.zope.org/namespaces/metal"
m:use-macro="test/input/test05.xml/body">
dummy body in test6
</body>
</html>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:define-macro="myTable">
<!-- macro definition with slots -->
<tr>
<td>Top Left</td>
<td>Top Right</td>
</tr>
<tr>
<td>Bottom left</td>
<td><span m:define-slot="bottomRight">Bottom Right</span></td>
</tr>
</table>
<?xml version="1.0" ?>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:define-macro="myTable">
<!-- macro definition with slots -->
<tr>
<td>Top Left</td>
<td>Top Right</td>
</tr>
<tr>
<td>Bottom left</td>
<td><span m:define-slot="bottomRight">Bottom Right</span></td>
</tr>
</table>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/input/test07.html/myTable">
<!-- macro use with slots -->
<tr>
<td>
<span m:fill-slot="bottomRight">
<h1>Some headline</h1>
<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.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
</span>
</td>
</tr>
</table>
<?xml version="1.0" ?>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/input/test07.xml/myTable">
<!-- macro use with slots -->
<tr>
<td>
<span m:fill-slot="bottomRight">
<h1>Some headline</h1>
<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.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
</span>
</td>
</tr>
</table>
<html>
<body>
<p>
Just a bunch of text.
<p>more text...
<ul>
<li>first item
<li>second item
<ol>
<li>second list, first item
<li>second list, second item
<dl compact>
<dt>term 1
<dt>term 2
<dd>definition
</dl>
</ol>
<li>Now let's have a paragraph...
<p>My Paragraph
</li>
<li>And a table in a list item:
<table>
</table>
</ul>
</body>
</html>
<html>
<body>
<p>
Just a bunch of text.</p>
<p>more text...</p>
<ul>
<li>first item</li>
<li>second item
<ol>
<li>second list, first item</li>
<li>second list, second item
<dl compact="">
<dt>term 1</dt>
<dt>term 2</dt>
<dd>definition</dd>
</dl></li>
</ol></li>
<li>Now let's have a paragraph...
<p>My Paragraph</p>
</li>
<li>And a table in a list item:
<table>
</table></li>
</ul>
</body>
</html>
<html><body>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/input/test07.html/myTable">
<!-- macro use with slots -->
<tr>
<td>
<span m:fill-slot="bottomRight">
<h1>Some headline</h1>
<p>This is the real contents of the bottom right slot.</p>
<hr>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<br><br>
</span>
</td>
</tr>
</table>
</body></html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal">
<p tal:replace="structure string:&lt;a&gt;bar&lt;/a&gt;"
tal:attributes="href string:http://www.python.org">dummy text</p>
<p tal:define="x python:1" tal:on-error="string:bad boy!">
<span tal:define="x python:2">
<span tal:define="x python:3">
<span tal:content="python:1/0"/>
</span>
</span>
</p>
<p tal:on-error="string:x undefined">
<span tal:content="x"/>
</p>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal">
<p tal:replace="structure string:&lt;a&gt;bar&lt;/a&gt;"
tal:attributes="href string:http://www.python.org">dummy text</p>
<p tal:define="x python:1" tal:on-error="string:bad boy!">
<span tal:define="x python:2">
<span tal:define="x python:3">
<span tal:content="python:1/0"/>
</span>
</span>
</p>
<p tal:on-error="string:x undefined">
<span tal:content="x"/>
</p>
</html>
<span tal:define="global true python:1; global false python:0" />
<img ismap>
<img ismap=ismap>
<img ismap="ismap">
<img ismap="foo">
<img ismap tal:attributes="ismap true">
<img ismap tal:attributes="ismap false">
<img ismap tal:attributes="ismap nothing">
<img ismap="foo" tal:attributes="ismap true">
<img ismap="foo" tal:attributes="ismap false">
<img ismap="foo" tal:attributes="ismap nothing">
<img tal:attributes="ismap true">
<img tal:attributes="ismap false">
<img tal:attributes="ismap nothing">
<span tal:define="global x string:x.gif" />
<img src="foo">
<img src="foo" tal:attributes="src x">
<img src="foo" tal:attributes="src nothing">
Here's a stray greater than: >
<script>
<!-- no comment -->
<notag>
&noentity;
</script>
<table>
<tr>
<td tal:repeat="x python:['car', 'bike', 'broomstick']" tal:content="x">
</td>
</tr>
</table>
<p>
<span tal:repeat="x python:['Harry', 'Ron', 'Hermione']" tal:replace="x" />
</p>
<?xml version="1.0" ?>
<html xmlns:tal="http://xml.zope.org/namespaces/tal">
<table>
<tr>
<td tal:repeat="x python:['car', 'bike', 'broomstick']" tal:content="x">
</td>
</tr>
</table>
<p>
<span tal:repeat="x python:['Harry', 'Ron', 'Hermione']" tal:replace="x" />
</p>
</html>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"DTD/xhtml1-transitional.dtd">
<html>
<head>dadada</head>
<body>
<h1>This
Is
The
Replaced
Title</h1>
<!-- test entity references -->
&nbsp;&HarryPotter;
<!-- examples adapted from TemplateAttributeLanguageSyntax -->
<span>here/id</span>
<p>5</p>
<p>
honda
</p>
<p>
subaru
</p>
<p>
acura
</p>
<p xml:foo="bar">foo bar</p>
<!-- more examples -->
<ul>
<span>
<li>honda</li>
</span>
<span>
<li>subaru</li>
</span>
<span>
<li>acura</li>
</span>
</ul>
<!-- test attribute expansion -->
<a href="http://python.org">python</a>
<a href="http://python.org">python</a>
<!-- test insert/replace structure -->
<span></span>
<span />
<span />
&nbsp;<h3>Header Level 3</h3>
<span>&nbsp;<h3>Header Level 3</h3></span>
</body>
</html>
<?xml version="1.0" ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"DTD/xhtml1-transitional.dtd">
<html>
<head>dadada</head>
<body>
<h1>This Is The Replaced Title</h1>
<!-- test entity references -->
&nbsp;&HarryPotter;
<!-- examples adapted from TemplateAttributeLanguageSyntax -->
<span>here/id</span>
<p>5</p>
<p>
honda
</p>
<p>
subaru
</p>
<p>
acura
</p>
<p xml:foo="bar">foo bar</p>
<!-- more examples -->
<ul>
<span>
<li>honda</li>
</span>
<span>
<li>subaru</li>
</span>
<span>
<li>acura</li>
</span>
</ul>
<!-- test attribute expansion -->
<a href="http://python.org">python</a>
<a href="http://python.org">python</a>
<!-- test insert/replace structure -->
<span></span>
<span/>
<span/>
&nbsp;<h3>Header Level 3</h3>
<span>&nbsp;<h3>Header Level 3</h3></span>
</body>
</html>
<biztalk_1 xmlns="urn:schemas-biztalk-org:biztalk:biztalk_1">
<foo:header xmlns:foo="whomping-willow" plain="guido" quote="&quot;" apostrophe="'" both="&quot;'" lt="&lt;" gt="&gt;" amp="&amp;" foo="">
<manifest>
<document>
<name>sample1</name>
<description>a simple invoice</description>
</document>
</manifest>
</foo:header>
<body>
<!-- sample1.xml is an example of a simple invoice for a small restaurant supplies order -->
<invoice xmlns="urn:http://schemas.biztalk.org/united_rest_com/yw7sg15x.xml">
<header>
<invoicenumber>01786</invoicenumber>
<invoicedate>2000-03-17</invoicedate> <!-- March 17th, 2000 -->
<orderno>55377</orderno>
<orderdate>2000-03-15</orderdate> <!-- March 15th, 2000 -->
<customerpo>GJ03405</customerpo>
<shipmethod>DAVE 1</shipmethod>
<shipdate>2000-03-17</shipdate> <!-- March 17th, 2000 -->
<customerid>K5211(34)</customerid>
<salespersoncode>23</salespersoncode>
<taxid>23</taxid>
</header>
<invoiceto>
<name>SHIPWRIGHT RESTAURANTS LIMITED</name>
<addressline>125 NORTH SERVICE ROAD W</addressline>
<addressline>WESTLAKE ACCESS</addressline>
<city>NORTH BAY</city>
<postcode>L8B1O5</postcode>
<state>ONTARIO</state>
<country>CANADA</country>
</invoiceto>
<shipto>
<name />
<addressline>ATTN: PAULINE DEGRASSI</addressline>
<city />
<postcode />
<state />
<country />
</shipto>
<detaillines>
<detailline>
<quantityshipped>1</quantityshipped>
<unitofmeasure>CS</unitofmeasure>
<partnumber>DM 5309</partnumber>
<partdescription>#1013 12 OZ.MUNICH STEIN</partdescription>
<unitprice>37.72</unitprice>
<linetotal>37.72</linetotal>
</detailline>
<detailline>
<quantityshipped>6</quantityshipped>
<unitofmeasure>DZ</unitofmeasure>
<partnumber>ON 6420</partnumber>
<partdescription>PROVINCIAL DINNER FORK</partdescription>
<unitprice>17.98</unitprice>
<linetotal>107.88</linetotal>
</detailline>
<detailline>
<quantityshipped>72</quantityshipped>
<unitofmeasure>EA</unitofmeasure>
<partnumber>JR20643</partnumber>
<partdescription>PLASTIC HANDLED STEAK KNIFE</partdescription>
<unitprice>.81</unitprice>
<linetotal>58.32</linetotal>
</detailline>
<detailline>
<quantityshipped>6</quantityshipped>
<unitofmeasure>DZ</unitofmeasure>
<partnumber>ON 6410</partnumber>
<partdescription>PROVINCIAL TEASPOONS</partdescription>
<unitprice>12.16</unitprice>
<linetotal>72.96</linetotal>
</detailline>
<detailline>
<quantityshipped>0</quantityshipped>
<unitofmeasure>DZ</unitofmeasure>
<partnumber>ON 6411</partnumber>
<partdescription>PROVINCIAL RD BOWL SPOON</partdescription>
<quantitybackordered>6</quantitybackordered>
<unitprice>17.98</unitprice>
<linetotal>0.00</linetotal>
</detailline>
<detailline>
<quantityshipped>1</quantityshipped>
<unitofmeasure>EA</unitofmeasure>
<partnumber>DO 3218</partnumber>
<partdescription>34 OZ DUAL DIAL SCALE AM3218</partdescription>
<unitprice>70.00</unitprice>
<discountpercentage>5.0</discountpercentage>
<linetotal>66.50</linetotal>
</detailline>
<detailline>
<quantityshipped>1</quantityshipped>
<unitofmeasure>CS</unitofmeasure>
<partnumber>DM 195</partnumber>
<partdescription>20 OZ.BEER PUB GLASS</partdescription>
<unitprice>55.90</unitprice>
<linetotal>55.90</linetotal>
</detailline>
</detaillines>
<totals>
<subtotal>399.28</subtotal>
<discounttotal>3.50</discounttotal>
<freighttotal>23.75</freighttotal>
<gsttotal>29.61</gsttotal>
<provtaxtotal>33.84</provtaxtotal>
<othertotal>33.84</othertotal>
<invoicetotal>486.48</invoicetotal>
</totals>
</invoice>
</body>
</biztalk_1>
<?xml version="1.0" ?>
<biztalk_1 xmlns="urn:schemas-biztalk-org:biztalk:biztalk_1">
<foo:header xmlns:foo="whomping-willow" plain="guido" quote="&quot;" apostrophe="'" both="&quot;'" lt="&lt;" gt="&gt;" amp="&amp;" foo="">
<manifest>
<document>
<name>sample1</name>
<description>a simple invoice</description>
</document>
</manifest>
</foo:header>
<body>
<!-- sample1.xml is an example of a simple invoice for a small restaurant supplies order -->
<Invoice xmlns="urn:http://schemas.biztalk.org/united_rest_com/yw7sg15x.xml">
<Header>
<InvoiceNumber>01786</InvoiceNumber>
<InvoiceDate>2000-03-17</InvoiceDate> <!-- March 17th, 2000 -->
<OrderNo>55377</OrderNo>
<OrderDate>2000-03-15</OrderDate> <!-- March 15th, 2000 -->
<CustomerPO>GJ03405</CustomerPO>
<ShipMethod>DAVE 1</ShipMethod>
<ShipDate>2000-03-17</ShipDate> <!-- March 17th, 2000 -->
<CustomerID>K5211(34)</CustomerID>
<SalesPersonCode>23</SalesPersonCode>
<TaxID>23</TaxID>
</Header>
<InvoiceTo>
<Name>SHIPWRIGHT RESTAURANTS LIMITED</Name>
<AddressLine>125 NORTH SERVICE ROAD W</AddressLine>
<AddressLine>WESTLAKE ACCESS</AddressLine>
<City>NORTH BAY</City>
<PostCode>L8B1O5</PostCode>
<State>ONTARIO</State>
<Country>CANADA</Country>
</InvoiceTo>
<ShipTo>
<Name/>
<AddressLine>ATTN: PAULINE DEGRASSI</AddressLine>
<City/>
<PostCode/>
<State/>
<Country/>
</ShipTo>
<DetailLines>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>CS</UnitOfMeasure>
<PartNumber>DM 5309</PartNumber>
<PartDescription>#1013 12 OZ.MUNICH STEIN</PartDescription>
<UnitPrice>37.72</UnitPrice>
<LineTotal>37.72</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>6</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6420</PartNumber>
<PartDescription>PROVINCIAL DINNER FORK</PartDescription>
<UnitPrice>17.98</UnitPrice>
<LineTotal>107.88</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>72</QuantityShipped>
<UnitOfMeasure>EA</UnitOfMeasure>
<PartNumber>JR20643</PartNumber>
<PartDescription>PLASTIC HANDLED STEAK KNIFE</PartDescription>
<UnitPrice>.81</UnitPrice>
<LineTotal>58.32</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>6</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6410</PartNumber>
<PartDescription>PROVINCIAL TEASPOONS</PartDescription>
<UnitPrice>12.16</UnitPrice>
<LineTotal>72.96</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>0</QuantityShipped>
<UnitOfMeasure>DZ</UnitOfMeasure>
<PartNumber>ON 6411</PartNumber>
<PartDescription>PROVINCIAL RD BOWL SPOON</PartDescription>
<QuantityBackOrdered>6</QuantityBackOrdered>
<UnitPrice>17.98</UnitPrice>
<LineTotal>0.00</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>EA</UnitOfMeasure>
<PartNumber>DO 3218</PartNumber>
<PartDescription>34 OZ DUAL DIAL SCALE AM3218</PartDescription>
<UnitPrice>70.00</UnitPrice>
<DiscountPercentage>5.0</DiscountPercentage>
<LineTotal>66.50</LineTotal>
</DetailLine>
<DetailLine>
<QuantityShipped>1</QuantityShipped>
<UnitOfMeasure>CS</UnitOfMeasure>
<PartNumber>DM 195</PartNumber>
<PartDescription>20 OZ.BEER PUB GLASS</PartDescription>
<UnitPrice>55.90</UnitPrice>
<LineTotal>55.90</LineTotal>
</DetailLine>
</DetailLines>
<Totals>
<SubTotal>399.28</SubTotal>
<DiscountTotal>3.50</DiscountTotal>
<FreightTotal>23.75</FreightTotal>
<GSTTotal>29.61</GSTTotal>
<ProvTaxTotal>33.84</ProvTaxTotal>
<OtherTotal>33.84</OtherTotal>
<InvoiceTotal>486.48</InvoiceTotal>
</Totals>
</Invoice>
</body>
</biztalk_1>
<p>
<span>
<span>hello brave new world</span>
<span>
<span>goodbye cruel world</span>
</span>
<span>hello brave new world</span>
</span>
</p>
<?xml version="1.0" ?>
<p>
<span>
<span>hello brave new world</span>
<span>
<span>goodbye cruel world</span>
</span>
<span>hello brave new world</span>
</span>
</p>
<html>
<body>
<ul>
</ul>
<span />
<ul>
<li>
0
hello world
</li>
<li>
1
hello world
</li>
</ul>
<span />
<ul>
<li>
0
goodbye cruel world
</li>
<li>
1
goodbye cruel world
</li>
</ul>
<p>define-slot</p>
<p>fill-slot</p>
</body>
</html>
<?xml version="1.0" ?>
<html>
<body>
<ul>
</ul>
<span/>
<ul>
<li>
0
hello world
</li>
<li>
1
hello world
</li>
</ul>
<span/>
<ul>
<li>
0
goodbye cruel world
</li>
<li>
1
goodbye cruel world
</li>
</ul>
<p>define-slot</p>
<p>fill-slot</p>
</body>
</html>
<html>
<body>
<h1>This is the body of test5</h1>
</body>
</html>
<?xml version="1.0" ?>
<html>
<body>
<h1>This is the body of test5</h1>
</body>
</html>
<html>
<body>
<h1>This is the body of test5</h1>
</body>
</html>
<?xml version="1.0" ?>
<html>
<body>
<h1>This is the body of test5</h1>
</body>
</html>
<table>
<!-- macro definition with slots -->
<tr>
<td>Top Left</td>
<td>Top Right</td>
</tr>
<tr>
<td>Bottom left</td>
<td><span>Bottom Right</span></td>
</tr>
</table>
<?xml version="1.0" ?>
<table>
<!-- macro definition with slots -->
<tr>
<td>Top Left</td>
<td>Top Right</td>
</tr>
<tr>
<td>Bottom left</td>
<td><span>Bottom Right</span></td>
</tr>
</table>
<table>
<!-- macro definition with slots -->
<tr>
<td>Top Left</td>
<td>Top Right</td>
</tr>
<tr>
<td>Bottom left</td>
<td><span>
<h1>Some headline</h1>
<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.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
</span></td>
</tr>
</table>
<?xml version="1.0" ?>
<table>
<!-- macro definition with slots -->
<tr>
<td>Top Left</td>
<td>Top Right</td>
</tr>
<tr>
<td>Bottom left</td>
<td><span>
<h1>Some headline</h1>
<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.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
</span></td>
</tr>
</table>
<html>
<body>
<p>
Just a bunch of text.</p>
<p>more text...</p>
<ul>
<li>first item</li>
<li>second item
<ol>
<li>second list, first item</li>
<li>second list, second item
<dl compact>
<dt>term 1</dt>
<dt>term 2</dt>
<dd>definition</dd>
</dl></li>
</ol></li>
<li>Now let's have a paragraph...
<p>My Paragraph</p>
</li>
<li>And a table in a list item:
<table>
</table></li>
</ul>
</body>
</html>
<html>
<body>
<p>
Just a bunch of text.</p>
<p>more text...</p>
<ul>
<li>first item</li>
<li>second item
<ol>
<li>second list, first item</li>
<li>second list, second item
<dl compact="">
<dt>term 1</dt>
<dt>term 2</dt>
<dd>definition</dd>
</dl></li>
</ol></li>
<li>Now let's have a paragraph...
<p>My Paragraph</p>
</li>
<li>And a table in a list item:
<table>
</table></li>
</ul>
</body>
</html>
<html><body>
<table>
<!-- macro definition with slots -->
<tr>
<td>Top Left</td>
<td>Top Right</td>
</tr>
<tr>
<td>Bottom left</td>
<td><span>
<h1>Some headline</h1>
<p>This is the real contents of the bottom right slot.</p>
<hr>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<p>It is supposed to contain a lot of text. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab.
Blabber, blabber, blah. Baah, baah, barb.</p>
<br><br>
</span></td>
</tr>
</table>
</body></html>
<html>
<a href="http://www.python.org">bar</a>
<p>bad boy!</p>
<p>x undefined</p>
</html>
<html>
<a href="http://www.python.org">bar</a>
<p>bad boy!</p>
<p>x undefined</p>
</html>
<span />
<img ismap>
<img ismap="ismap">
<img ismap="ismap">
<img ismap="foo">
<img ismap>
<img>
<img>
<img ismap>
<img>
<img>
<img ismap>
<img>
<img>
<span />
<img src="foo">
<img src="x.gif">
<img>
Here's a stray greater than: >
<script>
<!-- no comment -->
<notag>
&noentity;
</script>
<table>
<tr>
<td>car</td>
<td>bike</td>
<td>broomstick</td>
</tr>
</table>
<p>
Harry
Ron
Hermione
</p>
<?xml version="1.0" ?>
<html>
<table>
<tr>
<td>car</td>
<td>bike</td>
<td>broomstick</td>
</tr>
</table>
<p>
Harry
Ron
Hermione
</p>
</html>
#! /usr/bin/env python1.5
"""Run all tests."""
import sys
import utils
import unittest
import test_htmlparser
import test_htmltalparser
import test_xmlparser
import test_talinterpreter
def test_suite():
suite = unittest.TestSuite()
suite.addTest(test_htmlparser.test_suite())
suite.addTest(test_htmltalparser.test_suite())
suite.addTest(test_xmlparser.test_suite())
suite.addTest(test_talinterpreter.test_suite())
return suite
def main():
return utils.run_suite(test_suite())
if __name__ == "__main__":
errs = main()
sys.exit(errs and 1 or 0)
#! /usr/bin/env python1.5
"""Tests for HTMLParser.py."""
import sys
import utils
import unittest
from TAL import HTMLParser
class EventCollector(HTMLParser.HTMLParser):
def __init__(self):
self.events = []
self.append = self.events.append
HTMLParser.HTMLParser.__init__(self)
def get_events(self):
# Normalize the list of events so that buffer artefacts don't
# separate runs of contiguous characters.
L = []
prevtype = None
for event in self.events:
type = event[0]
if type == prevtype == "data":
L[-1] = ("data", L[-1][1] + event[1])
else:
L.append(event)
prevtype = type
self.events = L
return L
# structure markup
def handle_starttag(self, tag, attrs):
self.append(("starttag", tag, attrs))
def handle_startendtag(self, tag, attrs):
self.append(("startendtag", tag, attrs))
def handle_endtag(self, tag):
self.append(("endtag", tag))
# all other markup
def handle_comment(self, data):
self.append(("comment", data))
def handle_charref(self, data):
self.append(("charref", data))
def handle_data(self, data):
self.append(("data", data))
def handle_decl(self, data):
self.append(("decl", data))
def handle_entityref(self, data):
self.append(("entityref", data))
def handle_pi(self, data):
self.append(("pi", data))
class EventCollectorExtra(EventCollector):
def handle_starttag(self, tag, attrs):
EventCollector.handle_starttag(self, tag, attrs)
self.append(("starttag_text", self.get_starttag_text()))
class TestCaseBase(unittest.TestCase):
# Constant pieces of source and events
prologue = ""
epilogue = ""
initial_events = []
final_events = []
def _run_check(self, source, events, collector=EventCollector):
parser = collector()
parser.feed(self.prologue)
for s in source:
parser.feed(s)
for c in self.epilogue:
parser.feed(c)
parser.close()
self.assert_(parser.get_events() ==
self.initial_events + events + self.final_events,
parser.get_events())
def _run_check_extra(self, source, events):
self._run_check(source, events, EventCollectorExtra)
def _parse_error(self, source):
def parse(source=source):
parser = HTMLParser.HTMLParser()
parser.feed(source)
parser.close()
self.assertRaises(HTMLParser.HTMLParseError, parse)
class HTMLParserTestCase(TestCaseBase):
def check_processing_instruction_only(self):
self._run_check("<?processing instruction>", [
("pi", "processing instruction"),
])
def check_simple_html(self):
self._run_check("""
<!DOCTYPE html PUBLIC 'foo'>
<HTML>&entity;&#32;
<!--comment1a
-></foo><bar>&lt;<?pi?></foo<bar
comment1b-->
<Img sRc='Bar' isMAP>sample
text
<!--comment2a-- --comment2b-->
</Html>
""", [
("data", "\n"),
("decl", "DOCTYPE html PUBLIC 'foo'"),
("data", "\n"),
("starttag", "html", []),
("entityref", "entity"),
("charref", "32"),
("data", "\n"),
("comment", "comment1a\n-></foo><bar>&lt;<?pi?></foo<bar\ncomment1b"),
("data", "\n"),
("starttag", "img", [("src", "Bar"), ("ismap", None)]),
("data", "sample\ntext\n"),
("comment", "comment2a-- --comment2b"),
("data", "\n"),
("endtag", "html"),
("data", "\n"),
])
def check_bad_nesting(self):
self._run_check("<a><b></a></b>", [
("starttag", "a", []),
("starttag", "b", []),
("endtag", "a"),
("endtag", "b"),
])
def check_attr_syntax(self):
output = [
("starttag", "a", [("b", "v"), ("c", "v"), ("d", "v"), ("e", None)])
]
self._run_check("""<a b='v' c="v" d=v e>""", output)
self._run_check("""<a b = 'v' c = "v" d = v e>""", output)
self._run_check("""<a\nb\n=\n'v'\nc\n=\n"v"\nd\n=\nv\ne>""", output)
self._run_check("""<a\tb\t=\t'v'\tc\t=\t"v"\td\t=\tv\te>""", output)
def check_attr_values(self):
self._run_check("""<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'>""",
[("starttag", "a", [("b", "xxx\n\txxx"),
("c", "yyy\t\nyyy"),
("d", "\txyz\n")])
])
self._run_check("""<a b='' c="">""", [
("starttag", "a", [("b", ""), ("c", "")]),
])
def check_attr_entity_replacement(self):
self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [
("starttag", "a", [("b", "&><\"'")]),
])
def check_attr_funky_names(self):
self._run_check("""<a a.b='v' c:d=v e-f=v>""", [
("starttag", "a", [("a.b", "v"), ("c:d", "v"), ("e-f", "v")]),
])
def check_starttag_end_boundary(self):
self._run_check("""<a b='<'>""", [("starttag", "a", [("b", "<")])])
self._run_check("""<a b='>'>""", [("starttag", "a", [("b", ">")])])
def check_buffer_artefacts(self):
output = [("starttag", "a", [("b", "<")])]
self._run_check(["<a b='<'>"], output)
self._run_check(["<a ", "b='<'>"], output)
self._run_check(["<a b", "='<'>"], output)
self._run_check(["<a b=", "'<'>"], output)
self._run_check(["<a b='<", "'>"], output)
self._run_check(["<a b='<'", ">"], output)
output = [("starttag", "a", [("b", ">")])]
self._run_check(["<a b='>'>"], output)
self._run_check(["<a ", "b='>'>"], output)
self._run_check(["<a b", "='>'>"], output)
self._run_check(["<a b=", "'>'>"], output)
self._run_check(["<a b='>", "'>"], output)
self._run_check(["<a b='>'", ">"], output)
def check_starttag_junk_chars(self):
self._parse_error("<")
self._parse_error("<>")
self._parse_error("</>")
self._parse_error("</$>")
self._parse_error("</")
self._parse_error("</a")
self._parse_error("</a")
self._parse_error("<a<a>")
self._parse_error("</a<a>")
self._parse_error("<$")
self._parse_error("<$>")
self._parse_error("<!")
self._parse_error("<a $>")
self._parse_error("<a")
self._parse_error("<a foo='bar'")
self._parse_error("<a foo='bar")
self._parse_error("<a foo='>'")
self._parse_error("<a foo='>")
self._parse_error("<a foo=>")
def check_declaration_junk_chars(self):
self._parse_error("<!DOCTYPE foo $ >")
def check_startendtag(self):
self._run_check("<p/>", [
("startendtag", "p", []),
])
self._run_check("<p></p>", [
("starttag", "p", []),
("endtag", "p"),
])
self._run_check("<p><img src='foo' /></p>", [
("starttag", "p", []),
("startendtag", "img", [("src", "foo")]),
("endtag", "p"),
])
def check_get_starttag_text(self):
s = """<foo:bar \n one="1"\ttwo=2 >"""
self._run_check_extra(s, [
("starttag", "foo:bar", [("one", "1"), ("two", "2")]),
("starttag_text", s)])
def check_cdata_content(self):
s = """<script> <!-- not a comment --> &not-an-entity-ref; </script>"""
self._run_check(s, [
("starttag", "script", []),
("data", " <!-- not a comment --> &not-an-entity-ref; "),
("endtag", "script"),
])
s = """<script> <not a='start tag'> </script>"""
self._run_check(s, [
("starttag", "script", []),
("data", " <not a='start tag'> "),
("endtag", "script"),
])
# Support for the Zope regression test framework:
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(HTMLParserTestCase, "check_"))
return suite
if __name__ == "__main__":
errs = utils.run_suite(test_suite())
sys.exit(errs and 1 or 0)
#! /usr/bin/env python1.5
"""Tests for the HTMLTALParser code generator."""
import pprint
import sys
import utils
import unittest
from TAL import HTMLTALParser
from TAL.TALDefs import TAL_VERSION, TALError, METALError
class TestCaseBase(unittest.TestCase):
prologue = ""
epilogue = ""
initial_program = [('version', TAL_VERSION), ('mode', 'html')]
final_program = []
def _merge(self, p1, p2):
if p1 and p2 and p1[-1][0] == 'rawtext' and p2[0][0] == 'rawtext':
return p1[:-1] + [('rawtext', p1[-1][1] + p2[0][1])] + p2[1:]
else:
return p1+p2
def _run_check(self, source, program, macros={}):
parser = HTMLTALParser.HTMLTALParser()
parser.parseString(self.prologue + source + self.epilogue)
got_program, got_macros = parser.getCode()
program = self._merge(self.initial_program, program)
program = self._merge(program, self.final_program)
self.assert_(got_program == program, got_program)
self.assert_(got_macros == macros, got_macros)
def _get_check(self, source, program=[], macros={}):
parser = HTMLTALParser.HTMLTALParser()
parser.parseString(source)
got_program, got_macros = parser.getCode()
pprint.pprint(got_program)
pprint.pprint(got_macros)
def _should_error(self, source, exc=TALError):
def parse(self=self, source=source):
parser = HTMLTALParser.HTMLTALParser()
parser.parseString(self.prologue + source + self.epilogue)
self.assertRaises(exc, parse)
class HTMLTALParserTestCases(TestCaseBase):
def check_code_simple_identity(self):
self._run_check("""<html a='b' b="c" c=d><title>My Title</html>""", [
('rawtext', '<html a="b" b="c" c="d">'
'<title>My Title</title></html>'),
])
def check_code_implied_list_closings(self):
self._run_check("""<ul><li><p><p><li></ul>""", [
('rawtext', '<ul><li><p></p><p></p></li><li></li></ul>'),
])
self._run_check("""<dl><dt><dt><dd><dd><ol><li><li></ol></dl>""", [
('rawtext', '<dl><dt></dt><dt></dt><dd></dd>'
'<dd><ol><li></li><li></li></ol></dd></dl>'),
])
def check_code_implied_table_closings(self):
self._run_check("""<p>text <table><tr><th>head\t<tr><td>cell\t"""
"""<table><tr><td>cell \n \t \n<tr>""", [
('rawtext', '<p>text</p> <table><tr><th>head</th>'
'</tr>\t<tr><td>cell\t<table><tr><td>cell</td>'
'</tr> \n \t \n<tr></tr></table></td></tr></table>'),
])
self._run_check("""<table><tr><td>cell """
"""<table><tr><td>cell </table></table>""", [
('rawtext', '<table><tr><td>cell <table><tr><td>cell</td></tr>'
' </table></td></tr></table>'),
])
def check_code_bad_nesting(self):
def check(self=self):
self._run_check("<a><b></a></b>", [])
self.assertRaises(HTMLTALParser.NestingError, check)
def check_code_attr_syntax(self):
output = [
('rawtext', '<a b="v" c="v" d="v" e></a>'),
]
self._run_check("""<a b='v' c="v" d=v e>""", output)
self._run_check("""<a b = 'v' c = "v" d = v e>""", output)
self._run_check("""<a\nb\n=\n'v'\nc\n=\n"v"\nd\n=\nv\ne>""", output)
self._run_check("""<a\tb\t=\t'v'\tc\t=\t"v"\td\t=\tv\te>""", output)
def check_code_attr_values(self):
self._run_check(
"""<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'>""", [
('rawtext',
'<a b="xxx\n\txxx" c="yyy\t\nyyy" d="\txyz\n"></a>')])
self._run_check("""<a b='' c="">""", [
('rawtext', '<a b="" c=""></a>'),
])
def check_code_attr_entity_replacement(self):
# we expect entities *not* to be replaced by HTLMParser!
self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [
('rawtext', '<a b="&amp;&gt;&lt;&quot;\'"></a>'),
])
self._run_check("""<a b='\"'>""", [
('rawtext', '<a b="&quot;"></a>'),
])
self._run_check("""<a b='&'>""", [
('rawtext', '<a b="&amp;"></a>'),
])
self._run_check("""<a b='<'>""", [
('rawtext', '<a b="&lt;"></a>'),
])
def check_code_attr_funky_names(self):
self._run_check("""<a a.b='v' c:d=v e-f=v>""", [
('rawtext', '<a a.b="v" c:d="v" e-f="v"></a>'),
])
def check_code_pcdata_entityref(self):
self._run_check("""&nbsp;""", [
('rawtext', '&nbsp;'),
])
def check_code_short_endtags(self):
self._run_check("""<html><img/></html>""", [
('rawtext', '<html><img /></html>'),
])
class METALGeneratorTestCases(TestCaseBase):
def check_null(self):
self._run_check("", [])
def check_define_macro(self):
macro = self.initial_program + [
('startTag', 'p', [('metal:define-macro', 'M', 'metal')]),
('rawtext', 'booh</p>')]
program = [
('setPosition', (1, 0)),
('defineMacro', 'M', macro),
]
macros = {'M': macro}
self._run_check('<p metal:define-macro="M">booh</p>', program, macros)
def check_use_macro(self):
self._run_check('<p metal:use-macro="M">booh</p>', [
('setPosition', (1, 0)),
('useMacro',
'M', '$M$', {},
[('startTag', 'p', [('metal:use-macro', 'M', 'metal')]),
('rawtext', 'booh</p>')]),
])
def check_define_slot(self):
macro = self.initial_program + [
('startTag', 'p', [('metal:define-macro', 'M', 'metal')]),
('rawtext', 'foo'),
('setPosition', (1, 29)),
('defineSlot', 'S',
[('startTag', 'span', [('metal:define-slot', 'S', 'metal')]),
('rawtext', 'spam</span>')]),
('rawtext', 'bar</p>'),
]
program = [('setPosition', (1, 0)),
('defineMacro', 'M', macro)]
macros = {'M': macro}
self._run_check('<p metal:define-macro="M">foo'
'<span metal:define-slot="S">spam</span>bar</p>',
program, macros)
def check_fill_slot(self):
self._run_check('<p metal:use-macro="M">foo'
'<span metal:fill-slot="S">spam</span>bar</p>', [
('setPosition', (1, 0)),
('useMacro',
'M', '$M$',
{'S': [('startTag', 'span', [('metal:fill-slot', 'S', 'metal')]),
('rawtext', 'spam</span>')]},
[('startTag', 'p', [('metal:use-macro', 'M', 'metal')]),
('rawtext', 'foo'),
('setPosition', (1, 26)),
('fillSlot', 'S',
[('startTag', 'span', [('metal:fill-slot', 'S', 'metal')]),
('rawtext', 'spam</span>')]),
('rawtext', 'bar</p>')]),
])
class TALGeneratorTestCases(TestCaseBase):
def check_null(self):
self._run_check("", [])
def check_define(self):
self._run_check("<p tal:define='xyzzy string:spam'></p>", [
('setPosition', (1, 0)),
('beginScope',),
('setLocal', 'xyzzy', '$string:spam$'),
('startTag', 'p', [('tal:define', 'xyzzy string:spam', 'tal')]),
('rawtext', '</p>'),
('endScope',),
])
self._run_check("<p tal:define='local xyzzy string:spam'></p>", [
('setPosition', (1, 0)),
('beginScope',),
('setLocal', 'xyzzy', '$string:spam$'),
('startTag', 'p',
[('tal:define', 'local xyzzy string:spam', 'tal')]),
('rawtext', '</p>'),
('endScope',),
])
self._run_check("<p tal:define='global xyzzy string:spam'></p>", [
('setPosition', (1, 0)),
('beginScope',),
('setGlobal', 'xyzzy', '$string:spam$'),
('startTag', 'p',
[('tal:define', 'global xyzzy string:spam', 'tal')]),
('rawtext', '</p>'),
('endScope',),
])
self._run_check("<p tal:define='x string:spam; y x'></p>", [
('setPosition', (1, 0)),
('beginScope',),
('setLocal', 'x', '$string:spam$'),
('setLocal', 'y', '$x$'),
('startTag', 'p', [('tal:define', 'x string:spam; y x', 'tal')]),
('rawtext', '</p>'),
('endScope',),
])
self._run_check("<p tal:define='x string:;;;;; y x'></p>", [
('setPosition', (1, 0)),
('beginScope',),
('setLocal', 'x', '$string:;;$'),
('setLocal', 'y', '$x$'),
('startTag', 'p', [('tal:define', 'x string:;;;;; y x', 'tal')]),
('rawtext', '</p>'),
('endScope',),
])
self._run_check(
"<p tal:define='x string:spam; global y x; local z y'></p>", [
('setPosition', (1, 0)),
('beginScope',),
('setLocal', 'x', '$string:spam$'),
('setGlobal', 'y', '$x$'),
('setLocal', 'z', '$y$'),
('startTag', 'p',
[('tal:define', 'x string:spam; global y x; local z y', 'tal')]),
('rawtext', '</p>'),
('endScope',),
])
def check_condition(self):
self._run_check(
"<p><span tal:condition='python:1'><b>foo</b></span></p>", [
('rawtext', '<p>'),
('setPosition', (1, 3)),
('condition', '$python:1$',
[('startTag', 'span', [('tal:condition', 'python:1', 'tal')]),
('rawtext', '<b>foo</b></span>')]),
('rawtext', '</p>'),
])
def check_content(self):
self._run_check("<p tal:content='string:foo'>bar</p>", [
('setPosition', (1, 0)),
('startTag', 'p', [('tal:content', 'string:foo', 'tal')]),
('insertText', '$string:foo$', [('rawtext', 'bar')]),
('rawtext', '</p>'),
])
self._run_check("<p tal:content='text string:foo'>bar</p>", [
('setPosition', (1, 0)),
('startTag', 'p', [('tal:content', 'text string:foo', 'tal')]),
('insertText', '$string:foo$', [('rawtext', 'bar')]),
('rawtext', '</p>'),
])
self._run_check("<p tal:content='structure string:<br>'>bar</p>", [
('setPosition', (1, 0)),
('startTag', 'p',
[('tal:content', 'structure string:<br>', 'tal')]),
('insertStructure', '$string:<br>$', {}, [('rawtext', 'bar')]),
('rawtext', '</p>'),
])
def check_replace(self):
self._run_check("<p tal:replace='string:foo'>bar</p>", [
('setPosition', (1, 0)),
('insertText', '$string:foo$',
[('startTag', 'p', [('tal:replace', 'string:foo', 'tal')]),
('rawtext', 'bar</p>')]),
])
self._run_check("<p tal:replace='text string:foo'>bar</p>", [
('setPosition', (1, 0)),
('insertText', '$string:foo$',
[('startTag', 'p', [('tal:replace', 'text string:foo', 'tal')]),
('rawtext', 'bar</p>')]),
])
self._run_check("<p tal:replace='structure string:<br>'>bar</p>", [
('setPosition', (1, 0)),
('insertStructure', '$string:<br>$', {},
[('startTag', 'p',
[('tal:replace', 'structure string:<br>', 'tal')]),
('rawtext', 'bar</p>')]),
])
def check_repeat(self):
self._run_check("<p tal:repeat='x python:(1,2,3)'>"
"<span tal:replace='x'>dummy</span></p>", [
('setPosition', (1, 0)),
('beginScope',),
('loop', 'x', '$python:(1,2,3)$',
[('startTag', 'p', [('tal:repeat', 'x python:(1,2,3)', 'tal')]),
('setPosition', (1, 33)),
('insertText', '$x$',
[('startTag', 'span', [('tal:replace', 'x', 'tal')]),
('rawtext', 'dummy</span>')]),
('rawtext', '</p>')]),
('endScope',),
])
def check_attributes(self):
self._run_check("<a href='foo' name='bar' tal:attributes="
"'href string:http://www.zope.org; x string:y'>"
"link</a>", [
('setPosition', (1, 0)),
('startTag', 'a',
[('href', 'foo', 'replace', '$string:http://www.zope.org$'),
('name', 'bar'),
('tal:attributes',
'href string:http://www.zope.org; x string:y', 'tal'),
('x', '', 'replace', '$string:y$')]),
('rawtext', 'link</a>'),
])
self._run_check("<p tal:replace='structure string:<img>' "
"tal:attributes='src string:foo.png'>duh</p>", [
('setPosition', (1, 0)),
('insertStructure', '$string:<img>$',
{'src': '$string:foo.png$'},
[('startTag', 'p',
[('tal:replace', 'structure string:<img>', 'tal'),
('tal:attributes', 'src string:foo.png', 'tal')]),
('rawtext', 'duh</p>')]),
])
def check_on_error(self):
self._run_check("<p tal:on-error='string:error' "
"tal:content='notHere'>okay</p>", [
('setPosition', (1, 0)),
('onError',
[('startTag', 'p',
[('tal:on-error', 'string:error', 'tal'),
('tal:content', 'notHere', 'tal')]),
('insertText', '$notHere$', [('rawtext', 'okay')]),
('rawtext', '</p>')],
[('startTag', 'p',
[('tal:on-error', 'string:error', 'tal'),
('tal:content', 'notHere', 'tal')]),
('insertText', '$string:error$', []),
('rawtext', '</p>')]),
])
self._run_check("<p tal:on-error='string:error' "
"tal:replace='notHere'>okay</p>", [
('setPosition', (1, 0)),
('onError',
[('insertText', '$notHere$',
[('startTag', 'p',
[('tal:on-error', 'string:error', 'tal'),
('tal:replace', 'notHere', 'tal')]),
('rawtext', 'okay</p>')])],
[('startTag', 'p',
[('tal:on-error', 'string:error', 'tal'),
('tal:replace', 'notHere', 'tal')]),
('insertText', '$string:error$', []),
('rawtext', '</p>')]),
])
def check_dup_attr(self):
self._should_error("<img tal:condition='x' tal:condition='x'>")
self._should_error("<img metal:define-macro='x' "
"metal:define-macro='x'>", METALError)
def check_tal_errors(self):
self._should_error("<p tal:define='x' />")
self._should_error("<p tal:repeat='x' />")
self._should_error("<p tal:foobar='x' />")
self._should_error("<p tal:replace='x' tal:content='x' />")
self._should_error("<p tal:replace='x'>")
def check_metal_errors(self):
exc = METALError
self._should_error(2*"<p metal:define-macro='x'>xxx</p>", exc)
## self._should_error("<html metal:define-macro='x'>" +
## 2*"<p metal:define-slot='y' />" + "</html>")
self._should_error("<html metal:use-macro='x'>" +
2*"<p metal:fill-slot='y' />" + "</html>", exc)
self._should_error("<p metal:foobar='x' />", exc)
self._should_error("<p metal:define-slot='x' metal:fill-slot='x' />",
exc)
self._should_error("<p metal:define-macro='x'>", exc)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(HTMLTALParserTestCases, "check_"))
suite.addTest(unittest.makeSuite(METALGeneratorTestCases, "check_"))
suite.addTest(unittest.makeSuite(TALGeneratorTestCases, "check_"))
return suite
if __name__ == "__main__":
errs = utils.run_suite(test_suite())
sys.exit(errs and 1 or 0)
#! /usr/bin/env python1.5
"""Tests for TALInterpreter."""
import sys
import utils
import unittest
from TAL.TALDefs import METALError
from TAL.HTMLTALParser import HTMLTALParser
from TAL.TALInterpreter import TALInterpreter
from TAL.DummyEngine import DummyEngine
class MacroErrorsTestCase(unittest.TestCase):
def _compile(self, source):
parser = HTMLTALParser()
parser.parseString(source)
program, macros = parser.getCode()
return program, macros
def setUp(self):
dummy, macros = self._compile('<p metal:define-macro="M">Booh</p>')
self.macro = macros['M']
self.engine = DummyEngine(macros)
program, dummy = self._compile('<p metal:use-macro="M">Bah</p>')
self.interpreter = TALInterpreter(program, {}, self.engine)
def tearDown(self):
try:
self.interpreter()
except METALError:
pass
else:
self.fail("Expected METALError")
def check_mode_error(self):
self.macro[1] = ("mode", "duh")
def check_version_error(self):
self.macro[0] = ("version", "duh")
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(MacroErrorsTestCase, "check_"))
return suite
if __name__ == "__main__":
errs = utils.run_suite(test_suite())
sys.exit(errs and 1 or 0)
#! /usr/bin/env python1.5
"""Tests for XMLParser.py."""
import string
import sys
import utils
import unittest
from TAL import XMLParser
class EventCollector(XMLParser.XMLParser):
def __init__(self):
self.events = []
self.append = self.events.append
XMLParser.XMLParser.__init__(self)
self.parser.ordered_attributes = 1
def get_events(self):
# Normalize the list of events so that buffer artefacts don't
# separate runs of contiguous characters.
L = []
prevtype = None
for event in self.events:
type = event[0]
if type == prevtype == "data":
L[-1] = ("data", L[-1][1] + event[1])
else:
L.append(event)
prevtype = type
self.events = L
return L
# structure markup
def StartElementHandler(self, tag, attrs):
self.append(("starttag", tag, attrs))
def EndElementHandler(self, tag):
self.append(("endtag", tag))
# all other markup
def CommentHandler(self, data):
self.append(("comment", data))
def handle_charref(self, data):
self.append(("charref", data))
def CharacterDataHandler(self, data):
self.append(("data", data))
def StartDoctypeDeclHandler(self, rootelem, publicId, systemId, subset):
self.append(("doctype", rootelem, systemId, publicId, subset))
def XmlDeclHandler(self, version, encoding, standalone):
self.append(("decl", version, encoding, standalone))
def ExternalEntityRefHandler(self, data):
self.append(("entityref", data))
def ProcessingInstructionHandler(self, target, data):
self.append(("pi", target, data))
class EventCollectorExtra(EventCollector):
def handle_starttag(self, tag, attrs):
EventCollector.handle_starttag(self, tag, attrs)
self.append(("starttag_text", self.get_starttag_text()))
class SegmentedFile:
def __init__(self, parts):
self.parts = list(parts)
def read(self, bytes):
if self.parts:
s = self.parts.pop(0)
else:
s = ''
return s
class XMLParserTestCase(unittest.TestCase):
def _run_check(self, source, events, collector=EventCollector):
parser = collector()
if isinstance(source, type([])):
parser.parseStream(SegmentedFile(source))
else:
parser.parseString(source)
self.assert_(parser.get_events() == events, parser.get_events())
def _run_check_extra(self, source, events):
self._run_check(source, events, EventCollectorExtra)
def _parse_error(self, source):
def parse(source=source):
parser = XMLParser.XMLParser()
parser.parseString(source)
self.assertRaises(XMLParser.XMLParseError, parse)
def check_processing_instruction_only(self):
self._run_check("<?processing instruction?><a/>", [
("pi", "processing", "instruction"),
("starttag", "a", []),
("endtag", "a"),
])
def check_simple_html(self):
self._run_check("""\
<?xml version='1.0' encoding='iso-8859-1'?>
<!DOCTYPE html PUBLIC 'foo' 'bar'>
<html>&entity;&#32;
<!--comment1a
-></foo><bar>&lt;<?pi?></foo<bar
comment1b-->
<img src='Bar' ismap=''/>sample
text
<!--comment2a- -comment2b-->
</html>
""", [
("decl", "1.0", "iso-8859-1", -1),
("doctype", "html", "foo", "bar", 0),
("starttag", "html", []),
# ("entityref", "entity"),
("data", " \n"),
("comment", "comment1a\n-></foo><bar>&lt;<?pi?></foo<bar\ncomment1b"),
("data", "\n"),
("starttag", "img", ["src", "Bar", "ismap", ""]),
("endtag", "img"),
("data", "sample\ntext\n"),
("comment", "comment2a- -comment2b"),
("data", "\n"),
("endtag", "html"),
])
def check_bad_nesting(self):
try:
self._run_check("<a><b></a></b>", [
("starttag", "a", []),
("starttag", "b", []),
("endtag", "a"),
("endtag", "b"),
])
except:
e = sys.exc_info()[1]
self.assert_(e.lineno == 1,
"did not receive correct position information")
else:
self.fail("expected parse error: bad nesting")
def check_attr_syntax(self):
output = [
("starttag", "a", ["b", "v", "c", "v"]),
("endtag", "a"),
]
self._run_check("""<a b='v' c="v"/>""", output)
self._run_check("""<a b = 'v' c = "v"/>""", output)
self._run_check("""<a\nb\n=\n'v'\nc\n=\n"v"\n/>""", output)
self._run_check("""<a\tb\t=\t'v'\tc\t=\t"v"\t/>""", output)
def check_attr_values(self):
self._run_check("""<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'/>""",
[("starttag", "a", ["b", "xxx xxx",
"c", "yyy yyy",
"d", " xyz "]),
("endtag", "a"),
])
self._run_check("""<a b='' c="" d=''/>""", [
("starttag", "a", ["b", "", "c", "", "d", ""]),
("endtag", "a"),
])
def check_attr_entity_replacement(self):
self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'/>""", [
("starttag", "a", ["b", "&><\"'"]),
("endtag", "a"),
])
def check_attr_funky_names(self):
self._run_check("""<a a.b='v' c:d='v' e-f='v'/>""", [
("starttag", "a", ["a.b", "v", "c:d", "v", "e-f", "v"]),
("endtag", "a"),
])
def check_starttag_end_boundary(self):
self._run_check("""<a b='&lt;'/>""", [
("starttag", "a", ["b", "<"]),
("endtag", "a"),
])
self._run_check("""<a b='&gt;'/>""", [
("starttag", "a", ["b", ">"]),
("endtag", "a"),
])
def check_buffer_artefacts(self):
output = [("starttag", "a", ["b", "<"]), ("endtag", "a")]
self._run_check(["<a b='&lt;'/>"], output)
self._run_check(["<a ", "b='&lt;'/>"], output)
self._run_check(["<a b", "='&lt;'/>"], output)
self._run_check(["<a b=", "'&lt;'/>"], output)
self._run_check(["<a b='&lt;", "'/>"], output)
self._run_check(["<a b='&lt;'", "/>"], output)
output = [("starttag", "a", ["b", ">"]), ("endtag", "a")]
self._run_check(["<a b='&gt;'/>"], output)
self._run_check(["<a ", "b='&gt;'/>"], output)
self._run_check(["<a b", "='&gt;'/>"], output)
self._run_check(["<a b=", "'&gt;'/>"], output)
self._run_check(["<a b='&gt;", "'/>"], output)
self._run_check(["<a b='&gt;'", "/>"], output)
def check_starttag_junk_chars(self):
self._parse_error("<")
self._parse_error("<>")
self._parse_error("</>")
self._parse_error("</$>")
self._parse_error("</")
self._parse_error("</a")
self._parse_error("</a")
self._parse_error("<a<a>")
self._parse_error("</a<a>")
self._parse_error("<$")
self._parse_error("<$>")
self._parse_error("<!")
self._parse_error("<a $>")
self._parse_error("<a")
self._parse_error("<a foo='bar'")
self._parse_error("<a foo='bar")
self._parse_error("<a foo='>'")
self._parse_error("<a foo='>")
def check_declaration_junk_chars(self):
self._parse_error("<!DOCTYPE foo $ >")
# Support for the Zope regression test framework:
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(XMLParserTestCase, "check_"))
return suite
if __name__ == "__main__":
errs = utils.run_suite(test_suite())
sys.exit(errs and 1 or 0)
"""Helper functions for the test suite."""
import os
import sys
mydir = os.path.abspath(os.path.dirname(__file__))
codedir = os.path.dirname(os.path.dirname(mydir))
if codedir not in sys.path:
sys.path.append(codedir)
import unittest
def run_suite(suite, outf=None, errf=None):
if outf is None:
outf = sys.stdout
runner = unittest.TextTestRunner(outf)
result = runner.run(suite)
## print "\n\n"
## if result.errors:
## print "Errors (unexpected exceptions):"
## map(print_error, result.errors)
## print
## if result.failures:
## print "Failures (assertion failures):"
## map(print_error, result.failures)
## print
newerrs = len(result.errors) + len(result.failures)
if newerrs:
print "'Errors' indicate exceptions other than AssertionError."
print "'Failures' indicate AssertionError"
if errf is None:
errf = sys.stderr
errf.write("%d errors, %d failures\n"
% (len(result.errors), len(result.failures)))
return newerrs
def print_error(info):
testcase, (type, e, tb) = info
<html> <html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" <body xmlns:m="http://xml.zope.org/namespaces/metal"
m:use-macro="test/input/test05.html/body"> m:use-macro="tests/input/test05.html/body">
dummy body in test6 dummy body in test6
</body> </body>
</html> </html>
<?xml version="1.0" ?> <?xml version="1.0" ?>
<html> <html>
<body xmlns:m="http://xml.zope.org/namespaces/metal" <body xmlns:m="http://xml.zope.org/namespaces/metal"
m:use-macro="test/input/test05.xml/body"> m:use-macro="tests/input/test05.xml/body">
dummy body in test6 dummy body in test6
</body> </body>
</html> </html>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/input/test07.html/myTable"> <table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="tests/input/test07.html/myTable">
<!-- macro use with slots --> <!-- macro use with slots -->
<tr> <tr>
<td> <td>
......
<?xml version="1.0" ?> <?xml version="1.0" ?>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/input/test07.xml/myTable"> <table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="tests/input/test07.xml/myTable">
<!-- macro use with slots --> <!-- macro use with slots -->
<tr> <tr>
<td> <td>
......
<html><body> <html><body>
<table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="test/input/test07.html/myTable"> <table xmlns:m="http://xml.zope.org/namespaces/metal" m:use-macro="tests/input/test07.html/myTable">
<!-- macro use with slots --> <!-- macro use with slots -->
<tr> <tr>
<td> <td>
......
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