[Zope-CVS] CVS: Packages/ZConfig - Interpolation.py:1.2
Fred L. Drake, Jr.
fdrake@acm.org
Wed, 9 Oct 2002 12:30:32 -0400
Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv4882
Modified Files:
Interpolation.py
Log Message:
Proposed interface for nested interpolation.
=== Packages/ZConfig/Interpolation.py 1.1 => 1.2 ===
--- Packages/ZConfig/Interpolation.py:1.1 Wed Oct 9 11:33:53 2002
+++ Packages/ZConfig/Interpolation.py Wed Oct 9 12:30:31 2002
@@ -3,23 +3,54 @@
XXX document syntax here
"""
+class InterpolationError(Exception):
+ """Base exception for string interpolation errors."""
-class InterpolationSyntaxError(Exception):
+class InterpolationSyntaxError(InterpolationError):
"""Raised when interpolation source text contains syntactical errors."""
- pass
+
+ def __init__(self, msg, context):
+ self.message = msg
+ if context is None:
+ self.context = context
+ else:
+ self.context = context[:]
+ InterpolationError.__init__(self, msg, self.context)
+
+class InterpolationRecursionError(InterpolationError):
+ """Raised when a nested interpolation is recursive."""
+
+ def __init__(self, name, context):
+ self.name = name
+ self.context = context[:]
+ self.message = ("recursion on %s; current context:\n%s"
+ % (repr(name), ", ".join(context)))
+ InterpolationError.__init__(self, name, self.context)
+
+
+def get(section, name, default=None):
+ # XXX should this interpolate from default if that's what's used?
+ missing = []
+ s = section.get(name, missing)
+ if s is missing:
+ return default
+ if "$" in s:
+ accum = []
+ _interp(accum, s, section, [name])
+ s = ''.join(accum)
+ return s
def interpolate(s, section):
"""Interpolate variables from `section` into `s`."""
if '$' in s:
accum = []
- _interp(accum, s, section)
- return ''.join(accum)
- else:
- return s
+ _interp(accum, s, section, None)
+ s = ''.join(accum)
+ return s
-def _interp(accum, rest, section):
+def _interp(accum, rest, section, context):
while 1:
i = rest.find("$")
if i < 0:
@@ -28,7 +59,7 @@
accum.append(rest[:i])
rest = rest[i+1:]
if not rest:
- raise InterpolationSyntaxError("lone '$' at end of text")
+ raise InterpolationSyntaxError("lone '$' at end of text", context)
if rest[0] == "$":
accum.append("$")
rest = rest[1:]
@@ -36,20 +67,34 @@
rest = rest[1:]
m = _name_match(rest[:])
if not m:
- raise InterpolationSyntaxError("'${' not followed by name")
+ raise InterpolationSyntaxError("'${' not followed by name",
+ context)
name = m.group(0)
length = len(name)
if rest[length:length+1] != "}":
- raise InterpolationSyntaxError("'${%s' not followed by '}'"
- % name)
- accum.append(section.get(name, ""))
+ raise InterpolationSyntaxError(
+ "'${%s' not followed by '}'" % name, context)
+ v = section.get(name, "")
+ if "$" in v and context:
+ if name in context:
+ raise InterpolationRecursionError(name, context)
+ _interp(accum, v, section, context + [name])
+ else:
+ accum.append(v)
rest = rest[length+1:]
else:
m = _name_match(rest)
if not m:
- raise InterpolationSyntaxError("'$' not followed by name")
+ raise InterpolationSyntaxError("'$' not followed by name",
+ context)
name = m.group(0)
- accum.append(section.get(name, ""))
+ v = section.get(name, "")
+ if "$" in v and context:
+ if name in context:
+ raise InterpolationRecursionError(name, context)
+ _interp(accum, v, section, context + [name])
+ else:
+ accum.append(v)
rest = rest[len(name):]