Code

*** empty log message ***
[roundup.git] / TAL / TALDefs.py
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
4 # All Rights Reserved.
5
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
11 # FOR A PARTICULAR PURPOSE
12
13 ##############################################################################
14 """
15 Common definitions used by TAL and METAL compilation an transformation.
16 """
18 from types import ListType, TupleType
20 TAL_VERSION = "1.3.2"
22 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
25 ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal"
26 ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal"
28 NAME_RE = "[a-zA-Z_][a-zA-Z0-9_]*"
30 KNOWN_METAL_ATTRIBUTES = [
31     "define-macro",
32     "use-macro",
33     "define-slot",
34     "fill-slot",
35     "slot"
36     ]
38 KNOWN_TAL_ATTRIBUTES = [
39     "define",
40     "condition",
41     "content",
42     "replace",
43     "repeat",
44     "attributes",
45     "on-error",
46     "omit-tag",
47     "tal tag",
48     ]
50 class TALError(Exception):
52     def __init__(self, msg, position=(None, None)):
53         assert msg != ""
54         self.msg = msg
55         self.lineno = position[0]
56         self.offset = position[1]
58     def __str__(self):
59         result = self.msg
60         if self.lineno is not None:
61             result = result + ", at line %d" % self.lineno
62         if self.offset is not None:
63             result = result + ", column %d" % (self.offset + 1)
64         return result
66 class METALError(TALError):
67     pass
69 class TALESError(TALError):
70     pass
72 class ErrorInfo:
74     def __init__(self, err, position=(None, None)):
75         if isinstance(err, Exception):
76             self.type = err.__class__
77             self.value = err
78         else:
79             self.type = err
80             self.value = None
81         self.lineno = position[0]
82         self.offset = position[1]
84 import re
85 _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)
87 del re
89 def parseAttributeReplacements(arg):
90     dict = {}
91     for part in splitParts(arg):
92         m = _attr_re.match(part)
93         if not m:
94             raise TALError("Bad syntax in attributes:" + `part`)
95         name, expr = m.group(1, 2)
96         if dict.has_key(name):
97             raise TALError("Duplicate attribute name in attributes:" + `part`)
98         dict[name] = expr
99     return dict
101 def parseSubstitution(arg, position=(None, None)):
102     m = _subst_re.match(arg)
103     if not m:
104         raise TALError("Bad syntax in substitution text: " + `arg`, position)
105     key, expr = m.group(1, 2)
106     if not key:
107         key = "text"
108     return key, expr
110 def splitParts(arg):
111     # Break in pieces at undoubled semicolons and
112     # change double semicolons to singles:
113     import string
114     arg = string.replace(arg, ";;", "\0")
115     parts = string.split(arg, ';')
116     parts = map(lambda s, repl=string.replace: repl(s, "\0", ";"), parts)
117     if len(parts) > 1 and not string.strip(parts[-1]):
118         del parts[-1] # It ended in a semicolon
119     return parts
121 def isCurrentVersion(program):
122     version = getProgramVersion(program)
123     return version == TAL_VERSION
125 def getProgramMode(program):
126     version = getProgramVersion(program)
127     if (version == TAL_VERSION and isinstance(program[1], TupleType) and
128         len(program[1]) == 2):
129         opcode, mode = program[1]
130         if opcode == "mode":
131             return mode
132     return None
134 def getProgramVersion(program):
135     if (len(program) >= 2 and
136         isinstance(program[0], TupleType) and len(program[0]) == 2):
137         opcode, version = program[0]
138         if opcode == "version":
139             return version
140     return None
142 import cgi
143 def quote(s, escape=cgi.escape):
144     return '"%s"' % escape(s, 1)
145 del cgi