[Zope-Checkins] CVS: Packages/ZConfig - Substitution.py:1.11
Fred L. Drake, Jr.
fred@zope.com
Wed, 4 Dec 2002 20:09:54 -0500
Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv11821
Modified Files:
Substitution.py
Log Message:
Be more strict when scanning the source text: If '$' is not followed
by '$' or a name, raise an exception. (Previously this used '' for
the replacement text.)
=== Packages/ZConfig/Substitution.py 1.10 => 1.11 ===
--- Packages/ZConfig/Substitution.py:1.10 Wed Dec 4 17:48:31 2002
+++ Packages/ZConfig/Substitution.py Wed Dec 4 20:09:53 2002
@@ -5,8 +5,8 @@
except NameError:
False = 0
-class SubstitutionSyntaxError(Exception):
- """Raised when interpolation source text contains syntactical errors."""
+class SubstitutionError(Exception):
+ """Base class for exceptions raised by ZConfig.Substitution."""
def __init__(self, msg):
self.message = msg
@@ -14,14 +14,35 @@
def __str__(self):
return self.message
+class SubstitutionSyntaxError(SubstitutionError):
+ """Raised when interpolation source text contains syntactical errors."""
+
+class SubstitutionReplacementError(SubstitutionError, LookupError):
+ """Raised when no replacement is available for a reference."""
+
+ def __init__(self, source, name):
+ self.source = source
+ self.name = name
+ SubstitutionError.__init__(
+ self, "no replacement for " + `name`)
+
def substitute(s, mapping):
"""Interpolate variables from `section` into `s`."""
if "$" in s:
- accum = []
- _interp(accum, s, mapping)
- s = ''.join(accum)
- return s
+ result = ''
+ rest = s
+ while rest:
+ p, name, rest = _split(rest)
+ result += p
+ if name:
+ v = mapping.get(name)
+ if v is None:
+ raise SubstitutionReplacementError(s, name)
+ result += v
+ return result
+ else:
+ return s
def isname(s):
@@ -33,18 +54,6 @@
return False
-def _interp(accum, rest, mapping):
- while 1:
- s, name, rest = _split(rest)
- if s:
- accum.append(s)
- if name:
- v = mapping.get(name, "")
- accum.append(v)
- if not rest:
- return
-
-
def _split(s):
# Return a triple: prefix, name, suffix
# - prefix is text that can be used literally in the result (may be '')
@@ -55,7 +64,8 @@
i = s.find("$")
c = s[i+1:i+2]
if c == "":
- return s, None, None
+ raise SubstitutionSyntaxError(
+ "illegal lone '$' at end of source")
if c == "$":
return s[:i+1], None, s[i+2:]
prefix = s[:i]
@@ -71,7 +81,8 @@
else:
m = _name_match(s, i+1)
if not m:
- return prefix + "$", None, s[i+1:]
+ raise SubstitutionSyntaxError(
+ "'$' not followed by '$' or name")
name = m.group(0)
i = m.end()
return prefix, name.lower(), s[i:]