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('&amp;', s)
186 s = _entch_re.sub(r'&amp;\1', s)
187 s = _entn1_re.sub('&amp;#', s)
188 s = _entnx_re.sub(r'&amp;\1', s)
189 s = _entnd_re.sub(r'&amp;\1', s)
190 s = s.replace('<', '&lt;')
191 s = s.replace('>', '&gt;')
192 s = s.replace('"', '&quot;')
193 return s

Roundup Issue Tracker: http://roundup-tracker.org/