Mercurial > p > roundup > code
annotate roundup/cgi/TAL/TALGenerator.py @ 5814:bd6d41f21a5a
More extensive EditCSV testing.
Uses test object to cover all types defined by database.
Also check for an error with a row that's too short.
CSV starts with blank line to verify that it recognises header line.
Changes password, date, int, link and other fields.
Deletes row and verified that it is retired.
Make actions.py properly handle emptying of password field.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Fri, 14 Jun 2019 21:26:19 -0400 |
| parents | 936275dfe1fa |
| children | 883c9e90b403 |
| rev | line source |
|---|---|
| 1049 | 1 ############################################################################## |
| 2 # | |
| 3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors. | |
| 4 # All Rights Reserved. | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
5 # |
| 1049 | 6 # This software is subject to the provisions of the Zope Public License, |
| 7 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |
| 8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |
| 9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
11 # FOR A PARTICULAR PURPOSE. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
12 # |
| 1049 | 13 ############################################################################## |
| 14 """ | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
15 Code generator for TALInterpreter intermediate code. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
16 """ |
| 1049 | 17 |
| 18 import re | |
| 19 import cgi | |
| 20 | |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5382
diff
changeset
|
21 from . import TALDefs |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
22 |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5382
diff
changeset
|
23 from .TALDefs import NAME_RE, TAL_VERSION |
|
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5382
diff
changeset
|
24 from .TALDefs import I18NError, METALError, TALError |
|
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5382
diff
changeset
|
25 from .TALDefs import parseSubstitution |
|
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5382
diff
changeset
|
26 from .TranslationContext import TranslationContext, DEFAULT_DOMAIN |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
27 |
|
5800
1a835db41674
Call cgi.escape only on python 2. Replace with html.escapeif it can be
John Rouillard <rouilj@ieee.org>
parents:
5391
diff
changeset
|
28 try: |
|
1a835db41674
Call cgi.escape only on python 2. Replace with html.escapeif it can be
John Rouillard <rouilj@ieee.org>
parents:
5391
diff
changeset
|
29 from html import escape as html_escape # python 3 |
|
1a835db41674
Call cgi.escape only on python 2. Replace with html.escapeif it can be
John Rouillard <rouilj@ieee.org>
parents:
5391
diff
changeset
|
30 except ImportError: |
|
1a835db41674
Call cgi.escape only on python 2. Replace with html.escapeif it can be
John Rouillard <rouilj@ieee.org>
parents:
5391
diff
changeset
|
31 from cgi import escape as html_escape # python 2 fallback |
|
1a835db41674
Call cgi.escape only on python 2. Replace with html.escapeif it can be
John Rouillard <rouilj@ieee.org>
parents:
5391
diff
changeset
|
32 |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
33 I18N_REPLACE = 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
34 I18N_CONTENT = 2 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
35 I18N_EXPRESSION = 3 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
36 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
37 _name_rx = re.compile(NAME_RE) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
38 |
| 1049 | 39 |
| 40 class TALGenerator: | |
| 41 | |
| 42 inMacroUse = 0 | |
| 43 inMacroDef = 0 | |
| 44 source_file = None | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
45 |
| 1049 | 46 def __init__(self, expressionCompiler=None, xml=1, source_file=None): |
| 47 if not expressionCompiler: | |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5382
diff
changeset
|
48 from .DummyEngine import DummyEngine |
| 1049 | 49 expressionCompiler = DummyEngine() |
| 50 self.expressionCompiler = expressionCompiler | |
| 51 self.CompilerError = expressionCompiler.getCompilerError() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
52 # This holds the emitted opcodes representing the input |
| 1049 | 53 self.program = [] |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
54 # The program stack for when we need to do some sub-evaluation for an |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
55 # intermediate result. E.g. in an i18n:name tag for which the |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
56 # contents describe the ${name} value. |
| 1049 | 57 self.stack = [] |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
58 # Another stack of postponed actions. Elements on this stack are a |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
59 # dictionary; key/values contain useful information that |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
60 # emitEndElement needs to finish its calculations |
| 1049 | 61 self.todoStack = [] |
| 62 self.macros = {} | |
| 63 self.slots = {} | |
| 64 self.slotStack = [] | |
| 65 self.xml = xml | |
| 66 self.emit("version", TAL_VERSION) | |
| 67 self.emit("mode", xml and "xml" or "html") | |
| 68 if source_file is not None: | |
| 69 self.source_file = source_file | |
| 70 self.emit("setSourceFile", source_file) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
71 self.i18nContext = TranslationContext() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
72 self.i18nLevel = 0 |
| 1049 | 73 |
| 74 def getCode(self): | |
| 75 assert not self.stack | |
| 76 assert not self.todoStack | |
| 77 return self.optimize(self.program), self.macros | |
| 78 | |
| 79 def optimize(self, program): | |
| 80 output = [] | |
| 81 collect = [] | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
82 cursor = 0 |
| 1049 | 83 if self.xml: |
| 84 endsep = "/>" | |
| 85 else: | |
| 86 endsep = " />" | |
|
5391
a391a071d045
Python 3 preparation: use range() instead of xrange().
Joseph Myers <jsm@polyomino.org.uk>
parents:
5388
diff
changeset
|
87 for cursor in range(len(program)+1): |
| 1049 | 88 try: |
| 89 item = program[cursor] | |
| 90 except IndexError: | |
| 91 item = (None, None) | |
| 92 opcode = item[0] | |
| 93 if opcode == "rawtext": | |
| 94 collect.append(item[1]) | |
| 95 continue | |
| 96 if opcode == "endTag": | |
| 97 collect.append("</%s>" % item[1]) | |
| 98 continue | |
| 99 if opcode == "startTag": | |
| 100 if self.optimizeStartTag(collect, item[1], item[2], ">"): | |
| 101 continue | |
| 102 if opcode == "startEndTag": | |
| 103 if self.optimizeStartTag(collect, item[1], item[2], endsep): | |
| 104 continue | |
| 105 if opcode in ("beginScope", "endScope"): | |
| 106 # Push *Scope instructions in front of any text instructions; | |
| 107 # this allows text instructions separated only by *Scope | |
| 108 # instructions to be joined together. | |
| 109 output.append(self.optimizeArgsList(item)) | |
| 110 continue | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
111 if opcode == 'noop': |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
112 # This is a spacer for end tags in the face of i18n:name |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
113 # attributes. We can't let the optimizer collect immediately |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
114 # following end tags into the same rawtextOffset. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
115 opcode = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
116 pass |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
117 text = "".join(collect) |
| 1049 | 118 if text: |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
119 i = text.rfind("\n") |
| 1049 | 120 if i >= 0: |
| 121 i = len(text) - (i + 1) | |
| 122 output.append(("rawtextColumn", (text, i))) | |
| 123 else: | |
| 124 output.append(("rawtextOffset", (text, len(text)))) | |
| 125 if opcode != None: | |
| 126 output.append(self.optimizeArgsList(item)) | |
| 127 collect = [] | |
| 128 return self.optimizeCommonTriple(output) | |
| 129 | |
| 130 def optimizeArgsList(self, item): | |
| 131 if len(item) == 2: | |
| 132 return item | |
| 133 else: | |
| 134 return item[0], tuple(item[1:]) | |
| 135 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
136 # These codes are used to indicate what sort of special actions |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
137 # are needed for each special attribute. (Simple attributes don't |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
138 # get action codes.) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
139 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
140 # The special actions (which are modal) are handled by |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
141 # TALInterpreter.attrAction() and .attrAction_tal(). |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
142 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
143 # Each attribute is represented by a tuple: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
144 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
145 # (name, value) -- a simple name/value pair, with |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
146 # no special processing |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
147 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
148 # (name, value, action, *extra) -- attribute with special |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
149 # processing needs, action is a |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
150 # code that indicates which |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
151 # branch to take, and *extra |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
152 # contains additional, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
153 # action-specific information |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
154 # needed by the processing |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
155 # |
| 1049 | 156 def optimizeStartTag(self, collect, name, attrlist, end): |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
157 # return true if the tag can be converted to plain text |
| 1049 | 158 if not attrlist: |
| 159 collect.append("<%s%s" % (name, end)) | |
| 160 return 1 | |
| 161 opt = 1 | |
| 162 new = ["<" + name] | |
| 163 for i in range(len(attrlist)): | |
| 164 item = attrlist[i] | |
| 165 if len(item) > 2: | |
| 166 opt = 0 | |
| 167 name, value, action = item[:3] | |
| 168 attrlist[i] = (name, value, action) + item[3:] | |
| 169 else: | |
| 170 if item[1] is None: | |
| 171 s = item[0] | |
| 172 else: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
173 s = '%s="%s"' % (item[0], TALDefs.attrEscape(item[1])) |
| 1049 | 174 attrlist[i] = item[0], s |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
175 new.append(" " + s) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
176 # if no non-optimizable attributes were found, convert to plain text |
| 1049 | 177 if opt: |
| 178 new.append(end) | |
| 179 collect.extend(new) | |
| 180 return opt | |
| 181 | |
| 182 def optimizeCommonTriple(self, program): | |
| 183 if len(program) < 3: | |
| 184 return program | |
| 185 output = program[:2] | |
| 186 prev2, prev1 = output | |
| 187 for item in program[2:]: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
188 if ( item[0] == "beginScope" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
189 and prev1[0] == "setPosition" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
190 and prev2[0] == "rawtextColumn"): |
| 1049 | 191 position = output.pop()[1] |
| 192 text, column = output.pop()[1] | |
| 193 prev1 = None, None | |
| 194 closeprev = 0 | |
| 195 if output and output[-1][0] == "endScope": | |
| 196 closeprev = 1 | |
| 197 output.pop() | |
| 198 item = ("rawtextBeginScope", | |
| 199 (text, column, position, closeprev, item[1])) | |
| 200 output.append(item) | |
| 201 prev2 = prev1 | |
| 202 prev1 = item | |
| 203 return output | |
| 204 | |
| 205 def todoPush(self, todo): | |
| 206 self.todoStack.append(todo) | |
| 207 | |
| 208 def todoPop(self): | |
| 209 return self.todoStack.pop() | |
| 210 | |
| 211 def compileExpression(self, expr): | |
| 212 try: | |
| 213 return self.expressionCompiler.compile(expr) | |
|
5248
198b6e810c67
Use Python-3-compatible 'as' syntax for except statements
Eric S. Raymond <esr@thyrsus.com>
parents:
2348
diff
changeset
|
214 except self.CompilerError as err: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
215 raise TALError('%s in expression %s' % (err.args[0], repr(expr)), |
| 1049 | 216 self.position) |
| 217 | |
| 218 def pushProgram(self): | |
| 219 self.stack.append(self.program) | |
| 220 self.program = [] | |
| 221 | |
| 222 def popProgram(self): | |
| 223 program = self.program | |
| 224 self.program = self.stack.pop() | |
| 225 return self.optimize(program) | |
| 226 | |
| 227 def pushSlots(self): | |
| 228 self.slotStack.append(self.slots) | |
| 229 self.slots = {} | |
| 230 | |
| 231 def popSlots(self): | |
| 232 slots = self.slots | |
| 233 self.slots = self.slotStack.pop() | |
| 234 return slots | |
| 235 | |
| 236 def emit(self, *instruction): | |
| 237 self.program.append(instruction) | |
| 238 | |
| 239 def emitStartTag(self, name, attrlist, isend=0): | |
| 240 if isend: | |
| 241 opcode = "startEndTag" | |
| 242 else: | |
| 243 opcode = "startTag" | |
| 244 self.emit(opcode, name, attrlist) | |
| 245 | |
| 246 def emitEndTag(self, name): | |
| 247 if self.xml and self.program and self.program[-1][0] == "startTag": | |
| 248 # Minimize empty element | |
| 249 self.program[-1] = ("startEndTag",) + self.program[-1][1:] | |
| 250 else: | |
| 251 self.emit("endTag", name) | |
| 252 | |
| 253 def emitOptTag(self, name, optTag, isend): | |
| 254 program = self.popProgram() #block | |
| 255 start = self.popProgram() #start tag | |
| 256 if (isend or not program) and self.xml: | |
| 257 # Minimize empty element | |
| 258 start[-1] = ("startEndTag",) + start[-1][1:] | |
| 259 isend = 1 | |
| 260 cexpr = optTag[0] | |
| 261 if cexpr: | |
| 262 cexpr = self.compileExpression(optTag[0]) | |
| 263 self.emit("optTag", name, cexpr, optTag[1], isend, start, program) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
264 |
| 1049 | 265 def emitRawText(self, text): |
| 266 self.emit("rawtext", text) | |
| 267 | |
| 268 def emitText(self, text): | |
|
5800
1a835db41674
Call cgi.escape only on python 2. Replace with html.escapeif it can be
John Rouillard <rouilj@ieee.org>
parents:
5391
diff
changeset
|
269 self.emitRawText(html_escape(text)) |
| 1049 | 270 |
| 271 def emitDefines(self, defines): | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
272 for part in TALDefs.splitParts(defines): |
| 1049 | 273 m = re.match( |
| 274 r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part) | |
| 275 if not m: | |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
276 raise TALError("invalid define syntax: " + repr(part), |
| 1049 | 277 self.position) |
| 278 scope, name, expr = m.group(1, 2, 3) | |
| 279 scope = scope or "local" | |
| 280 cexpr = self.compileExpression(expr) | |
| 281 if scope == "local": | |
| 282 self.emit("setLocal", name, cexpr) | |
| 283 else: | |
| 284 self.emit("setGlobal", name, cexpr) | |
| 285 | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
286 def emitOnError(self, name, onError, TALtag, isend): |
| 1049 | 287 block = self.popProgram() |
| 288 key, expr = parseSubstitution(onError) | |
| 289 cexpr = self.compileExpression(expr) | |
| 290 if key == "text": | |
| 291 self.emit("insertText", cexpr, []) | |
| 292 else: | |
| 293 assert key == "structure" | |
| 294 self.emit("insertStructure", cexpr, {}, []) | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
295 if TALtag: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
296 self.emitOptTag(name, (None, 1), isend) |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
297 else: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
298 self.emitEndTag(name) |
| 1049 | 299 handler = self.popProgram() |
| 300 self.emit("onError", block, handler) | |
| 301 | |
| 302 def emitCondition(self, expr): | |
| 303 cexpr = self.compileExpression(expr) | |
| 304 program = self.popProgram() | |
| 305 self.emit("condition", cexpr, program) | |
| 306 | |
| 307 def emitRepeat(self, arg): | |
| 5809 | 308 m = re.match(r"(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg) |
| 1049 | 309 if not m: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
310 raise TALError("invalid repeat syntax: " + repr(arg), |
| 1049 | 311 self.position) |
| 312 name, expr = m.group(1, 2) | |
| 313 cexpr = self.compileExpression(expr) | |
| 314 program = self.popProgram() | |
| 315 self.emit("loop", name, cexpr, program) | |
| 316 | |
| 317 def emitSubstitution(self, arg, attrDict={}): | |
| 318 key, expr = parseSubstitution(arg) | |
| 319 cexpr = self.compileExpression(expr) | |
| 320 program = self.popProgram() | |
| 321 if key == "text": | |
| 322 self.emit("insertText", cexpr, program) | |
| 323 else: | |
| 324 assert key == "structure" | |
| 325 self.emit("insertStructure", cexpr, attrDict, program) | |
| 326 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
327 def emitI18nVariable(self, stuff): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
328 # Used for i18n:name attributes. arg is extra information describing |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
329 # how the contents of the variable should get filled in, and it will |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
330 # either be a 1-tuple or a 2-tuple. If arg[0] is None, then the |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
331 # i18n:name value is taken implicitly from the contents of the tag, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
332 # e.g. "I live in <span i18n:name="country">the USA</span>". In this |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
333 # case, arg[1] is the opcode sub-program describing the contents of |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
334 # the tag. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
335 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
336 # When arg[0] is not None, it contains the tal expression used to |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
337 # calculate the contents of the variable, e.g. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
338 # "I live in <span i18n:name="country" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
339 # tal:replace="here/countryOfOrigin" />" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
340 varname, action, expression = stuff |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
341 m = _name_rx.match(varname) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
342 if m is None or m.group() != varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
343 raise TALError("illegal i18n:name: %r" % varname, self.position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
344 key = cexpr = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
345 program = self.popProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
346 if action == I18N_REPLACE: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
347 # This is a tag with an i18n:name and a tal:replace (implicit or |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
348 # explicit). Get rid of the first and last elements of the |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
349 # program, which are the start and end tag opcodes of the tag. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
350 program = program[1:-1] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
351 elif action == I18N_CONTENT: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
352 # This is a tag with an i18n:name and a tal:content |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
353 # (explicit-only). Keep the first and last elements of the |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
354 # program, so we keep the start and end tag output. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
355 pass |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
356 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
357 assert action == I18N_EXPRESSION |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
358 key, expr = parseSubstitution(expression) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
359 cexpr = self.compileExpression(expr) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
360 # XXX Would key be anything but 'text' or None? |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
361 assert key in ('text', None) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
362 self.emit('i18nVariable', varname, program, cexpr) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
363 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
364 def emitTranslation(self, msgid, i18ndata): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
365 program = self.popProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
366 if i18ndata is None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
367 self.emit('insertTranslation', msgid, program) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
368 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
369 key, expr = parseSubstitution(i18ndata) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
370 cexpr = self.compileExpression(expr) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
371 assert key == 'text' |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
372 self.emit('insertTranslation', msgid, program, cexpr) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
373 |
| 1049 | 374 def emitDefineMacro(self, macroName): |
| 375 program = self.popProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
376 macroName = macroName.strip() |
|
5381
0942fe89e82e
Python 3 preparation: change "x.has_key(y)" to "y in x".
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
377 if macroName in self.macros: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
378 raise METALError("duplicate macro definition: %s" % repr(macroName), |
| 1049 | 379 self.position) |
| 380 if not re.match('%s$' % NAME_RE, macroName): | |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
381 raise METALError("invalid macro name: %s" % repr(macroName), |
| 1049 | 382 self.position) |
| 383 self.macros[macroName] = program | |
| 384 self.inMacroDef = self.inMacroDef - 1 | |
| 385 self.emit("defineMacro", macroName, program) | |
| 386 | |
| 387 def emitUseMacro(self, expr): | |
| 388 cexpr = self.compileExpression(expr) | |
| 389 program = self.popProgram() | |
| 390 self.inMacroUse = 0 | |
| 391 self.emit("useMacro", expr, cexpr, self.popSlots(), program) | |
| 392 | |
| 393 def emitDefineSlot(self, slotName): | |
| 394 program = self.popProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
395 slotName = slotName.strip() |
| 1049 | 396 if not re.match('%s$' % NAME_RE, slotName): |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
397 raise METALError("invalid slot name: %s" % repr(slotName), |
| 1049 | 398 self.position) |
| 399 self.emit("defineSlot", slotName, program) | |
| 400 | |
| 401 def emitFillSlot(self, slotName): | |
| 402 program = self.popProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
403 slotName = slotName.strip() |
|
5381
0942fe89e82e
Python 3 preparation: change "x.has_key(y)" to "y in x".
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
404 if slotName in self.slots: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
405 raise METALError("duplicate fill-slot name: %s" % repr(slotName), |
| 1049 | 406 self.position) |
| 407 if not re.match('%s$' % NAME_RE, slotName): | |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
408 raise METALError("invalid slot name: %s" % repr(slotName), |
| 1049 | 409 self.position) |
| 410 self.slots[slotName] = program | |
| 411 self.inMacroUse = 1 | |
| 412 self.emit("fillSlot", slotName, program) | |
| 413 | |
| 414 def unEmitWhitespace(self): | |
| 415 collect = [] | |
| 416 i = len(self.program) - 1 | |
| 417 while i >= 0: | |
| 418 item = self.program[i] | |
| 419 if item[0] != "rawtext": | |
| 420 break | |
| 421 text = item[1] | |
| 422 if not re.match(r"\A\s*\Z", text): | |
| 423 break | |
| 424 collect.append(text) | |
| 425 i = i-1 | |
| 426 del self.program[i+1:] | |
| 427 if i >= 0 and self.program[i][0] == "rawtext": | |
| 428 text = self.program[i][1] | |
| 429 m = re.search(r"\s+\Z", text) | |
| 430 if m: | |
| 431 self.program[i] = ("rawtext", text[:m.start()]) | |
| 432 collect.append(m.group()) | |
| 433 collect.reverse() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
434 return "".join(collect) |
| 1049 | 435 |
| 436 def unEmitNewlineWhitespace(self): | |
| 437 collect = [] | |
| 438 i = len(self.program) | |
| 439 while i > 0: | |
| 440 i = i-1 | |
| 441 item = self.program[i] | |
| 442 if item[0] != "rawtext": | |
| 443 break | |
| 444 text = item[1] | |
| 445 if re.match(r"\A[ \t]*\Z", text): | |
| 446 collect.append(text) | |
| 447 continue | |
| 448 m = re.match(r"(?s)^(.*)(\n[ \t]*)\Z", text) | |
| 449 if not m: | |
| 450 break | |
| 451 text, rest = m.group(1, 2) | |
| 452 collect.reverse() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
453 rest = rest + "".join(collect) |
| 1049 | 454 del self.program[i:] |
| 455 if text: | |
| 456 self.emit("rawtext", text) | |
| 457 return rest | |
| 458 return None | |
| 459 | |
| 460 def replaceAttrs(self, attrlist, repldict): | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
461 # Each entry in attrlist starts like (name, value). |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
462 # Result is (name, value, action, expr, xlat) if there is a |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
463 # tal:attributes entry for that attribute. Additional attrs |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
464 # defined only by tal:attributes are added here. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
465 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
466 # (name, value, action, expr, xlat) |
| 1049 | 467 if not repldict: |
| 468 return attrlist | |
| 469 newlist = [] | |
| 470 for item in attrlist: | |
| 471 key = item[0] | |
|
5381
0942fe89e82e
Python 3 preparation: change "x.has_key(y)" to "y in x".
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
472 if key in repldict: |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
473 expr, xlat, msgid = repldict[key] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
474 item = item[:2] + ("replace", expr, xlat, msgid) |
| 1049 | 475 del repldict[key] |
| 476 newlist.append(item) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
477 # Add dynamic-only attributes |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
478 for key, (expr, xlat, msgid) in repldict.items(): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
479 newlist.append((key, None, "insert", expr, xlat, msgid)) |
| 1049 | 480 return newlist |
| 481 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
482 def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict, |
| 1049 | 483 position=(None, None), isend=0): |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
484 if not taldict and not metaldict and not i18ndict: |
| 1049 | 485 # Handle the simple, common case |
| 486 self.emitStartTag(name, attrlist, isend) | |
| 487 self.todoPush({}) | |
| 488 if isend: | |
| 489 self.emitEndElement(name, isend) | |
| 490 return | |
| 491 | |
| 492 self.position = position | |
| 493 for key, value in taldict.items(): | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
494 if key not in TALDefs.KNOWN_TAL_ATTRIBUTES: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
495 raise TALError("bad TAL attribute: " + repr(key), position) |
| 1049 | 496 if not (value or key == 'omit-tag'): |
| 497 raise TALError("missing value for TAL attribute: " + | |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
498 repr(key), position) |
| 1049 | 499 for key, value in metaldict.items(): |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
500 if key not in TALDefs.KNOWN_METAL_ATTRIBUTES: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
501 raise METALError("bad METAL attribute: " + repr(key), |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
502 position) |
| 1049 | 503 if not value: |
| 504 raise TALError("missing value for METAL attribute: " + | |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
505 repr(key), position) |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
506 for key, value in i18ndict.items(): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
507 if key not in TALDefs.KNOWN_I18N_ATTRIBUTES: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
508 raise I18NError("bad i18n attribute: " + repr(key), position) |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
509 if not value and key in ("attributes", "data", "id"): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
510 raise I18NError("missing value for i18n attribute: " + |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
511 repr(key), position) |
| 1049 | 512 todo = {} |
| 513 defineMacro = metaldict.get("define-macro") | |
| 514 useMacro = metaldict.get("use-macro") | |
| 515 defineSlot = metaldict.get("define-slot") | |
| 516 fillSlot = metaldict.get("fill-slot") | |
| 517 define = taldict.get("define") | |
| 518 condition = taldict.get("condition") | |
| 519 repeat = taldict.get("repeat") | |
| 520 content = taldict.get("content") | |
| 521 replace = taldict.get("replace") | |
| 522 attrsubst = taldict.get("attributes") | |
| 523 onError = taldict.get("on-error") | |
| 524 omitTag = taldict.get("omit-tag") | |
| 525 TALtag = taldict.get("tal tag") | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
526 i18nattrs = i18ndict.get("attributes") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
527 # Preserve empty string if implicit msgids are used. We'll generate |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
528 # code with the msgid='' and calculate the right implicit msgid during |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
529 # interpretation phase. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
530 msgid = i18ndict.get("translate") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
531 varname = i18ndict.get('name') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
532 i18ndata = i18ndict.get('data') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
533 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
534 if varname and not self.i18nLevel: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
535 raise I18NError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
536 "i18n:name can only occur inside a translation unit", |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
537 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
538 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
539 if i18ndata and not msgid: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
540 raise I18NError("i18n:data must be accompanied by i18n:translate", |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
541 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
542 |
| 1049 | 543 if len(metaldict) > 1 and (defineMacro or useMacro): |
| 544 raise METALError("define-macro and use-macro cannot be used " | |
| 545 "together or with define-slot or fill-slot", | |
| 546 position) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
547 if replace: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
548 if content: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
549 raise TALError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
550 "tal:content and tal:replace are mutually exclusive", |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
551 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
552 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
553 raise I18NError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
554 "i18n:translate and tal:replace are mutually exclusive", |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
555 position) |
| 1049 | 556 |
| 557 repeatWhitespace = None | |
| 558 if repeat: | |
| 559 # Hack to include preceding whitespace in the loop program | |
| 560 repeatWhitespace = self.unEmitNewlineWhitespace() | |
| 561 if position != (None, None): | |
| 562 # XXX at some point we should insist on a non-trivial position | |
| 563 self.emit("setPosition", position) | |
| 564 if self.inMacroUse: | |
| 565 if fillSlot: | |
| 566 self.pushProgram() | |
| 567 if self.source_file is not None: | |
| 568 self.emit("setSourceFile", self.source_file) | |
| 569 todo["fillSlot"] = fillSlot | |
| 570 self.inMacroUse = 0 | |
| 571 else: | |
| 572 if fillSlot: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
573 raise METALError("fill-slot must be within a use-macro", |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
574 position) |
| 1049 | 575 if not self.inMacroUse: |
| 576 if defineMacro: | |
| 577 self.pushProgram() | |
| 578 self.emit("version", TAL_VERSION) | |
| 579 self.emit("mode", self.xml and "xml" or "html") | |
| 580 if self.source_file is not None: | |
| 581 self.emit("setSourceFile", self.source_file) | |
| 582 todo["defineMacro"] = defineMacro | |
| 583 self.inMacroDef = self.inMacroDef + 1 | |
| 584 if useMacro: | |
| 585 self.pushSlots() | |
| 586 self.pushProgram() | |
| 587 todo["useMacro"] = useMacro | |
| 588 self.inMacroUse = 1 | |
| 589 if defineSlot: | |
| 590 if not self.inMacroDef: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
591 raise METALError( |
| 1049 | 592 "define-slot must be within a define-macro", |
| 593 position) | |
| 594 self.pushProgram() | |
| 595 todo["defineSlot"] = defineSlot | |
| 596 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
597 if defineSlot or i18ndict: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
598 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
599 domain = i18ndict.get("domain") or self.i18nContext.domain |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
600 source = i18ndict.get("source") or self.i18nContext.source |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
601 target = i18ndict.get("target") or self.i18nContext.target |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
602 if ( domain != DEFAULT_DOMAIN |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
603 or source is not None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
604 or target is not None): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
605 self.i18nContext = TranslationContext(self.i18nContext, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
606 domain=domain, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
607 source=source, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
608 target=target) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
609 self.emit("beginI18nContext", |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
610 {"domain": domain, "source": source, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
611 "target": target}) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
612 todo["i18ncontext"] = 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
613 if taldict or i18ndict: |
| 1049 | 614 dict = {} |
| 615 for item in attrlist: | |
| 616 key, value = item[:2] | |
| 617 dict[key] = value | |
| 618 self.emit("beginScope", dict) | |
| 619 todo["scope"] = 1 | |
| 620 if onError: | |
| 621 self.pushProgram() # handler | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
622 if TALtag: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
623 self.pushProgram() # start |
| 1049 | 624 self.emitStartTag(name, list(attrlist)) # Must copy attrlist! |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
625 if TALtag: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
626 self.pushProgram() # start |
| 1049 | 627 self.pushProgram() # block |
| 628 todo["onError"] = onError | |
| 629 if define: | |
| 630 self.emitDefines(define) | |
| 631 todo["define"] = define | |
| 632 if condition: | |
| 633 self.pushProgram() | |
| 634 todo["condition"] = condition | |
| 635 if repeat: | |
| 636 todo["repeat"] = repeat | |
| 637 self.pushProgram() | |
| 638 if repeatWhitespace: | |
| 639 self.emitText(repeatWhitespace) | |
| 640 if content: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
641 if varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
642 todo['i18nvar'] = (varname, I18N_CONTENT, None) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
643 todo["content"] = content |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
644 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
645 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
646 todo["content"] = content |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
647 elif replace: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
648 # tal:replace w/ i18n:name has slightly different semantics. What |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
649 # we're actually replacing then is the contents of the ${name} |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
650 # placeholder. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
651 if varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
652 todo['i18nvar'] = (varname, I18N_EXPRESSION, replace) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
653 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
654 todo["replace"] = replace |
| 1049 | 655 self.pushProgram() |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
656 # i18n:name w/o tal:replace uses the content as the interpolation |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
657 # dictionary values |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
658 elif varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
659 todo['i18nvar'] = (varname, I18N_REPLACE, None) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
660 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
661 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
662 self.i18nLevel += 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
663 todo['msgid'] = msgid |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
664 if i18ndata: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
665 todo['i18ndata'] = i18ndata |
| 1049 | 666 optTag = omitTag is not None or TALtag |
| 667 if optTag: | |
| 668 todo["optional tag"] = omitTag, TALtag | |
| 669 self.pushProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
670 if attrsubst or i18nattrs: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
671 if attrsubst: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
672 repldict = TALDefs.parseAttributeReplacements(attrsubst, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
673 self.xml) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
674 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
675 repldict = {} |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
676 if i18nattrs: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
677 i18nattrs = _parseI18nAttributes(i18nattrs, attrlist, repldict, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
678 self.position, self.xml, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
679 self.source_file) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
680 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
681 i18nattrs = {} |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
682 # Convert repldict's name-->expr mapping to a |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
683 # name-->(compiled_expr, translate) mapping |
| 1049 | 684 for key, value in repldict.items(): |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
685 if i18nattrs.get(key, None): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
686 raise I18NError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
687 ("attribute [%s] cannot both be part of tal:attributes" + |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
688 " and have a msgid in i18n:attributes") % key, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
689 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
690 ce = self.compileExpression(value) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
691 repldict[key] = ce, key in i18nattrs, i18nattrs.get(key) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
692 for key in i18nattrs: |
|
5381
0942fe89e82e
Python 3 preparation: change "x.has_key(y)" to "y in x".
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
693 if key not in repldict: |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
694 repldict[key] = None, 1, i18nattrs.get(key) |
| 1049 | 695 else: |
| 696 repldict = {} | |
| 697 if replace: | |
| 698 todo["repldict"] = repldict | |
| 699 repldict = {} | |
| 700 self.emitStartTag(name, self.replaceAttrs(attrlist, repldict), isend) | |
| 701 if optTag: | |
| 702 self.pushProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
703 if content and not varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
704 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
705 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
706 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
707 if content and varname: |
| 1049 | 708 self.pushProgram() |
| 709 if todo and position != (None, None): | |
| 710 todo["position"] = position | |
| 711 self.todoPush(todo) | |
| 712 if isend: | |
| 713 self.emitEndElement(name, isend) | |
| 714 | |
| 715 def emitEndElement(self, name, isend=0, implied=0): | |
| 716 todo = self.todoPop() | |
| 717 if not todo: | |
| 718 # Shortcut | |
| 719 if not isend: | |
| 720 self.emitEndTag(name) | |
| 721 return | |
| 722 | |
| 723 self.position = position = todo.get("position", (None, None)) | |
| 724 defineMacro = todo.get("defineMacro") | |
| 725 useMacro = todo.get("useMacro") | |
| 726 defineSlot = todo.get("defineSlot") | |
| 727 fillSlot = todo.get("fillSlot") | |
| 728 repeat = todo.get("repeat") | |
| 729 content = todo.get("content") | |
| 730 replace = todo.get("replace") | |
| 731 condition = todo.get("condition") | |
| 732 onError = todo.get("onError") | |
| 733 define = todo.get("define") | |
| 734 repldict = todo.get("repldict", {}) | |
| 735 scope = todo.get("scope") | |
| 736 optTag = todo.get("optional tag") | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
737 msgid = todo.get('msgid') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
738 i18ncontext = todo.get("i18ncontext") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
739 varname = todo.get('i18nvar') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
740 i18ndata = todo.get('i18ndata') |
| 1049 | 741 |
| 742 if implied > 0: | |
| 743 if defineMacro or useMacro or defineSlot or fillSlot: | |
| 744 exc = METALError | |
| 745 what = "METAL" | |
| 746 else: | |
| 747 exc = TALError | |
| 748 what = "TAL" | |
| 749 raise exc("%s attributes on <%s> require explicit </%s>" % | |
| 750 (what, name, name), position) | |
| 751 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
752 # If there's no tal:content or tal:replace in the tag with the |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
753 # i18n:name, tal:replace is the default. |
| 1049 | 754 if content: |
| 755 self.emitSubstitution(content, {}) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
756 # If we're looking at an implicit msgid, emit the insertTranslation |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
757 # opcode now, so that the end tag doesn't become part of the implicit |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
758 # msgid. If we're looking at an explicit msgid, it's better to emit |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
759 # the opcode after the i18nVariable opcode so we can better handle |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
760 # tags with both of them in them (and in the latter case, the contents |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
761 # would be thrown away for msgid purposes). |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
762 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
763 # Still, we should emit insertTranslation opcode before i18nVariable |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
764 # in case tal:content, i18n:translate and i18n:name in the same tag |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
765 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
766 if (not varname) or ( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
767 varname and (varname[1] == I18N_CONTENT)): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
768 self.emitTranslation(msgid, i18ndata) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
769 self.i18nLevel -= 1 |
| 1049 | 770 if optTag: |
| 771 self.emitOptTag(name, optTag, isend) | |
| 772 elif not isend: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
773 # If we're processing the end tag for a tag that contained |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
774 # i18n:name, we need to make sure that optimize() won't collect |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
775 # immediately following end tags into the same rawtextOffset, so |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
776 # put a spacer here that the optimizer will recognize. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
777 if varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
778 self.emit('noop') |
| 1049 | 779 self.emitEndTag(name) |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
780 # If i18n:name appeared in the same tag as tal:replace then we're |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
781 # going to do the substitution a little bit differently. The results |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
782 # of the expression go into the i18n substitution dictionary. |
| 1049 | 783 if replace: |
| 784 self.emitSubstitution(replace, repldict) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
785 elif varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
786 # o varname[0] is the variable name |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
787 # o varname[1] is either |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
788 # - I18N_REPLACE for implicit tal:replace |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
789 # - I18N_CONTENT for tal:content |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
790 # - I18N_EXPRESSION for explicit tal:replace |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
791 # o varname[2] will be None for the first two actions and the |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
792 # replacement tal expression for the third action. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
793 assert (varname[1] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
794 in [I18N_REPLACE, I18N_CONTENT, I18N_EXPRESSION]) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
795 self.emitI18nVariable(varname) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
796 # Do not test for "msgid is not None", i.e. we only want to test for |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
797 # explicit msgids here. See comment above. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
798 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
799 # in case tal:content, i18n:translate and i18n:name in the |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
800 # same tag insertTranslation opcode has already been |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
801 # emitted |
|
5382
1556b39fde7c
Python 3 preparation: use != instead of <>.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
802 if varname and (varname[1] != I18N_CONTENT): |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
803 self.emitTranslation(msgid, i18ndata) |
| 1049 | 804 if repeat: |
| 805 self.emitRepeat(repeat) | |
| 806 if condition: | |
| 807 self.emitCondition(condition) | |
| 808 if onError: | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
809 self.emitOnError(name, onError, optTag and optTag[1], isend) |
| 1049 | 810 if scope: |
| 811 self.emit("endScope") | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
812 if i18ncontext: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
813 self.emit("endI18nContext") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
814 assert self.i18nContext.parent is not None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
815 self.i18nContext = self.i18nContext.parent |
| 1049 | 816 if defineSlot: |
| 817 self.emitDefineSlot(defineSlot) | |
| 818 if fillSlot: | |
| 819 self.emitFillSlot(fillSlot) | |
| 820 if useMacro: | |
| 821 self.emitUseMacro(useMacro) | |
| 822 if defineMacro: | |
| 823 self.emitDefineMacro(defineMacro) | |
| 824 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
825 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
826 def _parseI18nAttributes(i18nattrs, attrlist, repldict, position, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
827 xml, source_file): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
828 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
829 def addAttribute(dic, attr, msgid, position, xml): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
830 if not xml: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
831 attr = attr.lower() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
832 if attr in dic: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
833 raise TALError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
834 "attribute may only be specified once in i18n:attributes: " |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
835 + attr, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
836 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
837 dic[attr] = msgid |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
838 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
839 d = {} |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
840 if ';' in i18nattrs: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
841 i18nattrlist = i18nattrs.split(';') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
842 i18nattrlist = [attr.strip().split() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
843 for attr in i18nattrlist if attr.strip()] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
844 for parts in i18nattrlist: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
845 if len(parts) > 2: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
846 raise TALError("illegal i18n:attributes specification: %r" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
847 % parts, position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
848 if len(parts) == 2: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
849 attr, msgid = parts |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
850 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
851 # len(parts) == 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
852 attr = parts[0] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
853 msgid = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
854 addAttribute(d, attr, msgid, position, xml) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
855 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
856 i18nattrlist = i18nattrs.split() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
857 if len(i18nattrlist) == 2: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
858 staticattrs = [attr[0] for attr in attrlist if len(attr) == 2] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
859 if (not i18nattrlist[1] in staticattrs) and ( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
860 not i18nattrlist[1] in repldict): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
861 attr, msgid = i18nattrlist |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
862 addAttribute(d, attr, msgid, position, xml) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
863 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
864 msgid = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
865 for attr in i18nattrlist: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
866 addAttribute(d, attr, msgid, position, xml) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
867 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
868 msgid = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
869 for attr in i18nattrlist: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
870 addAttribute(d, attr, msgid, position, xml) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
871 return d |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
872 |
| 1049 | 873 def test(): |
| 874 t = TALGenerator() | |
| 875 t.pushProgram() | |
| 876 t.emit("bar") | |
| 877 p = t.popProgram() | |
| 878 t.emit("foo", p) | |
| 879 | |
| 880 if __name__ == "__main__": | |
| 881 test() |
