Mercurial > p > roundup > code
comparison roundup/cgi/TAL/TALDefs.py @ 2348:8c2402a78bb0
beginning getting ZPT up to date: TAL first
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Fri, 21 May 2004 05:36:30 +0000 |
| parents | fc52d57c6c3e |
| children | 63868084b8bb |
comparison
equal
deleted
inserted
replaced
| 2347:fbbda3b1816d | 2348:8c2402a78bb0 |
|---|---|
| 1 ############################################################################## | 1 ############################################################################## |
| 2 # | 2 # |
| 3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors. | 3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors. |
| 4 # All Rights Reserved. | 4 # All Rights Reserved. |
| 5 # | 5 # |
| 6 # This software is subject to the provisions of the Zope Public License, | 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. | 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 | 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 | 9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | 10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
| 11 # FOR A PARTICULAR PURPOSE | 11 # FOR A PARTICULAR PURPOSE. |
| 12 # | 12 # |
| 13 ############################################################################## | 13 ############################################################################## |
| 14 """Common definitions used by TAL and METAL compilation an transformation. | 14 # Modifications for Roundup: |
| 15 # 1. commented out ITALES references | |
| 15 """ | 16 """ |
| 16 __docformat__ = 'restructuredtext' | 17 Common definitions used by TAL and METAL compilation an transformation. |
| 18 """ | |
| 17 | 19 |
| 18 from types import ListType, TupleType | 20 from types import ListType, TupleType |
| 19 | 21 |
| 20 TAL_VERSION = "1.3.2" | 22 #from ITALES import ITALESErrorInfo |
| 23 | |
| 24 TAL_VERSION = "1.4" | |
| 21 | 25 |
| 22 XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace | 26 XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace |
| 23 XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations | 27 XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations |
| 24 | 28 |
| 25 ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal" | 29 ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal" |
| 26 ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal" | 30 ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal" |
| 31 ZOPE_I18N_NS = "http://xml.zope.org/namespaces/i18n" | |
| 27 | 32 |
| 28 NAME_RE = "[a-zA-Z_][a-zA-Z0-9_]*" | 33 # This RE must exactly match the expression of the same name in the |
| 34 # zope.i18n.simpletranslationservice module: | |
| 35 NAME_RE = "[a-zA-Z_][-a-zA-Z0-9_]*" | |
| 29 | 36 |
| 30 KNOWN_METAL_ATTRIBUTES = [ | 37 KNOWN_METAL_ATTRIBUTES = [ |
| 31 "define-macro", | 38 "define-macro", |
| 32 "use-macro", | 39 "use-macro", |
| 33 "define-slot", | 40 "define-slot", |
| 34 "fill-slot", | 41 "fill-slot", |
| 35 "slot" | 42 "slot", |
| 36 ] | 43 ] |
| 37 | 44 |
| 38 KNOWN_TAL_ATTRIBUTES = [ | 45 KNOWN_TAL_ATTRIBUTES = [ |
| 39 "define", | 46 "define", |
| 40 "condition", | 47 "condition", |
| 45 "on-error", | 52 "on-error", |
| 46 "omit-tag", | 53 "omit-tag", |
| 47 "tal tag", | 54 "tal tag", |
| 48 ] | 55 ] |
| 49 | 56 |
| 57 KNOWN_I18N_ATTRIBUTES = [ | |
| 58 "translate", | |
| 59 "domain", | |
| 60 "target", | |
| 61 "source", | |
| 62 "attributes", | |
| 63 "data", | |
| 64 "name", | |
| 65 ] | |
| 66 | |
| 50 class TALError(Exception): | 67 class TALError(Exception): |
| 51 | 68 |
| 52 def __init__(self, msg, position=(None, None)): | 69 def __init__(self, msg, position=(None, None)): |
| 53 assert msg != "" | 70 assert msg != "" |
| 54 self.msg = msg | 71 self.msg = msg |
| 55 self.lineno = position[0] | 72 self.lineno = position[0] |
| 56 self.offset = position[1] | 73 self.offset = position[1] |
| 74 self.filename = None | |
| 75 | |
| 76 def setFile(self, filename): | |
| 77 self.filename = filename | |
| 57 | 78 |
| 58 def __str__(self): | 79 def __str__(self): |
| 59 result = self.msg | 80 result = self.msg |
| 60 if self.lineno is not None: | 81 if self.lineno is not None: |
| 61 result = result + ", at line %d" % self.lineno | 82 result = result + ", at line %d" % self.lineno |
| 62 if self.offset is not None: | 83 if self.offset is not None: |
| 63 result = result + ", column %d" % (self.offset + 1) | 84 result = result + ", column %d" % (self.offset + 1) |
| 85 if self.filename is not None: | |
| 86 result = result + ', in file %s' % self.filename | |
| 64 return result | 87 return result |
| 65 | 88 |
| 66 class METALError(TALError): | 89 class METALError(TALError): |
| 67 pass | 90 pass |
| 68 | 91 |
| 69 class TALESError(TALError): | 92 class TALESError(TALError): |
| 70 pass | 93 pass |
| 71 | 94 |
| 95 class I18NError(TALError): | |
| 96 pass | |
| 97 | |
| 98 | |
| 72 class ErrorInfo: | 99 class ErrorInfo: |
| 100 | |
| 101 #__implements__ = ITALESErrorInfo | |
| 73 | 102 |
| 74 def __init__(self, err, position=(None, None)): | 103 def __init__(self, err, position=(None, None)): |
| 75 if isinstance(err, Exception): | 104 if isinstance(err, Exception): |
| 76 self.type = err.__class__ | 105 self.type = err.__class__ |
| 77 self.value = err | 106 self.value = err |
| 79 self.type = err | 108 self.type = err |
| 80 self.value = None | 109 self.value = None |
| 81 self.lineno = position[0] | 110 self.lineno = position[0] |
| 82 self.offset = position[1] | 111 self.offset = position[1] |
| 83 | 112 |
| 113 | |
| 114 | |
| 84 import re | 115 import re |
| 85 _attr_re = re.compile(r"\s*([^\s]+)\s+([^\s].*)\Z", re.S) | 116 _attr_re = re.compile(r"\s*([^\s]+)\s+([^\s].*)\Z", re.S) |
| 86 _subst_re = re.compile(r"\s*(?:(text|structure)\s+)?(.*)\Z", re.S) | 117 _subst_re = re.compile(r"\s*(?:(text|structure)\s+)?(.*)\Z", re.S) |
| 87 del re | 118 del re |
| 88 | 119 |
| 89 def parseAttributeReplacements(arg): | 120 def parseAttributeReplacements(arg, xml): |
| 90 dict = {} | 121 dict = {} |
| 91 for part in splitParts(arg): | 122 for part in splitParts(arg): |
| 92 m = _attr_re.match(part) | 123 m = _attr_re.match(part) |
| 93 if not m: | 124 if not m: |
| 94 raise TALError("Bad syntax in attributes:" + `part`) | 125 raise TALError("Bad syntax in attributes: " + `part`) |
| 95 name, expr = m.group(1, 2) | 126 name, expr = m.group(1, 2) |
| 127 if not xml: | |
| 128 name = name.lower() | |
| 96 if dict.has_key(name): | 129 if dict.has_key(name): |
| 97 raise TALError("Duplicate attribute name in attributes:" + `part`) | 130 raise TALError("Duplicate attribute name in attributes: " + `part`) |
| 98 dict[name] = expr | 131 dict[name] = expr |
| 99 return dict | 132 return dict |
| 100 | 133 |
| 101 def parseSubstitution(arg, position=(None, None)): | 134 def parseSubstitution(arg, position=(None, None)): |
| 102 m = _subst_re.match(arg) | 135 m = _subst_re.match(arg) |
| 108 return key, expr | 141 return key, expr |
| 109 | 142 |
| 110 def splitParts(arg): | 143 def splitParts(arg): |
| 111 # Break in pieces at undoubled semicolons and | 144 # Break in pieces at undoubled semicolons and |
| 112 # change double semicolons to singles: | 145 # change double semicolons to singles: |
| 113 import string | 146 arg = arg.replace(";;", "\0") |
| 114 arg = string.replace(arg, ";;", "\0") | 147 parts = arg.split(';') |
| 115 parts = string.split(arg, ';') | 148 parts = [p.replace("\0", ";") for p in parts] |
| 116 parts = map(lambda s, repl=string.replace: repl(s, "\0", ";"), parts) | 149 if len(parts) > 1 and not parts[-1].strip(): |
| 117 if len(parts) > 1 and not string.strip(parts[-1]): | |
| 118 del parts[-1] # It ended in a semicolon | 150 del parts[-1] # It ended in a semicolon |
| 119 return parts | 151 return parts |
| 120 | 152 |
| 121 def isCurrentVersion(program): | 153 def isCurrentVersion(program): |
| 122 version = getProgramVersion(program) | 154 version = getProgramVersion(program) |
| 137 opcode, version = program[0] | 169 opcode, version = program[0] |
| 138 if opcode == "version": | 170 if opcode == "version": |
| 139 return version | 171 return version |
| 140 return None | 172 return None |
| 141 | 173 |
| 142 import cgi | 174 import re |
| 143 def quote(s, escape=cgi.escape): | 175 _ent1_re = re.compile('&(?![A-Z#])', re.I) |
| 144 return '"%s"' % escape(s, 1) | 176 _entch_re = re.compile('&([A-Z][A-Z0-9]*)(?![A-Z0-9;])', re.I) |
| 145 del cgi | 177 _entn1_re = re.compile('&#(?![0-9X])', re.I) |
| 178 _entnx_re = re.compile('&(#X[A-F0-9]*)(?![A-F0-9;])', re.I) | |
| 179 _entnd_re = re.compile('&(#[0-9][0-9]*)(?![0-9;])') | |
| 180 del re | |
| 181 | |
| 182 def attrEscape(s): | |
| 183 """Replace special characters '&<>' by character entities, | |
| 184 except when '&' already begins a syntactically valid entity.""" | |
| 185 s = _ent1_re.sub('&', s) | |
| 186 s = _entch_re.sub(r'&\1', s) | |
| 187 s = _entn1_re.sub('&#', s) | |
| 188 s = _entnx_re.sub(r'&\1', s) | |
| 189 s = _entnd_re.sub(r'&\1', s) | |
| 190 s = s.replace('<', '<') | |
| 191 s = s.replace('>', '>') | |
| 192 s = s.replace('"', '"') | |
| 193 return s |
