[Zope-Checkins] CVS: Zope3/lib/python/Zope/TAL/tests - test_htmltalparser.py:1.30 test_talinterpreter.py:1.5

Fred L. Drake, Jr. fdrake@acm.org
Wed, 12 Jun 2002 11:39:37 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/TAL/tests
In directory cvs.zope.org:/tmp/cvs-serv12767/tests

Modified Files:
	test_htmltalparser.py test_talinterpreter.py 
Log Message:
Merge from fdrake-tal-i18n-branch:
This is the bulk of the changes from the branch.


=== Zope3/lib/python/Zope/TAL/tests/test_htmltalparser.py 1.29 => 1.30 ===
     def check_define_macro(self):
         macro = self.initial_program + [
-            ('startTag', ('p', [('metal:define-macro', 'M', 2)])),
+            ('startTag', ('p', [('metal:define-macro', 'M', 'metal')])),
             rawtext('booh</p>'),
             ]
         program = [
@@ -182,17 +182,17 @@
             ('setPosition', (1, 0)),
             ('useMacro',
              ('M', '$M$', {},
-              [('startTag', ('p', [('metal:use-macro', 'M', 2)])),
+              [('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', 2)])),
+            ('startTag', ('p', [('metal:define-macro', 'M', 'metal')])),
             rawtext('foo'),
             ('setPosition', (1, 29)),
             ('defineSlot', ('S',
-             [('startTag', ('span', [('metal:define-slot', 'S', 2)])),
+             [('startTag', ('span', [('metal:define-slot', 'S', 'metal')])),
               rawtext('spam</span>')])),
             rawtext('bar</p>'),
             ]
@@ -210,13 +210,13 @@
             ('useMacro',
              ('M', '$M$',
               {'S': [('startTag', ('span',
-                                   [('metal:fill-slot', 'S', 2)])),
+                                   [('metal:fill-slot', 'S', 'metal')])),
                      rawtext('spam</span>')]},
-             [('startTag', ('p', [('metal:use-macro', 'M', 2)])),
+             [('startTag', ('p', [('metal:use-macro', 'M', 'metal')])),
               rawtext('foo'),
               ('setPosition', (1, 26)),
               ('fillSlot', ('S',
-               [('startTag', ('span', [('metal:fill-slot', 'S', 2)])),
+               [('startTag', ('span', [('metal:fill-slot', 'S', 'metal')])),
                 rawtext('spam</span>')])),
               rawtext('bar</p>')])),
             ])
@@ -232,7 +232,7 @@
             ('setPosition', (1, 0)),
             ('beginScope', {'tal:define': 'xyzzy string:spam'}),
             ('setLocal', ('xyzzy', '$string:spam$')),
-            ('startTag', ('p', [('tal:define', 'xyzzy string:spam', 3)])),
+            ('startTag', ('p', [('tal:define', 'xyzzy string:spam', 'tal')])),
             ('endScope', ()),
             rawtext('</p>'),
             ])
@@ -243,7 +243,7 @@
             ('beginScope', {'tal:define': 'local xyzzy string:spam'}),
             ('setLocal', ('xyzzy', '$string:spam$')),
             ('startTag', ('p',
-             [('tal:define', 'local xyzzy string:spam', 3)])),
+             [('tal:define', 'local xyzzy string:spam', 'tal')])),
             ('endScope', ()),
             rawtext('</p>'),
             ])
@@ -254,7 +254,7 @@
             ('beginScope', {'tal:define': 'global xyzzy string:spam'}),
             ('setGlobal', ('xyzzy', '$string:spam$')),
             ('startTag', ('p',
-             [('tal:define', 'global xyzzy string:spam', 3)])),
+             [('tal:define', 'global xyzzy string:spam', 'tal')])),
             ('endScope', ()),
             rawtext('</p>'),
             ])
@@ -265,7 +265,7 @@
             ('beginScope', {'tal:define': 'x string:spam; y x'}),
             ('setLocal', ('x', '$string:spam$')),
             ('setLocal', ('y', '$x$')),
-            ('startTag', ('p', [('tal:define', 'x string:spam; y x', 3)])),
+            ('startTag', ('p', [('tal:define', 'x string:spam; y x', 'tal')])),
             ('endScope', ()),
             rawtext('</p>'),
             ])
@@ -276,7 +276,7 @@
             ('beginScope', {'tal:define': 'x string:;;;;; y x'}),
             ('setLocal', ('x', '$string:;;$')),
             ('setLocal', ('y', '$x$')),
-            ('startTag', ('p', [('tal:define', 'x string:;;;;; y x', 3)])),
+            ('startTag', ('p', [('tal:define', 'x string:;;;;; y x', 'tal')])),
             ('endScope', ()),
             rawtext('</p>'),
             ])
@@ -291,7 +291,7 @@
             ('setGlobal', ('y', '$x$')),
             ('setLocal', ('z', '$y$')),
             ('startTag', ('p',
-             [('tal:define', 'x string:spam; global y x; local z y', 3)])),
+             [('tal:define', 'x string:spam; global y x; local z y', 'tal')])),
             ('endScope', ()),
             rawtext('</p>'),
             ])
@@ -303,7 +303,7 @@
             ('setPosition', (1, 3)),
             ('beginScope', {'tal:condition': 'python:1'}),
             ('condition', ('$python:1$',
-             [('startTag', ('span', [('tal:condition', 'python:1', 3)])),
+             [('startTag', ('span', [('tal:condition', 'python:1', 'tal')])),
               rawtext('<b>foo</b></span>')])),
             ('endScope', ()),
             rawtext('</p>'),
@@ -312,8 +312,8 @@
     def check_content_1(self):
         self._run_check("<p tal:content='string:foo'>bar</p>", [
              ('setPosition', (1, 0)),
-             ('beginScope', {'tal:content': 'string:foo'}), 
-             ('startTag', ('p', [('tal:content', 'string:foo', 3)])),
+             ('beginScope', {'tal:content': 'string:foo'}),
+             ('startTag', ('p', [('tal:content', 'string:foo', 'tal')])),
              ('insertText', ('$string:foo$', [rawtext('bar')])),
              ('endScope', ()),
              rawtext('</p>'),
@@ -323,7 +323,7 @@
         self._run_check("<p tal:content='text string:foo'>bar</p>", [
              ('setPosition', (1, 0)),
              ('beginScope', {'tal:content': 'text string:foo'}),
-             ('startTag', ('p', [('tal:content', 'text string:foo', 3)])),
+             ('startTag', ('p', [('tal:content', 'text string:foo', 'tal')])),
              ('insertText', ('$string:foo$', [rawtext('bar')])),
              ('endScope', ()),
              rawtext('</p>'),
@@ -334,7 +334,7 @@
              ('setPosition', (1, 0)),
              ('beginScope', {'tal:content': 'structure string:<br>'}),
              ('startTag', ('p',
-              [('tal:content', 'structure string:<br>', 3)])),
+              [('tal:content', 'structure string:<br>', 'tal')])),
              ('insertStructure',
               ('$string:<br>$', {}, [rawtext('bar')])),
              ('endScope', ()),
@@ -346,7 +346,7 @@
              ('setPosition', (1, 0)),
              ('beginScope', {'tal:replace': 'string:foo'}),
              ('insertText', ('$string:foo$',
-              [('startTag', ('p', [('tal:replace', 'string:foo', 3)])),
+              [('startTag', ('p', [('tal:replace', 'string:foo', 'tal')])),
                rawtext('bar</p>')])),
              ('endScope', ()),
              ])
@@ -357,7 +357,7 @@
              ('beginScope', {'tal:replace': 'text string:foo'}),
              ('insertText', ('$string:foo$',
               [('startTag', ('p',
-                             [('tal:replace', 'text string:foo', 3)])),
+                             [('tal:replace', 'text string:foo', 'tal')])),
                rawtext('bar</p>')])),
              ('endScope', ()),
              ])
@@ -368,7 +368,7 @@
              ('beginScope', {'tal:replace': 'structure string:<br>'}),
              ('insertStructure', ('$string:<br>$', {},
               [('startTag', ('p',
-                [('tal:replace', 'structure string:<br>', 3)])),
+                [('tal:replace', 'structure string:<br>', 'tal')])),
                rawtext('bar</p>')])),
              ('endScope', ()),
              ])
@@ -380,11 +380,11 @@
              ('beginScope', {'tal:repeat': 'x python:(1,2,3)'}),
              ('loop', ('x', '$python:(1,2,3)$',
               [('startTag', ('p',
-                             [('tal:repeat', 'x python:(1,2,3)', 3)])),
+                             [('tal:repeat', 'x python:(1,2,3)', 'tal')])),
                ('setPosition', (1, 33)),
                ('beginScope', {'tal:replace': 'x'}),
                ('insertText', ('$x$',
-                [('startTag', ('span', [('tal:replace', 'x', 3)])),
+                [('startTag', ('span', [('tal:replace', 'x', 'tal')])),
                  rawtext('dummy</span>')])),
                ('endScope', ()),
                rawtext('</p>')])),
@@ -400,11 +400,11 @@
              {'tal:attributes': 'href string:http://www.zope.org; x string:y',
               'name': 'bar', 'href': 'foo'}),
             ('startTag', ('a',
-             [('href', 'foo', 0, '$string:http://www.zope.org$'),
+             [('href', 'foo', 'replace', '$string:http://www.zope.org$', 0),
               ('name', 'name="bar"'),
               ('tal:attributes',
-               'href string:http://www.zope.org; x string:y', 3),
-              ('x', None, 1, '$string:y$')])),
+               'href string:http://www.zope.org; x string:y', 'tal'),
+              ('x', None, 'insert', '$string:y$', 0)])),
             ('endScope', ()),
             rawtext('link</a>'),
             ])
@@ -416,12 +416,14 @@
             ('beginScope',
              {'tal:attributes': 'src string:foo.png',
               'tal:replace': 'structure string:<img>'}),
-            ('insertStructure', ('$string:<img>$',
-             {'src': '$string:foo.png$'},
-             [('startTag', ('p',
-               [('tal:replace', 'structure string:<img>', 3),
-                ('tal:attributes', 'src string:foo.png', 3)])),
-              rawtext('duh</p>')])),
+            ('insertStructure',
+             ('$string:<img>$',
+              {'src': ('$string:foo.png$', 0)},
+              [('startTag', ('p',
+                             [('tal:replace', 'structure string:<img>', 'tal'),
+                              ('tal:attributes', 'src string:foo.png',
+                               'tal')])),
+               rawtext('duh</p>')])),
             ('endScope', ()),
             ])
 
@@ -433,13 +435,13 @@
              {'tal:content': 'notHere', 'tal:on-error': 'string:error'}),
             ('onError',
              ([('startTag', ('p',
-                [('tal:on-error', 'string:error', 3),
-                 ('tal:content', 'notHere', 3)])),
+                [('tal:on-error', 'string:error', 'tal'),
+                 ('tal:content', 'notHere', 'tal')])),
                ('insertText', ('$notHere$', [rawtext('okay')])),
                rawtext('</p>')],
               [('startTag', ('p',
-                [('tal:on-error', 'string:error', 3),
-                 ('tal:content', 'notHere', 3)])),
+                [('tal:on-error', 'string:error', 'tal'),
+                 ('tal:content', 'notHere', 'tal')])),
                ('insertText', ('$string:error$', [])),
                rawtext('</p>')])),
             ('endScope', ()),
@@ -454,12 +456,12 @@
             ('onError',
              ([('insertText', ('$notHere$',
                 [('startTag', ('p',
-                  [('tal:on-error', 'string:error', 3),
-                   ('tal:replace', 'notHere', 3)])),
+                  [('tal:on-error', 'string:error', 'tal'),
+                   ('tal:replace', 'notHere', 'tal')])),
                  rawtext('okay</p>')]))],
               [('startTag', ('p',
-                [('tal:on-error', 'string:error', 3),
-                 ('tal:replace', 'notHere', 3)])),
+                [('tal:on-error', 'string:error', 'tal'),
+                 ('tal:replace', 'notHere', 'tal')])),
                ('insertText', ('$string:error$', [])),
                rawtext('</p>')])),
             ('endScope', ()),
@@ -484,7 +486,225 @@
                            2*"<p metal:fill-slot='y' />" + "</html>", exc)
         self._should_error("<p metal:foobar='x' />", exc)
         self._should_error("<p metal:define-macro='x'>", exc)
-        
+
+    #
+    #  I18N test cases
+    #
+
+    def check_i18n_attributes(self):
+        self._run_check("<img alt='foo' i18n:attributes='alt'>", [
+            ('setPosition', (1, 0)),
+            ('beginScope', {'alt': 'foo', 'i18n:attributes': 'alt'}),
+            ('startTag', ('img',
+             [('alt', 'foo', 'replace', None, 1),
+              ('i18n:attributes', 'alt', 'i18n')])),
+            ('endScope', ()),
+            ])
+
+    def check_i18n_translate(self):
+        self._run_check('''\
+<span i18n:translate="">Replace this</span>
+<span i18n:translate="msgid">This is a
+translated string</span>
+<span i18n:translate="">And another
+translated string</span>
+''', [
+  ('setPosition', (1, 0)),
+  ('beginScope', {'i18n:translate': ''}),
+  ('startTag', ('span', [('i18n:translate', '', 'i18n')])),
+  ('insertTranslation', ('', [('rawtextOffset', ('Replace this', 12))])),
+  ('rawtextBeginScope',
+   ('</span>\n', 0, (2, 0), 1, {'i18n:translate': 'msgid'})),
+  ('startTag', ('span', [('i18n:translate', 'msgid', 'i18n')])),
+  ('insertTranslation',
+   ('msgid', [('rawtextColumn', ('This is a\ntranslated string', 17))])),
+  ('rawtextBeginScope', ('</span>\n', 0, (4, 0), 1, {'i18n:translate': ''})),
+  ('startTag', ('span', [('i18n:translate', '', 'i18n')])),
+  ('insertTranslation',
+   ('', [('rawtextColumn', ('And another\ntranslated string', 17))])),
+  ('endScope', ()),
+  ('rawtextColumn', ('</span>\n', 0))])
+
+    def check_i18n_translate_with_nested_tal(self):
+        self._run_check('''\
+<span i18n:translate="">replaceable <p tal:replace="str:here">content</p></span>
+''', [
+  ('setPosition', (1, 0)),
+  ('beginScope', {'i18n:translate': ''}),
+  ('startTag', ('span', [('i18n:translate', '', 'i18n')])),
+  ('insertTranslation',
+   ('',
+    [('rawtextOffset', ('replaceable ', 12)),
+     ('setPosition', (1, 36)),
+     ('beginScope', {'tal:replace': 'str:here'}),
+     ('insertText',
+      ('$str:here$',
+       [('startTag', ('p', [('tal:replace', 'str:here', 'tal')])),
+        ('rawtextOffset', ('content</p>', 11))])),
+     ('endScope', ())])),
+  ('endScope', ()),
+  ('rawtextColumn', ('</span>\n', 0))
+  ])
+
+    def check_i18n_name(self):
+        self._run_check('''\
+<span i18n:translate="">
+  <span tal:replace="str:Lomax" i18n:name="name" /> was born in
+  <span tal:replace="str:Antarctica" i18n:name="country" />.
+</span>
+''', [
+  ('setPosition', (1, 0)),
+  ('beginScope', {'i18n:translate': ''}),
+  ('startTag', ('span', [('i18n:translate', '', 'i18n')])),
+  ('insertTranslation',
+   ('',
+    [('rawtextBeginScope',
+      ('\n  ',
+       2,
+       (2, 2),
+       0,
+       {'i18n:name': 'name', 'tal:replace': 'str:Lomax'})),
+     ('i18nVariable',
+      ('name',
+       '$str:Lomax$',
+       [('startEndTag',
+         ('span',
+          [('tal:replace', 'str:Lomax', 'tal'),
+           ('i18n:name', 'name', 'i18n')]))])),
+     ('rawtextBeginScope',
+      (' was born in\n  ',
+       2,
+       (3, 2),
+       1,
+       {'i18n:name': 'country', 'tal:replace': 'str:Antarctica'})),
+     ('i18nVariable',
+      ('country',
+       '$str:Antarctica$',
+       [('startEndTag',
+         ('span',
+          [('tal:replace', 'str:Antarctica', 'tal'),
+           ('i18n:name', 'country', 'i18n')]))])),
+     ('endScope', ()),
+     ('rawtextColumn', ('.\n', 0))])),
+  ('endScope', ()),
+  ('rawtextColumn', ('</span>\n', 0))
+  ])
+
+    def check_i18n_name_implicit_value(self):
+        self._run_check('''\
+<span i18n:translate="">
+  <span i18n:name="name"><b>Jim</b></span> was born in
+  <span i18n:name="country">the USA</span>.
+</span>
+''', [
+  ('setPosition', (1, 0)),
+  ('beginScope', {'i18n:translate': ''}),
+  ('startTag', ('span', [('i18n:translate', '', 'i18n')])),
+  ('insertTranslation',
+   ('',
+    [('rawtextBeginScope', ('\n  ', 2, (2, 2), 0, {'i18n:name': 'name'})),
+     ('i18nVariable',
+      ('name',
+       [('rawtextOffset', ('<b>Jim</b>', 10))],
+       [('startTag', ('span', [('i18n:name', 'name', 'i18n')])),
+        ('rawtextOffset', ('<b>Jim</b></span>', 17))])),
+     ('rawtextBeginScope',
+      (' was born in\n  ', 2, (3, 2), 1, {'i18n:name': 'country'})),
+     ('i18nVariable',
+      ('country',
+       [('rawtextOffset', ('the USA', 7))],
+       [('startTag', ('span', [('i18n:name', 'country', 'i18n')])),
+        ('rawtextOffset', ('the USA</span>', 14))])),
+     ('endScope', ()),
+     ('rawtextColumn', ('.\n', 0))])),
+  ('endScope', ()),
+  ('rawtextColumn', ('</span>\n', 0))
+  ])
+
+    def check_i18n_context_domain(self):
+        self._run_check("<span i18n:domain='mydomain'/>", [
+            ('setPosition', (1, 0)),
+            ('beginI18nContext', {'domain': 'mydomain'}),
+            ('beginScope', {'i18n:domain': 'mydomain'}),
+            ('startEndTag', ('span', [('i18n:domain', 'mydomain', 'i18n')])),
+            ('endScope', ()),
+            ('endI18nContext', ()),
+            ])
+
+    def check_i18n_context_source(self):
+        self._run_check("<span i18n:source='en'/>", [
+            ('setPosition', (1, 0)),
+            ('beginI18nContext', {'source': 'en'}),
+            ('beginScope', {'i18n:source': 'en'}),
+            ('startEndTag', ('span', [('i18n:source', 'en', 'i18n')])),
+            ('endScope', ()),
+            ('endI18nContext', ()),
+            ])
+
+    def check_i18n_context_source_target(self):
+        self._run_check("<span i18n:source='en' i18n:target='ru'/>", [
+            ('setPosition', (1, 0)),
+            ('beginI18nContext', {'source': 'en', 'target': 'ru'}),
+            ('beginScope', {'i18n:source': 'en', 'i18n:target': 'ru'}),
+            ('startEndTag', ('span', [('i18n:source', 'en', 'i18n'),
+                                      ('i18n:target', 'ru', 'i18n')])),
+            ('endScope', ()),
+            ('endI18nContext', ()),
+            ])
+
+    def check_i18n_data(self):
+        self._run_check('''\
+<span i18n:data="here/currentTime"
+      i18n:translate="timefmt">2:32 pm</span>
+''', [
+  ('setPosition', (1, 0)),
+  ('beginScope',
+   {'i18n:translate': 'timefmt', 'i18n:data': 'here/currentTime'}),
+  ('startTag',
+   ('span',
+    [('i18n:data', 'here/currentTime', 'i18n'),
+     ('i18n:translate', 'timefmt', 'i18n')])),
+  ('insertTranslation',
+   ('timefmt', [('rawtextOffset', ('2:32 pm', 7))], '$here/currentTime$')),
+  ('endScope', ()),
+  ('rawtextColumn', ('</span>\n', 0))
+  ])
+
+    def check_i18n_data_with_name(self):
+        self._run_check('''\
+At the tone the time will be
+<span i18n:data="here/currentTime"
+      i18n:translate="timefmt"
+      i18n:name="time">2:32 pm</span>... beep!
+''', [
+  ('rawtextBeginScope',
+   ('At the tone the time will be\n',
+    0,
+    (2, 0),
+    0,
+    {'i18n:data': 'here/currentTime',
+     'i18n:name': 'time',
+     'i18n:translate': 'timefmt'})),
+  ('i18nVariable',
+   ('time',
+    [('insertTranslation',
+      ('timefmt',
+       [('rawtextOffset', ('2:32 pm', 7))],
+       '$here/currentTime$'))],
+    [('startTag',
+      ('span',
+       [('i18n:data', 'here/currentTime', 'i18n'),
+        ('i18n:translate', 'timefmt', 'i18n'),
+        ('i18n:name', 'time', 'i18n')])),
+     ('insertTranslation',
+      ('timefmt',
+       [('rawtextOffset', ('2:32 pm', 7))],
+       '$here/currentTime$')),
+     ('rawtextOffset', ('</span>', 7))])),
+  ('endScope', ()),
+  ('rawtextColumn', ('... beep!\n', 0))
+  ])
+
 
 def test_suite():
     suite = unittest.TestSuite()


=== Zope3/lib/python/Zope/TAL/tests/test_talinterpreter.py 1.4 => 1.5 ===
 from StringIO import StringIO
 
-from Zope.TAL.TALDefs import METALError
+from Zope.TAL.TALDefs import METALError, I18NError
 from Zope.TAL.HTMLTALParser import HTMLTALParser
 from Zope.TAL.TALInterpreter import TALInterpreter
 from Zope.TAL.DummyEngine import DummyEngine
@@ -60,6 +60,29 @@
         self.macro[0] = ("version", "duh")
 
 
+class I18NErrorsTestCase(TestCaseBase):
+
+    def _check(self, src, msg):
+        try:
+            self._compile(src)
+        except I18NError:
+            pass
+        else:
+            self.fail(msg)
+
+    def check_id_with_replace(self):
+        self._check('<p i18n:id="foo" tal:replace="string:splat"></p>',
+                    "expected i18n:id with tal:replace to be denied")
+
+    def check_missing_values(self):
+        self._check('<p i18n:attributes=""></p>',
+                    "missing i18n:attributes value not caught")
+        self._check('<p i18n:data=""></p>',
+                    "missing i18n:data value not caught")
+        self._check('<p i18n:id=""></p>',
+                    "missing i18n:id value not caught")
+
+
 class OutputPresentationTestCase(TestCaseBase):
 
     def check_attribute_wrapping(self):
@@ -84,6 +107,7 @@
 
 def test_suite():
     suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(I18NErrorsTestCase, "check_"))
     suite.addTest(unittest.makeSuite(MacroErrorsTestCase, "check_"))
     suite.addTest(unittest.makeSuite(OutputPresentationTestCase, "check_"))
     return suite