Mercurial > p > roundup > code
annotate roundup/cgi/TAL/TALGenerator.py @ 6422:91ae685405ba
- issue2550964 - History can (temporarily) show incorrect value...
when a change is rejected.
Fix history function to always use the database values and ignore the
current setting in the form.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Wed, 26 May 2021 12:04:06 -0400 |
| parents | 883c9e90b403 |
| children | 978285986b2c |
| 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 |
|
5837
883c9e90b403
Fix problem with cgi.escape being depricated a different way. This way
John Rouillard <rouilj@ieee.org>
parents:
5809
diff
changeset
|
28 from roundup.anypy.html import html_escape |
|
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
|
29 |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
30 I18N_REPLACE = 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
31 I18N_CONTENT = 2 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
32 I18N_EXPRESSION = 3 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
33 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
34 _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
|
35 |
| 1049 | 36 |
| 37 class TALGenerator: | |
| 38 | |
| 39 inMacroUse = 0 | |
| 40 inMacroDef = 0 | |
| 41 source_file = None | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
42 |
| 1049 | 43 def __init__(self, expressionCompiler=None, xml=1, source_file=None): |
| 44 if not expressionCompiler: | |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5382
diff
changeset
|
45 from .DummyEngine import DummyEngine |
| 1049 | 46 expressionCompiler = DummyEngine() |
| 47 self.expressionCompiler = expressionCompiler | |
| 48 self.CompilerError = expressionCompiler.getCompilerError() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
49 # This holds the emitted opcodes representing the input |
| 1049 | 50 self.program = [] |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
51 # 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
|
52 # 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
|
53 # contents describe the ${name} value. |
| 1049 | 54 self.stack = [] |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
55 # 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
|
56 # 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
|
57 # emitEndElement needs to finish its calculations |
| 1049 | 58 self.todoStack = [] |
| 59 self.macros = {} | |
| 60 self.slots = {} | |
| 61 self.slotStack = [] | |
| 62 self.xml = xml | |
| 63 self.emit("version", TAL_VERSION) | |
| 64 self.emit("mode", xml and "xml" or "html") | |
| 65 if source_file is not None: | |
| 66 self.source_file = source_file | |
| 67 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
|
68 self.i18nContext = TranslationContext() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
69 self.i18nLevel = 0 |
| 1049 | 70 |
| 71 def getCode(self): | |
| 72 assert not self.stack | |
| 73 assert not self.todoStack | |
| 74 return self.optimize(self.program), self.macros | |
| 75 | |
| 76 def optimize(self, program): | |
| 77 output = [] | |
| 78 collect = [] | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
79 cursor = 0 |
| 1049 | 80 if self.xml: |
| 81 endsep = "/>" | |
| 82 else: | |
| 83 endsep = " />" | |
|
5391
a391a071d045
Python 3 preparation: use range() instead of xrange().
Joseph Myers <jsm@polyomino.org.uk>
parents:
5388
diff
changeset
|
84 for cursor in range(len(program)+1): |
| 1049 | 85 try: |
| 86 item = program[cursor] | |
| 87 except IndexError: | |
| 88 item = (None, None) | |
| 89 opcode = item[0] | |
| 90 if opcode == "rawtext": | |
| 91 collect.append(item[1]) | |
| 92 continue | |
| 93 if opcode == "endTag": | |
| 94 collect.append("</%s>" % item[1]) | |
| 95 continue | |
| 96 if opcode == "startTag": | |
| 97 if self.optimizeStartTag(collect, item[1], item[2], ">"): | |
| 98 continue | |
| 99 if opcode == "startEndTag": | |
| 100 if self.optimizeStartTag(collect, item[1], item[2], endsep): | |
| 101 continue | |
| 102 if opcode in ("beginScope", "endScope"): | |
| 103 # Push *Scope instructions in front of any text instructions; | |
| 104 # this allows text instructions separated only by *Scope | |
| 105 # instructions to be joined together. | |
| 106 output.append(self.optimizeArgsList(item)) | |
| 107 continue | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
108 if opcode == 'noop': |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
109 # 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
|
110 # 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
|
111 # 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
|
112 opcode = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
113 pass |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
114 text = "".join(collect) |
| 1049 | 115 if text: |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
116 i = text.rfind("\n") |
| 1049 | 117 if i >= 0: |
| 118 i = len(text) - (i + 1) | |
| 119 output.append(("rawtextColumn", (text, i))) | |
| 120 else: | |
| 121 output.append(("rawtextOffset", (text, len(text)))) | |
| 122 if opcode != None: | |
| 123 output.append(self.optimizeArgsList(item)) | |
| 124 collect = [] | |
| 125 return self.optimizeCommonTriple(output) | |
| 126 | |
| 127 def optimizeArgsList(self, item): | |
| 128 if len(item) == 2: | |
| 129 return item | |
| 130 else: | |
| 131 return item[0], tuple(item[1:]) | |
| 132 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
133 # 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
|
134 # 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
|
135 # get action codes.) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
136 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
137 # 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
|
138 # TALInterpreter.attrAction() and .attrAction_tal(). |
|
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 # 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
|
141 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
142 # (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
|
143 # no special processing |
|
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, action, *extra) -- attribute with special |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
146 # processing needs, action is a |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
147 # code that indicates which |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
148 # branch to take, and *extra |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
149 # contains additional, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
150 # action-specific information |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
151 # needed by the processing |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
152 # |
| 1049 | 153 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
|
154 # return true if the tag can be converted to plain text |
| 1049 | 155 if not attrlist: |
| 156 collect.append("<%s%s" % (name, end)) | |
| 157 return 1 | |
| 158 opt = 1 | |
| 159 new = ["<" + name] | |
| 160 for i in range(len(attrlist)): | |
| 161 item = attrlist[i] | |
| 162 if len(item) > 2: | |
| 163 opt = 0 | |
| 164 name, value, action = item[:3] | |
| 165 attrlist[i] = (name, value, action) + item[3:] | |
| 166 else: | |
| 167 if item[1] is None: | |
| 168 s = item[0] | |
| 169 else: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
170 s = '%s="%s"' % (item[0], TALDefs.attrEscape(item[1])) |
| 1049 | 171 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
|
172 new.append(" " + s) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
173 # if no non-optimizable attributes were found, convert to plain text |
| 1049 | 174 if opt: |
| 175 new.append(end) | |
| 176 collect.extend(new) | |
| 177 return opt | |
| 178 | |
| 179 def optimizeCommonTriple(self, program): | |
| 180 if len(program) < 3: | |
| 181 return program | |
| 182 output = program[:2] | |
| 183 prev2, prev1 = output | |
| 184 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
|
185 if ( item[0] == "beginScope" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
186 and prev1[0] == "setPosition" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
187 and prev2[0] == "rawtextColumn"): |
| 1049 | 188 position = output.pop()[1] |
| 189 text, column = output.pop()[1] | |
| 190 prev1 = None, None | |
| 191 closeprev = 0 | |
| 192 if output and output[-1][0] == "endScope": | |
| 193 closeprev = 1 | |
| 194 output.pop() | |
| 195 item = ("rawtextBeginScope", | |
| 196 (text, column, position, closeprev, item[1])) | |
| 197 output.append(item) | |
| 198 prev2 = prev1 | |
| 199 prev1 = item | |
| 200 return output | |
| 201 | |
| 202 def todoPush(self, todo): | |
| 203 self.todoStack.append(todo) | |
| 204 | |
| 205 def todoPop(self): | |
| 206 return self.todoStack.pop() | |
| 207 | |
| 208 def compileExpression(self, expr): | |
| 209 try: | |
| 210 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
|
211 except self.CompilerError as err: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
212 raise TALError('%s in expression %s' % (err.args[0], repr(expr)), |
| 1049 | 213 self.position) |
| 214 | |
| 215 def pushProgram(self): | |
| 216 self.stack.append(self.program) | |
| 217 self.program = [] | |
| 218 | |
| 219 def popProgram(self): | |
| 220 program = self.program | |
| 221 self.program = self.stack.pop() | |
| 222 return self.optimize(program) | |
| 223 | |
| 224 def pushSlots(self): | |
| 225 self.slotStack.append(self.slots) | |
| 226 self.slots = {} | |
| 227 | |
| 228 def popSlots(self): | |
| 229 slots = self.slots | |
| 230 self.slots = self.slotStack.pop() | |
| 231 return slots | |
| 232 | |
| 233 def emit(self, *instruction): | |
| 234 self.program.append(instruction) | |
| 235 | |
| 236 def emitStartTag(self, name, attrlist, isend=0): | |
| 237 if isend: | |
| 238 opcode = "startEndTag" | |
| 239 else: | |
| 240 opcode = "startTag" | |
| 241 self.emit(opcode, name, attrlist) | |
| 242 | |
| 243 def emitEndTag(self, name): | |
| 244 if self.xml and self.program and self.program[-1][0] == "startTag": | |
| 245 # Minimize empty element | |
| 246 self.program[-1] = ("startEndTag",) + self.program[-1][1:] | |
| 247 else: | |
| 248 self.emit("endTag", name) | |
| 249 | |
| 250 def emitOptTag(self, name, optTag, isend): | |
| 251 program = self.popProgram() #block | |
| 252 start = self.popProgram() #start tag | |
| 253 if (isend or not program) and self.xml: | |
| 254 # Minimize empty element | |
| 255 start[-1] = ("startEndTag",) + start[-1][1:] | |
| 256 isend = 1 | |
| 257 cexpr = optTag[0] | |
| 258 if cexpr: | |
| 259 cexpr = self.compileExpression(optTag[0]) | |
| 260 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
|
261 |
| 1049 | 262 def emitRawText(self, text): |
| 263 self.emit("rawtext", text) | |
| 264 | |
| 265 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
|
266 self.emitRawText(html_escape(text)) |
| 1049 | 267 |
| 268 def emitDefines(self, defines): | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
269 for part in TALDefs.splitParts(defines): |
| 1049 | 270 m = re.match( |
| 271 r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part) | |
| 272 if not m: | |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
273 raise TALError("invalid define syntax: " + repr(part), |
| 1049 | 274 self.position) |
| 275 scope, name, expr = m.group(1, 2, 3) | |
| 276 scope = scope or "local" | |
| 277 cexpr = self.compileExpression(expr) | |
| 278 if scope == "local": | |
| 279 self.emit("setLocal", name, cexpr) | |
| 280 else: | |
| 281 self.emit("setGlobal", name, cexpr) | |
| 282 | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
283 def emitOnError(self, name, onError, TALtag, isend): |
| 1049 | 284 block = self.popProgram() |
| 285 key, expr = parseSubstitution(onError) | |
| 286 cexpr = self.compileExpression(expr) | |
| 287 if key == "text": | |
| 288 self.emit("insertText", cexpr, []) | |
| 289 else: | |
| 290 assert key == "structure" | |
| 291 self.emit("insertStructure", cexpr, {}, []) | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
292 if TALtag: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
293 self.emitOptTag(name, (None, 1), isend) |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
294 else: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
295 self.emitEndTag(name) |
| 1049 | 296 handler = self.popProgram() |
| 297 self.emit("onError", block, handler) | |
| 298 | |
| 299 def emitCondition(self, expr): | |
| 300 cexpr = self.compileExpression(expr) | |
| 301 program = self.popProgram() | |
| 302 self.emit("condition", cexpr, program) | |
| 303 | |
| 304 def emitRepeat(self, arg): | |
| 5809 | 305 m = re.match(r"(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg) |
| 1049 | 306 if not m: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
307 raise TALError("invalid repeat syntax: " + repr(arg), |
| 1049 | 308 self.position) |
| 309 name, expr = m.group(1, 2) | |
| 310 cexpr = self.compileExpression(expr) | |
| 311 program = self.popProgram() | |
| 312 self.emit("loop", name, cexpr, program) | |
| 313 | |
| 314 def emitSubstitution(self, arg, attrDict={}): | |
| 315 key, expr = parseSubstitution(arg) | |
| 316 cexpr = self.compileExpression(expr) | |
| 317 program = self.popProgram() | |
| 318 if key == "text": | |
| 319 self.emit("insertText", cexpr, program) | |
| 320 else: | |
| 321 assert key == "structure" | |
| 322 self.emit("insertStructure", cexpr, attrDict, program) | |
| 323 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
324 def emitI18nVariable(self, stuff): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
325 # 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
|
326 # 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
|
327 # 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
|
328 # 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
|
329 # 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
|
330 # 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
|
331 # the tag. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
332 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
333 # 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
|
334 # 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
|
335 # "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
|
336 # tal:replace="here/countryOfOrigin" />" |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
337 varname, action, expression = stuff |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
338 m = _name_rx.match(varname) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
339 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
|
340 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
|
341 key = cexpr = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
342 program = self.popProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
343 if action == I18N_REPLACE: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
344 # 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
|
345 # 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
|
346 # 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
|
347 program = program[1:-1] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
348 elif action == I18N_CONTENT: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
349 # 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
|
350 # (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
|
351 # 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
|
352 pass |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
353 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
354 assert action == I18N_EXPRESSION |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
355 key, expr = parseSubstitution(expression) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
356 cexpr = self.compileExpression(expr) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
357 # 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
|
358 assert key in ('text', None) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
359 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
|
360 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
361 def emitTranslation(self, msgid, i18ndata): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
362 program = self.popProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
363 if i18ndata is None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
364 self.emit('insertTranslation', msgid, program) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
365 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
366 key, expr = parseSubstitution(i18ndata) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
367 cexpr = self.compileExpression(expr) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
368 assert key == 'text' |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
369 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
|
370 |
| 1049 | 371 def emitDefineMacro(self, macroName): |
| 372 program = self.popProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
373 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
|
374 if macroName in self.macros: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
375 raise METALError("duplicate macro definition: %s" % repr(macroName), |
| 1049 | 376 self.position) |
| 377 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
|
378 raise METALError("invalid macro name: %s" % repr(macroName), |
| 1049 | 379 self.position) |
| 380 self.macros[macroName] = program | |
| 381 self.inMacroDef = self.inMacroDef - 1 | |
| 382 self.emit("defineMacro", macroName, program) | |
| 383 | |
| 384 def emitUseMacro(self, expr): | |
| 385 cexpr = self.compileExpression(expr) | |
| 386 program = self.popProgram() | |
| 387 self.inMacroUse = 0 | |
| 388 self.emit("useMacro", expr, cexpr, self.popSlots(), program) | |
| 389 | |
| 390 def emitDefineSlot(self, slotName): | |
| 391 program = self.popProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
392 slotName = slotName.strip() |
| 1049 | 393 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
|
394 raise METALError("invalid slot name: %s" % repr(slotName), |
| 1049 | 395 self.position) |
| 396 self.emit("defineSlot", slotName, program) | |
| 397 | |
| 398 def emitFillSlot(self, slotName): | |
| 399 program = self.popProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
400 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
|
401 if slotName in self.slots: |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
402 raise METALError("duplicate fill-slot name: %s" % repr(slotName), |
| 1049 | 403 self.position) |
| 404 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
|
405 raise METALError("invalid slot name: %s" % repr(slotName), |
| 1049 | 406 self.position) |
| 407 self.slots[slotName] = program | |
| 408 self.inMacroUse = 1 | |
| 409 self.emit("fillSlot", slotName, program) | |
| 410 | |
| 411 def unEmitWhitespace(self): | |
| 412 collect = [] | |
| 413 i = len(self.program) - 1 | |
| 414 while i >= 0: | |
| 415 item = self.program[i] | |
| 416 if item[0] != "rawtext": | |
| 417 break | |
| 418 text = item[1] | |
| 419 if not re.match(r"\A\s*\Z", text): | |
| 420 break | |
| 421 collect.append(text) | |
| 422 i = i-1 | |
| 423 del self.program[i+1:] | |
| 424 if i >= 0 and self.program[i][0] == "rawtext": | |
| 425 text = self.program[i][1] | |
| 426 m = re.search(r"\s+\Z", text) | |
| 427 if m: | |
| 428 self.program[i] = ("rawtext", text[:m.start()]) | |
| 429 collect.append(m.group()) | |
| 430 collect.reverse() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
431 return "".join(collect) |
| 1049 | 432 |
| 433 def unEmitNewlineWhitespace(self): | |
| 434 collect = [] | |
| 435 i = len(self.program) | |
| 436 while i > 0: | |
| 437 i = i-1 | |
| 438 item = self.program[i] | |
| 439 if item[0] != "rawtext": | |
| 440 break | |
| 441 text = item[1] | |
| 442 if re.match(r"\A[ \t]*\Z", text): | |
| 443 collect.append(text) | |
| 444 continue | |
| 445 m = re.match(r"(?s)^(.*)(\n[ \t]*)\Z", text) | |
| 446 if not m: | |
| 447 break | |
| 448 text, rest = m.group(1, 2) | |
| 449 collect.reverse() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
450 rest = rest + "".join(collect) |
| 1049 | 451 del self.program[i:] |
| 452 if text: | |
| 453 self.emit("rawtext", text) | |
| 454 return rest | |
| 455 return None | |
| 456 | |
| 457 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
|
458 # 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
|
459 # 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
|
460 # 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
|
461 # 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
|
462 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
463 # (name, value, action, expr, xlat) |
| 1049 | 464 if not repldict: |
| 465 return attrlist | |
| 466 newlist = [] | |
| 467 for item in attrlist: | |
| 468 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
|
469 if key in repldict: |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
470 expr, xlat, msgid = repldict[key] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
471 item = item[:2] + ("replace", expr, xlat, msgid) |
| 1049 | 472 del repldict[key] |
| 473 newlist.append(item) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
474 # Add dynamic-only attributes |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
475 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
|
476 newlist.append((key, None, "insert", expr, xlat, msgid)) |
| 1049 | 477 return newlist |
| 478 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
479 def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict, |
| 1049 | 480 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
|
481 if not taldict and not metaldict and not i18ndict: |
| 1049 | 482 # Handle the simple, common case |
| 483 self.emitStartTag(name, attrlist, isend) | |
| 484 self.todoPush({}) | |
| 485 if isend: | |
| 486 self.emitEndElement(name, isend) | |
| 487 return | |
| 488 | |
| 489 self.position = position | |
| 490 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
|
491 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
|
492 raise TALError("bad TAL attribute: " + repr(key), position) |
| 1049 | 493 if not (value or key == 'omit-tag'): |
| 494 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
|
495 repr(key), position) |
| 1049 | 496 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
|
497 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
|
498 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
|
499 position) |
| 1049 | 500 if not value: |
| 501 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
|
502 repr(key), position) |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
503 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
|
504 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
|
505 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
|
506 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
|
507 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
|
508 repr(key), position) |
| 1049 | 509 todo = {} |
| 510 defineMacro = metaldict.get("define-macro") | |
| 511 useMacro = metaldict.get("use-macro") | |
| 512 defineSlot = metaldict.get("define-slot") | |
| 513 fillSlot = metaldict.get("fill-slot") | |
| 514 define = taldict.get("define") | |
| 515 condition = taldict.get("condition") | |
| 516 repeat = taldict.get("repeat") | |
| 517 content = taldict.get("content") | |
| 518 replace = taldict.get("replace") | |
| 519 attrsubst = taldict.get("attributes") | |
| 520 onError = taldict.get("on-error") | |
| 521 omitTag = taldict.get("omit-tag") | |
| 522 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
|
523 i18nattrs = i18ndict.get("attributes") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
524 # 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
|
525 # 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
|
526 # interpretation phase. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
527 msgid = i18ndict.get("translate") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
528 varname = i18ndict.get('name') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
529 i18ndata = i18ndict.get('data') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
530 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
531 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
|
532 raise I18NError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
533 "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
|
534 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
535 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
536 if i18ndata and not msgid: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
537 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
|
538 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
539 |
| 1049 | 540 if len(metaldict) > 1 and (defineMacro or useMacro): |
| 541 raise METALError("define-macro and use-macro cannot be used " | |
| 542 "together or with define-slot or fill-slot", | |
| 543 position) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
544 if replace: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
545 if content: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
546 raise TALError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
547 "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
|
548 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
549 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
550 raise I18NError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
551 "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
|
552 position) |
| 1049 | 553 |
| 554 repeatWhitespace = None | |
| 555 if repeat: | |
| 556 # Hack to include preceding whitespace in the loop program | |
| 557 repeatWhitespace = self.unEmitNewlineWhitespace() | |
| 558 if position != (None, None): | |
| 559 # XXX at some point we should insist on a non-trivial position | |
| 560 self.emit("setPosition", position) | |
| 561 if self.inMacroUse: | |
| 562 if fillSlot: | |
| 563 self.pushProgram() | |
| 564 if self.source_file is not None: | |
| 565 self.emit("setSourceFile", self.source_file) | |
| 566 todo["fillSlot"] = fillSlot | |
| 567 self.inMacroUse = 0 | |
| 568 else: | |
| 569 if fillSlot: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
570 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
|
571 position) |
| 1049 | 572 if not self.inMacroUse: |
| 573 if defineMacro: | |
| 574 self.pushProgram() | |
| 575 self.emit("version", TAL_VERSION) | |
| 576 self.emit("mode", self.xml and "xml" or "html") | |
| 577 if self.source_file is not None: | |
| 578 self.emit("setSourceFile", self.source_file) | |
| 579 todo["defineMacro"] = defineMacro | |
| 580 self.inMacroDef = self.inMacroDef + 1 | |
| 581 if useMacro: | |
| 582 self.pushSlots() | |
| 583 self.pushProgram() | |
| 584 todo["useMacro"] = useMacro | |
| 585 self.inMacroUse = 1 | |
| 586 if defineSlot: | |
| 587 if not self.inMacroDef: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
588 raise METALError( |
| 1049 | 589 "define-slot must be within a define-macro", |
| 590 position) | |
| 591 self.pushProgram() | |
| 592 todo["defineSlot"] = defineSlot | |
| 593 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
594 if defineSlot or i18ndict: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
595 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
596 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
|
597 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
|
598 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
|
599 if ( domain != DEFAULT_DOMAIN |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
600 or source is not None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
601 or target is not None): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
602 self.i18nContext = TranslationContext(self.i18nContext, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
603 domain=domain, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
604 source=source, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
605 target=target) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
606 self.emit("beginI18nContext", |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
607 {"domain": domain, "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 todo["i18ncontext"] = 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
610 if taldict or i18ndict: |
| 1049 | 611 dict = {} |
| 612 for item in attrlist: | |
| 613 key, value = item[:2] | |
| 614 dict[key] = value | |
| 615 self.emit("beginScope", dict) | |
| 616 todo["scope"] = 1 | |
| 617 if onError: | |
| 618 self.pushProgram() # handler | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
619 if TALtag: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
620 self.pushProgram() # start |
| 1049 | 621 self.emitStartTag(name, list(attrlist)) # Must copy attrlist! |
|
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.pushProgram() # block |
| 625 todo["onError"] = onError | |
| 626 if define: | |
| 627 self.emitDefines(define) | |
| 628 todo["define"] = define | |
| 629 if condition: | |
| 630 self.pushProgram() | |
| 631 todo["condition"] = condition | |
| 632 if repeat: | |
| 633 todo["repeat"] = repeat | |
| 634 self.pushProgram() | |
| 635 if repeatWhitespace: | |
| 636 self.emitText(repeatWhitespace) | |
| 637 if content: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
638 if varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
639 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
|
640 todo["content"] = content |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
641 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
642 else: |
|
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 elif replace: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
645 # 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
|
646 # 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
|
647 # placeholder. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
648 if varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
649 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
|
650 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
651 todo["replace"] = replace |
| 1049 | 652 self.pushProgram() |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
653 # 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
|
654 # dictionary values |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
655 elif varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
656 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
|
657 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
658 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
659 self.i18nLevel += 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
660 todo['msgid'] = msgid |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
661 if i18ndata: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
662 todo['i18ndata'] = i18ndata |
| 1049 | 663 optTag = omitTag is not None or TALtag |
| 664 if optTag: | |
| 665 todo["optional tag"] = omitTag, TALtag | |
| 666 self.pushProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
667 if attrsubst or i18nattrs: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
668 if attrsubst: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
669 repldict = TALDefs.parseAttributeReplacements(attrsubst, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
670 self.xml) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
671 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
672 repldict = {} |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
673 if i18nattrs: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
674 i18nattrs = _parseI18nAttributes(i18nattrs, attrlist, repldict, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
675 self.position, self.xml, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
676 self.source_file) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
677 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
678 i18nattrs = {} |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
679 # 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
|
680 # name-->(compiled_expr, translate) mapping |
| 1049 | 681 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
|
682 if i18nattrs.get(key, None): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
683 raise I18NError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
684 ("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
|
685 " 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
|
686 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
687 ce = self.compileExpression(value) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
688 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
|
689 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
|
690 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
|
691 repldict[key] = None, 1, i18nattrs.get(key) |
| 1049 | 692 else: |
| 693 repldict = {} | |
| 694 if replace: | |
| 695 todo["repldict"] = repldict | |
| 696 repldict = {} | |
| 697 self.emitStartTag(name, self.replaceAttrs(attrlist, repldict), isend) | |
| 698 if optTag: | |
| 699 self.pushProgram() | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
700 if content and not varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
701 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
702 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
703 self.pushProgram() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
704 if content and varname: |
| 1049 | 705 self.pushProgram() |
| 706 if todo and position != (None, None): | |
| 707 todo["position"] = position | |
| 708 self.todoPush(todo) | |
| 709 if isend: | |
| 710 self.emitEndElement(name, isend) | |
| 711 | |
| 712 def emitEndElement(self, name, isend=0, implied=0): | |
| 713 todo = self.todoPop() | |
| 714 if not todo: | |
| 715 # Shortcut | |
| 716 if not isend: | |
| 717 self.emitEndTag(name) | |
| 718 return | |
| 719 | |
| 720 self.position = position = todo.get("position", (None, None)) | |
| 721 defineMacro = todo.get("defineMacro") | |
| 722 useMacro = todo.get("useMacro") | |
| 723 defineSlot = todo.get("defineSlot") | |
| 724 fillSlot = todo.get("fillSlot") | |
| 725 repeat = todo.get("repeat") | |
| 726 content = todo.get("content") | |
| 727 replace = todo.get("replace") | |
| 728 condition = todo.get("condition") | |
| 729 onError = todo.get("onError") | |
| 730 define = todo.get("define") | |
| 731 repldict = todo.get("repldict", {}) | |
| 732 scope = todo.get("scope") | |
| 733 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
|
734 msgid = todo.get('msgid') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
735 i18ncontext = todo.get("i18ncontext") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
736 varname = todo.get('i18nvar') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
737 i18ndata = todo.get('i18ndata') |
| 1049 | 738 |
| 739 if implied > 0: | |
| 740 if defineMacro or useMacro or defineSlot or fillSlot: | |
| 741 exc = METALError | |
| 742 what = "METAL" | |
| 743 else: | |
| 744 exc = TALError | |
| 745 what = "TAL" | |
| 746 raise exc("%s attributes on <%s> require explicit </%s>" % | |
| 747 (what, name, name), position) | |
| 748 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
749 # 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
|
750 # i18n:name, tal:replace is the default. |
| 1049 | 751 if content: |
| 752 self.emitSubstitution(content, {}) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
753 # 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
|
754 # 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
|
755 # 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
|
756 # 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
|
757 # 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
|
758 # 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
|
759 # |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
760 # 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
|
761 # 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
|
762 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
763 if (not varname) or ( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
764 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
|
765 self.emitTranslation(msgid, i18ndata) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
766 self.i18nLevel -= 1 |
| 1049 | 767 if optTag: |
| 768 self.emitOptTag(name, optTag, isend) | |
| 769 elif not isend: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
770 # 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
|
771 # 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
|
772 # 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
|
773 # 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
|
774 if varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
775 self.emit('noop') |
| 1049 | 776 self.emitEndTag(name) |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
777 # 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
|
778 # 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
|
779 # of the expression go into the i18n substitution dictionary. |
| 1049 | 780 if replace: |
| 781 self.emitSubstitution(replace, repldict) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
782 elif varname: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
783 # 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
|
784 # o varname[1] is either |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
785 # - 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
|
786 # - I18N_CONTENT for tal:content |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
787 # - 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
|
788 # 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
|
789 # 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
|
790 assert (varname[1] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
791 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
|
792 self.emitI18nVariable(varname) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
793 # 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
|
794 # 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
|
795 if msgid is not None: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
796 # 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
|
797 # 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
|
798 # emitted |
|
5382
1556b39fde7c
Python 3 preparation: use != instead of <>.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
799 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
|
800 self.emitTranslation(msgid, i18ndata) |
| 1049 | 801 if repeat: |
| 802 self.emitRepeat(repeat) | |
| 803 if condition: | |
| 804 self.emitCondition(condition) | |
| 805 if onError: | |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
806 self.emitOnError(name, onError, optTag and optTag[1], isend) |
| 1049 | 807 if scope: |
| 808 self.emit("endScope") | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
809 if i18ncontext: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
810 self.emit("endI18nContext") |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
811 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
|
812 self.i18nContext = self.i18nContext.parent |
| 1049 | 813 if defineSlot: |
| 814 self.emitDefineSlot(defineSlot) | |
| 815 if fillSlot: | |
| 816 self.emitFillSlot(fillSlot) | |
| 817 if useMacro: | |
| 818 self.emitUseMacro(useMacro) | |
| 819 if defineMacro: | |
| 820 self.emitDefineMacro(defineMacro) | |
| 821 | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
822 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
823 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
|
824 xml, source_file): |
|
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 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
|
827 if not xml: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
828 attr = attr.lower() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
829 if attr in dic: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
830 raise TALError( |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
831 "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
|
832 + attr, |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
833 position) |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
834 dic[attr] = msgid |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
835 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
836 d = {} |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
837 if ';' in i18nattrs: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
838 i18nattrlist = i18nattrs.split(';') |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
839 i18nattrlist = [attr.strip().split() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
840 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
|
841 for parts in i18nattrlist: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
842 if len(parts) > 2: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
843 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
|
844 % parts, position) |
|
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 attr, msgid = parts |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
847 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
848 # len(parts) == 1 |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
849 attr = parts[0] |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
850 msgid = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
851 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
|
852 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
853 i18nattrlist = i18nattrs.split() |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
854 if len(i18nattrlist) == 2: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
855 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
|
856 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
|
857 not i18nattrlist[1] in repldict): |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
858 attr, msgid = i18nattrlist |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
859 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
|
860 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
861 msgid = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
862 for attr in i18nattrlist: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
863 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
|
864 else: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
865 msgid = None |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
866 for attr in i18nattrlist: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
867 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
|
868 return d |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
869 |
| 1049 | 870 def test(): |
| 871 t = TALGenerator() | |
| 872 t.pushProgram() | |
| 873 t.emit("bar") | |
| 874 p = t.popProgram() | |
| 875 t.emit("foo", p) | |
| 876 | |
| 877 if __name__ == "__main__": | |
| 878 test() |
