Commit 633669f1 authored by Guido van Rossum's avatar Guido van Rossum

Add a version to the generated intermediate code. This is simply a

new opcode, "version", whose argument is the new constant
TALDefs.TAL_VERSION (currently "1.0").  The opcode implementation
currently asserts that the correct version is given; future
implementations can implement backwards compatible behavior.
parent e403208c
...@@ -86,14 +86,6 @@ TO DO ...@@ -86,14 +86,6 @@ TO DO
- TALInterpreter currently always uses an XML parser to parse inserted - TALInterpreter currently always uses an XML parser to parse inserted
structure; it should use a parser appropriate to the mode. structure; it should use a parser appropriate to the mode.
- The HTML parser currently returns <img ismap> as if it said <img
ismap="ismap">. This will break with old browsers. I see two ways
to fix this: (1) change the API to return None for the value in this
case, and then generate different code; or (2) special-case the
generator to recognize that the value is the same as the attribute
name for specific attribute names (the list is BOOLEAN_HTML_ATTRS in
TALInterpreter).
- HTMLTALParser.py and TALParser.py are silly names. Should be - HTMLTALParser.py and TALParser.py are silly names. Should be
HTMLTALCompiler.py and XMLTALCompiler.py (or maybe shortened, HTMLTALCompiler.py and XMLTALCompiler.py (or maybe shortened,
without "TAL"?) without "TAL"?)
......
...@@ -86,6 +86,8 @@ ...@@ -86,6 +86,8 @@
Common definitions used by TAL and METAL compilation an transformation. Common definitions used by TAL and METAL compilation an transformation.
""" """
TAL_VERSION = "1.0"
XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace
XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations
......
...@@ -110,6 +110,7 @@ class TALGenerator: ...@@ -110,6 +110,7 @@ class TALGenerator:
self.slots = {} self.slots = {}
self.slotStack = [] self.slotStack = []
self.xml = xml self.xml = xml
self.emit("version", TAL_VERSION)
def getCode(self): def getCode(self):
return self.optimize(self.program), self.macros return self.optimize(self.program), self.macros
......
...@@ -97,7 +97,7 @@ except ImportError: ...@@ -97,7 +97,7 @@ except ImportError:
from StringIO import StringIO from StringIO import StringIO
from XMLParser import XMLParser from XMLParser import XMLParser
from TALDefs import TALError, TALESError, quote from TALDefs import TALError, TALESError, quote, TAL_VERSION
BOOLEAN_HTML_ATTRS = [ BOOLEAN_HTML_ATTRS = [
# List of Boolean attributes in HTML that should be rendered in # List of Boolean attributes in HTML that should be rendered in
...@@ -177,6 +177,9 @@ class TALInterpreter: ...@@ -177,6 +177,9 @@ class TALInterpreter:
apply(method, args) apply(method, args)
self.level = self.level - 1 self.level = self.level - 1
def do_version(self, version):
assert version == TAL_VERSION
def do_setPosition(self, position): def do_setPosition(self, position):
self.position = position self.position = position
......
...@@ -8,6 +8,7 @@ import utils ...@@ -8,6 +8,7 @@ import utils
import unittest import unittest
from TAL import HTMLTALParser from TAL import HTMLTALParser
from TAL.TALDefs import TAL_VERSION
class HTMLTALParserTestCases(unittest.TestCase): class HTMLTALParserTestCases(unittest.TestCase):
...@@ -28,6 +29,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -28,6 +29,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_simple_identity(self): def check_code_simple_identity(self):
self._run_check("""<html a='b' b="c" c=d><title>My Title</html>""", [ self._run_check("""<html a='b' b="c" c=d><title>My Title</html>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<html a="b" b="c" c="d">'), ('rawtext', '<html a="b" b="c" c="d">'),
('setPosition', (1, 22)), ('setPosition', (1, 22)),
...@@ -36,6 +38,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -36,6 +38,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_implied_list_closings(self): def check_code_implied_list_closings(self):
self._run_check("""<ul><li><p><p><li></ul>""", [ self._run_check("""<ul><li><p><p><li></ul>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<ul>'), ('rawtext', '<ul>'),
('setPosition', (1, 4)), ('setPosition', (1, 4)),
...@@ -48,6 +51,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -48,6 +51,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
('rawtext', '<li></li></ul>'), ('rawtext', '<li></li></ul>'),
]) ])
self._run_check("""<dl><dt><dt><dd><dd><ol><li><li></ol></dl>""", [ self._run_check("""<dl><dt><dt><dd><dd><ol><li><li></ol></dl>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<dl>'), ('rawtext', '<dl>'),
('setPosition', (1, 4)), ('setPosition', (1, 4)),
...@@ -69,6 +73,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -69,6 +73,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_implied_table_closings(self): def check_code_implied_table_closings(self):
self._run_check("""<p>text <table><tr><th>head\t<tr><td>cell\t""" self._run_check("""<p>text <table><tr><th>head\t<tr><td>cell\t"""
"""<table><tr><td>cell \n \t \n<tr>""", [ """<table><tr><td>cell \n \t \n<tr>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<p>text</p> '), ('rawtext', '<p>text</p> '),
('setPosition', (1, 8)), ('setPosition', (1, 8)),
...@@ -92,6 +97,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -92,6 +97,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
]) ])
self._run_check("""<table><tr><td>cell """ self._run_check("""<table><tr><td>cell """
"""<table><tr><td>cell </table></table>""", [ """<table><tr><td>cell </table></table>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<table>'), ('rawtext', '<table>'),
('setPosition', (1, 7)), ('setPosition', (1, 7)),
...@@ -113,6 +119,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -113,6 +119,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_attr_syntax(self): def check_code_attr_syntax(self):
output = [ output = [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="v" c="v" d="v" e></a>'), ('rawtext', '<a b="v" c="v" d="v" e></a>'),
] ]
...@@ -123,11 +130,13 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -123,11 +130,13 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_attr_values(self): def check_code_attr_values(self):
self._run_check( self._run_check(
"""<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'>""", """<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'>""", [
[('setPosition', (1, 0)), ('version', TAL_VERSION),
('rawtext', ('setPosition', (1, 0)),
'<a b="xxx\n\txxx" c="yyy\t\nyyy" d="\txyz\n"></a>')]) ('rawtext',
'<a b="xxx\n\txxx" c="yyy\t\nyyy" d="\txyz\n"></a>')])
self._run_check("""<a b='' c="" d=>""", [ self._run_check("""<a b='' c="" d=>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="" c="" d=""></a>'), ('rawtext', '<a b="" c="" d=""></a>'),
]) ])
...@@ -135,35 +144,42 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -135,35 +144,42 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_attr_entity_replacement(self): def check_code_attr_entity_replacement(self):
# we expect entities *not* to be replaced by HTLMParser! # we expect entities *not* to be replaced by HTLMParser!
self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [ self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="&amp;&gt;&lt;&quot;\'"></a>'), ('rawtext', '<a b="&amp;&gt;&lt;&quot;\'"></a>'),
]) ])
self._run_check("""<a b='\"'>""", [ self._run_check("""<a b='\"'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', "<a b='\"'></a>"), ('rawtext', "<a b='\"'></a>"),
]) ])
self._run_check("""<a b='&'>""", [ self._run_check("""<a b='&'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="&amp;"></a>'), ('rawtext', '<a b="&amp;"></a>'),
]) ])
self._run_check("""<a b='<'>""", [ self._run_check("""<a b='<'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="&lt;"></a>'), ('rawtext', '<a b="&lt;"></a>'),
]) ])
def check_code_attr_funky_names(self): def check_code_attr_funky_names(self):
self._run_check("""<a a.b='v' c:d=v e-f=v>""", [ self._run_check("""<a a.b='v' c:d=v e-f=v>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a a.b="v" c:d="v" e-f="v"></a>'), ('rawtext', '<a a.b="v" c:d="v" e-f="v"></a>'),
]) ])
def check_code_pcdata_entityref(self): def check_code_pcdata_entityref(self):
self._run_check("""&nbsp;""", [ self._run_check("""&nbsp;""", [
('version', TAL_VERSION),
('rawtext', '&nbsp;'), ('rawtext', '&nbsp;'),
]) ])
def check_code_short_endtags(self): def check_code_short_endtags(self):
self._run_check("""<html><img/></html>""", [ self._run_check("""<html><img/></html>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<html>'), ('rawtext', '<html>'),
('setPosition', (1, 6)), ('setPosition', (1, 6)),
......
...@@ -8,6 +8,7 @@ import utils ...@@ -8,6 +8,7 @@ import utils
import unittest import unittest
from TAL import HTMLTALParser from TAL import HTMLTALParser
from TAL.TALDefs import TAL_VERSION
class HTMLTALParserTestCases(unittest.TestCase): class HTMLTALParserTestCases(unittest.TestCase):
...@@ -28,6 +29,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -28,6 +29,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_simple_identity(self): def check_code_simple_identity(self):
self._run_check("""<html a='b' b="c" c=d><title>My Title</html>""", [ self._run_check("""<html a='b' b="c" c=d><title>My Title</html>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<html a="b" b="c" c="d">'), ('rawtext', '<html a="b" b="c" c="d">'),
('setPosition', (1, 22)), ('setPosition', (1, 22)),
...@@ -36,6 +38,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -36,6 +38,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_implied_list_closings(self): def check_code_implied_list_closings(self):
self._run_check("""<ul><li><p><p><li></ul>""", [ self._run_check("""<ul><li><p><p><li></ul>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<ul>'), ('rawtext', '<ul>'),
('setPosition', (1, 4)), ('setPosition', (1, 4)),
...@@ -48,6 +51,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -48,6 +51,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
('rawtext', '<li></li></ul>'), ('rawtext', '<li></li></ul>'),
]) ])
self._run_check("""<dl><dt><dt><dd><dd><ol><li><li></ol></dl>""", [ self._run_check("""<dl><dt><dt><dd><dd><ol><li><li></ol></dl>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<dl>'), ('rawtext', '<dl>'),
('setPosition', (1, 4)), ('setPosition', (1, 4)),
...@@ -69,6 +73,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -69,6 +73,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_implied_table_closings(self): def check_code_implied_table_closings(self):
self._run_check("""<p>text <table><tr><th>head\t<tr><td>cell\t""" self._run_check("""<p>text <table><tr><th>head\t<tr><td>cell\t"""
"""<table><tr><td>cell \n \t \n<tr>""", [ """<table><tr><td>cell \n \t \n<tr>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<p>text</p> '), ('rawtext', '<p>text</p> '),
('setPosition', (1, 8)), ('setPosition', (1, 8)),
...@@ -92,6 +97,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -92,6 +97,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
]) ])
self._run_check("""<table><tr><td>cell """ self._run_check("""<table><tr><td>cell """
"""<table><tr><td>cell </table></table>""", [ """<table><tr><td>cell </table></table>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<table>'), ('rawtext', '<table>'),
('setPosition', (1, 7)), ('setPosition', (1, 7)),
...@@ -113,6 +119,7 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -113,6 +119,7 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_attr_syntax(self): def check_code_attr_syntax(self):
output = [ output = [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="v" c="v" d="v" e></a>'), ('rawtext', '<a b="v" c="v" d="v" e></a>'),
] ]
...@@ -123,11 +130,13 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -123,11 +130,13 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_attr_values(self): def check_code_attr_values(self):
self._run_check( self._run_check(
"""<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'>""", """<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'>""", [
[('setPosition', (1, 0)), ('version', TAL_VERSION),
('rawtext', ('setPosition', (1, 0)),
'<a b="xxx\n\txxx" c="yyy\t\nyyy" d="\txyz\n"></a>')]) ('rawtext',
'<a b="xxx\n\txxx" c="yyy\t\nyyy" d="\txyz\n"></a>')])
self._run_check("""<a b='' c="" d=>""", [ self._run_check("""<a b='' c="" d=>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="" c="" d=""></a>'), ('rawtext', '<a b="" c="" d=""></a>'),
]) ])
...@@ -135,35 +144,42 @@ class HTMLTALParserTestCases(unittest.TestCase): ...@@ -135,35 +144,42 @@ class HTMLTALParserTestCases(unittest.TestCase):
def check_code_attr_entity_replacement(self): def check_code_attr_entity_replacement(self):
# we expect entities *not* to be replaced by HTLMParser! # we expect entities *not* to be replaced by HTLMParser!
self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [ self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="&amp;&gt;&lt;&quot;\'"></a>'), ('rawtext', '<a b="&amp;&gt;&lt;&quot;\'"></a>'),
]) ])
self._run_check("""<a b='\"'>""", [ self._run_check("""<a b='\"'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', "<a b='\"'></a>"), ('rawtext', "<a b='\"'></a>"),
]) ])
self._run_check("""<a b='&'>""", [ self._run_check("""<a b='&'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="&amp;"></a>'), ('rawtext', '<a b="&amp;"></a>'),
]) ])
self._run_check("""<a b='<'>""", [ self._run_check("""<a b='<'>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a b="&lt;"></a>'), ('rawtext', '<a b="&lt;"></a>'),
]) ])
def check_code_attr_funky_names(self): def check_code_attr_funky_names(self):
self._run_check("""<a a.b='v' c:d=v e-f=v>""", [ self._run_check("""<a a.b='v' c:d=v e-f=v>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<a a.b="v" c:d="v" e-f="v"></a>'), ('rawtext', '<a a.b="v" c:d="v" e-f="v"></a>'),
]) ])
def check_code_pcdata_entityref(self): def check_code_pcdata_entityref(self):
self._run_check("""&nbsp;""", [ self._run_check("""&nbsp;""", [
('version', TAL_VERSION),
('rawtext', '&nbsp;'), ('rawtext', '&nbsp;'),
]) ])
def check_code_short_endtags(self): def check_code_short_endtags(self):
self._run_check("""<html><img/></html>""", [ self._run_check("""<html><img/></html>""", [
('version', TAL_VERSION),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('rawtext', '<html>'), ('rawtext', '<html>'),
('setPosition', (1, 6)), ('setPosition', (1, 6)),
......
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