[Zope-Checkins] CVS: Zope/lib/python/ZConfig - Substitution.py:1.3.6.1 ApacheStyle.py:1.1.4.3 Config.py:1.2.4.3 Context.py:1.1.4.4 __init__.py:1.1.4.2 Interpolation.py:NONE
Chris McDonough
chrism@zope.com
Fri, 15 Nov 2002 20:26:48 -0500
Update of /cvs-repository/Zope/lib/python/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv25541
Modified Files:
Tag: chrism-install-branch
ApacheStyle.py Config.py Context.py __init__.py
Added Files:
Tag: chrism-install-branch
Substitution.py
Removed Files:
Tag: chrism-install-branch
Interpolation.py
Log Message:
Updating chrism-install-branch ZConfig to HEAD.
=== Added File Zope/lib/python/ZConfig/Substitution.py ===
"""Substitution support for ZConfig values."""
class SubstitutionError(Exception):
"""Base exception for string substitution errors."""
def __init__(self, msg, context):
self.message = msg
self.context = context
def __str__(self):
return self.message
class SubstitutionSyntaxError(SubstitutionError):
"""Raised when interpolation source text contains syntactical errors."""
def __init__(self, msg, context):
if context is not None:
context = context[:]
SubstitutionError.__init__(self, msg, context)
class SubstitutionRecursionError(SubstitutionError):
"""Raised when a nested interpolation is recursive."""
def __init__(self, name, context):
self.name = name
msg = ("recursion on %s; current context:\n%s"
% (repr(name), ", ".join(context)))
SubstitutionError.__init__(self, msg, 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 substitute(s, section):
"""Interpolate variables from `section` into `s`."""
if '$' in s:
accum = []
_interp(accum, s, section, None)
s = ''.join(accum)
return s
def _interp(accum, rest, section, context):
while 1:
i = rest.find("$")
if i < 0:
accum.append(rest)
break
accum.append(rest[:i])
rest = rest[i+1:]
if not rest:
accum.append("$")
break
if rest[0] == "$":
accum.append("$")
rest = rest[1:]
elif rest[0] == "{":
rest = rest[1:]
m = _name_match(rest[:])
if not m:
raise SubstitutionSyntaxError("'${' not followed by name",
context)
name = m.group(0)
length = len(name)
if rest[length:length+1] != "}":
raise SubstitutionSyntaxError(
"'${%s' not followed by '}'" % name, context)
v = section.get(name)
if v is None:
parent = getattr(section, "container", None)
while parent is not None:
v = parent.get(name)
if v is not None:
break
parent = getattr(parent, "container", None)
else:
v = ""
if "$" in v and context:
if name in context:
raise SubstitutionRecursionError(name, context)
_interp(accum, v, section, context + [name])
else:
accum.append(v)
rest = rest[length+1:]
else:
m = _name_match(rest)
if not m:
accum.append("$")
continue
name = m.group(0)
v = section.get(name, "")
if "$" in v and context:
if name in context:
raise SubstitutionRecursionError(name, context)
_interp(accum, v, section, context + [name])
else:
accum.append(v)
rest = rest[len(name):]
import re
_name_match = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*").match
del re
=== Zope/lib/python/ZConfig/ApacheStyle.py 1.1.4.2 => 1.1.4.3 ===
--- Zope/lib/python/ZConfig/ApacheStyle.py:1.1.4.2 Sat Oct 26 15:51:46 2002
+++ Zope/lib/python/ZConfig/ApacheStyle.py Fri Nov 15 20:26:17 2002
@@ -32,6 +32,7 @@
if type.lower() != section.type:
raise ConfigurationSyntaxError(
"unbalanced section end", url, lineno)
+ section.finish()
section = stack.pop()
continue
if line[0] == "<":
=== Zope/lib/python/ZConfig/Config.py 1.2.4.2 => 1.2.4.3 ===
--- Zope/lib/python/ZConfig/Config.py:1.2.4.2 Sat Oct 26 15:51:46 2002
+++ Zope/lib/python/ZConfig/Config.py Fri Nov 15 20:26:17 2002
@@ -3,7 +3,8 @@
from Common import *
class Configuration:
- def __init__(self, type, name, url):
+ def __init__(self, container, type, name, url):
+ self.container = container
self.type = type
self.name = name or None
self.delegate = None
@@ -25,6 +26,9 @@
else:
return "<%s at 0x%x>" % (classname, id(self))
+ def finish(self):
+ pass
+
def setDelegate(self, section):
if self.delegate is not None:
raise ConfigurationError("cannot modify delegation")
@@ -198,9 +202,9 @@
class ImportingConfiguration(Configuration):
- def __init__(self, *args):
+ def __init__(self, url):
self._imports = []
- Configuration.__init__(self, *args)
+ Configuration.__init__(self, None, None, None, url)
def addImport(self, section):
self._imports.append(section)
=== Zope/lib/python/ZConfig/Context.py 1.1.4.3 => 1.1.4.4 ===
--- Zope/lib/python/ZConfig/Context.py:1.1.4.3 Sat Oct 26 15:51:46 2002
+++ Zope/lib/python/ZConfig/Context.py Fri Nov 15 20:26:17 2002
@@ -17,19 +17,20 @@
self._named_sections = {} # name -> Configuration
self._needed_names = {} # name -> [needy Configuration, ...]
self._current_imports = []
+ self._all_sections = []
# subclass-support API
def createImportedSection(self, section, url):
- return ImportingConfiguration(None, None, url)
+ return ImportingConfiguration(url)
def createNestedSection(self, section, type, name, delegatename):
if name:
name = name.lower()
- return Configuration(type.lower(), name, section.url)
+ return Configuration(section, type.lower(), name, section.url)
def createToplevelSection(self, url):
- return ImportingConfiguration(None, None, url)
+ return ImportingConfiguration(url)
def getDelegateType(self, type):
# Applications must provide delegation typing information by
@@ -47,11 +48,29 @@
if os.path.exists(url):
url = "file://" + urllib.pathname2url(os.path.abspath(url))
top = self.createToplevelSection(url)
+ self._all_sections.append(top)
self._imports = [top]
self._parse_url(url, top)
self._finish()
return top
+ def loadfile(self, file, url=None):
+ if not url:
+ name = getattr(file, "name", None)
+ if name and name[0] != "<" and name[-1] != ">":
+ url = "file://" + urllib.pathname2url(os.path.abspath(name))
+ top = self.createToplevelSection(url)
+ self._all_sections.append(top)
+ self._imports = [top]
+ self._current_imports.append(top)
+ try:
+ self.parse(file, top, url)
+ finally:
+ del self._current_imports[-1]
+ self._finish()
+ return top
+
+
# interface for parser
def importConfiguration(self, section, url):
@@ -59,6 +78,7 @@
if config.url == url:
return config
newsect = self.createImportedSection(section, url)
+ self._all_sections.append(newsect)
self._imports.append(newsect)
section.addImport(newsect)
self._parse_url(url, newsect)
@@ -88,6 +108,7 @@
raise ConfigurationError(
"named section cannot change type")
newsect = self.createNestedSection(section, type, name, delegatename)
+ self._all_sections.append(newsect)
if delegatename:
# The knitting together of the delegation graph needs this.
try:
@@ -144,3 +165,17 @@
referrer.type, type)
referrer.setDelegate(section)
self._needed_names = None
+ # Now "finish" the sections, making sure we close inner
+ # sections before outer sections. We really should order
+ # these better, but for now, "finish" all sections that have
+ # no delegates first, then those that have them. This is not
+ # enough to guarantee that delegates are finished before their
+ # users.
+ self._all_sections.reverse()
+ for sect in self._all_sections:
+ if sect.delegate is None:
+ sect.finish()
+ for sect in self._all_sections:
+ if sect.delegate is not None:
+ sect.finish()
+ self._all_sections = None
=== Zope/lib/python/ZConfig/__init__.py 1.1.4.1 => 1.1.4.2 ===
--- Zope/lib/python/ZConfig/__init__.py:1.1.4.1 Thu Oct 10 14:29:12 2002
+++ Zope/lib/python/ZConfig/__init__.py Fri Nov 15 20:26:17 2002
@@ -19,3 +19,7 @@
def load(url):
import Context
return Context.Context().load(url)
+
+def loadfile(file, url=None):
+ import Context
+ return Context.Context().loadfile(file, url)
=== Removed File Zope/lib/python/ZConfig/Interpolation.py ===