ConfigParser:

- ensure that option names in interpolations are handled by
  self.optionxform in the same way that other references to option
  names
- add tests, documentation
(closes SF bug #857881, patch #865455)
This commit is contained in:
Fred Drake 2004-05-18 02:25:51 +00:00
parent beddfcb6d0
commit bc12b01d83
3 changed files with 24 additions and 5 deletions

View File

@ -62,6 +62,13 @@ and \method{items()} methods. The values in \var{defaults} must be
appropriate for the \samp{\%()s} string interpolation. Note that appropriate for the \samp{\%()s} string interpolation. Note that
\var{__name__} is an intrinsic default; its value is the section name, \var{__name__} is an intrinsic default; its value is the section name,
and will override any value provided in \var{defaults}. and will override any value provided in \var{defaults}.
All option names used in interpolation will be passed through the
\method{optionxform()} method just like any other option name
reference. For example, using the default implementation of
\method{optionxform()} (which converts option names to lower case),
the values \samp{foo \%(bar)s} and \samp{foo \%(BAR)s} are
equivalent.
\end{classdesc} \end{classdesc}
\begin{classdesc}{SafeConfigParser}{\optional{defaults}} \begin{classdesc}{SafeConfigParser}{\optional{defaults}}
@ -271,6 +278,8 @@ option names case sensitive.
The \class{ConfigParser} class extends some methods of the The \class{ConfigParser} class extends some methods of the
\class{RawConfigParser} interface, adding some optional arguments. \class{RawConfigParser} interface, adding some optional arguments.
The \class{SafeConfigParser} class implements the same extended
interface.
\begin{methoddesc}{get}{section, option\optional{, raw\optional{, vars}}} \begin{methoddesc}{get}{section, option\optional{, raw\optional{, vars}}}
Get an \var{option} value for the named \var{section}. All the Get an \var{option} value for the named \var{section}. All the

View File

@ -555,6 +555,7 @@ class ConfigParser(RawConfigParser):
while depth: # Loop through this until it's done while depth: # Loop through this until it's done
depth -= 1 depth -= 1
if "%(" in value: if "%(" in value:
value = self._KEYCRE.sub(self._interpolation_replace, value)
try: try:
value = value % vars value = value % vars
except KeyError, e: except KeyError, e:
@ -566,6 +567,15 @@ class ConfigParser(RawConfigParser):
raise InterpolationDepthError(option, section, rawval) raise InterpolationDepthError(option, section, rawval)
return value return value
_KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
def _interpolation_replace(self, match):
s = match.group(1)
if s is None:
return match.group()
else:
return "%%(%s)s" % self.optionxform(s)
class SafeConfigParser(ConfigParser): class SafeConfigParser(ConfigParser):
@ -598,7 +608,7 @@ class SafeConfigParser(ConfigParser):
if m is None: if m is None:
raise InterpolationSyntaxError(option, section, raise InterpolationSyntaxError(option, section,
"bad interpolation variable reference %r" % rest) "bad interpolation variable reference %r" % rest)
var = m.group(1) var = self.optionxform(m.group(1))
rest = rest[m.end():] rest = rest[m.end():]
try: try:
v = map[var] v = map[var]

View File

@ -222,11 +222,11 @@ class TestCaseBase(unittest.TestCase):
"with11=%(with10)s\n" "with11=%(with10)s\n"
"with10=%(with9)s\n" "with10=%(with9)s\n"
"with9=%(with8)s\n" "with9=%(with8)s\n"
"with8=%(with7)s\n" "with8=%(With7)s\n"
"with7=%(with6)s\n" "with7=%(WITH6)s\n"
"with6=%(with5)s\n" "with6=%(with5)s\n"
"with5=%(with4)s\n" "With5=%(with4)s\n"
"with4=%(with3)s\n" "WITH4=%(with3)s\n"
"with3=%(with2)s\n" "with3=%(with2)s\n"
"with2=%(with1)s\n" "with2=%(with1)s\n"
"with1=with\n" "with1=with\n"