has_option(): Use the option name transform consistently.

Closes SF bug #561822.

Integrate the "code cleanup and general bug fix patch" (SF bug #545096),
contributed by Gustavo Niemeyer.  This is the portion of that patch that
does not add new functionality.
This commit is contained in:
Fred Drake 2002-09-27 15:33:11 +00:00
parent 46466b4c92
commit c2ff9051d2
1 changed files with 51 additions and 55 deletions

View File

@ -83,13 +83,12 @@ ConfigParser -- responsible for for parsing a list of
write the configuration state in .ini format write the configuration state in .ini format
""" """
import types
import re import re
__all__ = ["NoSectionError","DuplicateSectionError","NoOptionError", __all__ = ["NoSectionError","DuplicateSectionError","NoOptionError",
"InterpolationError","InterpolationDepthError","ParsingError", "InterpolationError","InterpolationDepthError","ParsingError",
"MissingSectionHeaderError","ConfigParser", "MissingSectionHeaderError","ConfigParser",
"MAX_INTERPOLATION_DEPTH"] "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
DEFAULTSECT = "DEFAULT" DEFAULTSECT = "DEFAULT"
@ -200,7 +199,7 @@ class ConfigParser:
The DEFAULT section is not acknowledged. The DEFAULT section is not acknowledged.
""" """
return section in self.sections() return section in self.__sections
def options(self, section): def options(self, section):
"""Return a list of option names for the given section name.""" """Return a list of option names for the given section name."""
@ -260,40 +259,39 @@ class ConfigParser:
The section DEFAULT is special. The section DEFAULT is special.
""" """
try:
sectdict = self.__sections[section].copy()
except KeyError:
if section == DEFAULTSECT:
sectdict = {}
else:
raise NoSectionError(section)
d = self.__defaults.copy() d = self.__defaults.copy()
d.update(sectdict) try:
d.update(self.__sections[section])
except KeyError:
if section != DEFAULTSECT:
raise NoSectionError(section)
# Update with the entry specific variables # Update with the entry specific variables
if vars is not None: if vars is not None:
d.update(vars) d.update(vars)
option = self.optionxform(option) option = self.optionxform(option)
try: try:
rawval = d[option] value = d[option]
except KeyError: except KeyError:
raise NoOptionError(option, section) raise NoOptionError(option, section)
if raw: if raw:
return rawval return value
return self._interpolate(section, option, value, d)
def _interpolate(self, section, option, rawval, vars):
# do the string interpolation # do the string interpolation
value = rawval # Make it a pretty variable name value = rawval
depth = 0 depth = MAX_INTERPOLATION_DEPTH
while depth < 10: # Loop through this until it's done while depth: # Loop through this until it's done
depth = depth + 1 depth -= 1
if value.find("%(") >= 0: if value.find("%(") != -1:
try: try:
value = value % d value = value % vars
except KeyError, key: except KeyError, key:
raise InterpolationError(key, option, section, rawval) raise InterpolationError(key, option, section, rawval)
else: else:
break break
if value.find("%(") >= 0: if value.find("%(") != -1:
raise InterpolationDepthError(option, section, rawval) raise InterpolationDepthError(option, section, rawval)
return value return value
@ -306,58 +304,59 @@ class ConfigParser:
def getfloat(self, section, option): def getfloat(self, section, option):
return self.__get(section, float, option) return self.__get(section, float, option)
_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
'0': False, 'no': False, 'false': False, 'off': False}
def getboolean(self, section, option): def getboolean(self, section, option):
states = {'1': 1, 'yes': 1, 'true': 1, 'on': 1,
'0': 0, 'no': 0, 'false': 0, 'off': 0}
v = self.get(section, option) v = self.get(section, option)
if not v.lower() in states: if v.lower() not in self._boolean_states:
raise ValueError, 'Not a boolean: %s' % v raise ValueError, 'Not a boolean: %s' % v
return states[v.lower()] return self._boolean_states[v.lower()]
def optionxform(self, optionstr): def optionxform(self, optionstr):
return optionstr.lower() return optionstr.lower()
def has_option(self, section, option): def has_option(self, section, option):
"""Check for the existence of a given option in a given section.""" """Check for the existence of a given option in a given section."""
if not section or section == "DEFAULT": if not section or section == DEFAULTSECT:
option = self.optionxform(option)
return option in self.__defaults return option in self.__defaults
elif not self.has_section(section): elif section not in self.__sections:
return 0 return 0
else: else:
option = self.optionxform(option) option = self.optionxform(option)
return option in self.__sections[section] return (option in self.__sections[section]
or option in self.__defaults)
def set(self, section, option, value): def set(self, section, option, value):
"""Set an option.""" """Set an option."""
if not section or section == "DEFAULT": if not section or section == DEFAULTSECT:
sectdict = self.__defaults sectdict = self.__defaults
else: else:
try: try:
sectdict = self.__sections[section] sectdict = self.__sections[section]
except KeyError: except KeyError:
raise NoSectionError(section) raise NoSectionError(section)
option = self.optionxform(option) sectdict[self.optionxform(option)] = value
sectdict[option] = value
def write(self, fp): def write(self, fp):
"""Write an .ini-format representation of the configuration state.""" """Write an .ini-format representation of the configuration state."""
if self.__defaults: if self.__defaults:
fp.write("[DEFAULT]\n") fp.write("[%s]\n" % DEFAULTSECT)
for (key, value) in self.__defaults.items(): for (key, value) in self.__defaults.items():
fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t'))) fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
fp.write("\n") fp.write("\n")
for section in self.sections(): for section in self.__sections:
fp.write("[" + section + "]\n") fp.write("[%s]\n" % section)
sectdict = self.__sections[section] for (key, value) in self.__sections[section].items():
for (key, value) in sectdict.items(): if key != "__name__":
if key == "__name__": fp.write("%s = %s\n" %
continue (key, str(value).replace('\n', '\n\t')))
fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
fp.write("\n") fp.write("\n")
def remove_option(self, section, option): def remove_option(self, section, option):
"""Remove an option.""" """Remove an option."""
if not section or section == "DEFAULT": if not section or section == DEFAULTSECT:
sectdict = self.__defaults sectdict = self.__defaults
else: else:
try: try:
@ -372,24 +371,22 @@ class ConfigParser:
def remove_section(self, section): def remove_section(self, section):
"""Remove a file section.""" """Remove a file section."""
if section in self.__sections: existed = section in self.__sections
if existed:
del self.__sections[section] del self.__sections[section]
return True return existed
else:
return False
# #
# Regular expressions for parsing section headers and options. Note a # Regular expressions for parsing section headers and options.
# slight semantic change from the previous version, because of the use #
# of \w, _ is allowed in section header names.
SECTCRE = re.compile( SECTCRE = re.compile(
r'\[' # [ r'\[' # [
r'(?P<header>[^]]+)' # very permissive! r'(?P<header>[^]]+)' # very permissive!
r'\]' # ] r'\]' # ]
) )
OPTCRE = re.compile( OPTCRE = re.compile(
r'(?P<option>[]\-[\w_.*,(){}]+)' # a lot of stuff found by IvL r'(?P<option>[^:=\s]+)' # very permissive!
r'[ \t]*(?P<vi>[:=])[ \t]*' # any number of space/tab, r'\s*(?P<vi>[:=])\s*' # any number of space/tab,
# followed by separator # followed by separator
# (either : or =), followed # (either : or =), followed
# by any # space/tab # by any # space/tab
@ -418,15 +415,13 @@ class ConfigParser:
# comment or blank line? # comment or blank line?
if line.strip() == '' or line[0] in '#;': if line.strip() == '' or line[0] in '#;':
continue continue
if line.split()[0].lower() == 'rem' \ if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": # no leading whitespace
and line[0] in "rR": # no leading whitespace
continue continue
# continuation line? # continuation line?
if line[0] in ' \t' and cursect is not None and optname: if line[0].isspace() and cursect is not None and optname:
value = line.strip() value = line.strip()
if value: if value:
k = self.optionxform(optname) cursect[optname] = "%s\n%s" % (cursect[optname], value)
cursect[k] = "%s\n%s" % (cursect[k], value)
# a section header or option header? # a section header or option header?
else: else:
# is it a section header? # is it a section header?
@ -454,13 +449,14 @@ class ConfigParser:
# ';' is a comment delimiter only if it follows # ';' is a comment delimiter only if it follows
# a spacing character # a spacing character
pos = optval.find(';') pos = optval.find(';')
if pos and optval[pos-1].isspace(): if pos != -1 and optval[pos-1].isspace():
optval = optval[:pos] optval = optval[:pos]
optval = optval.strip() optval = optval.strip()
# allow empty values # allow empty values
if optval == '""': if optval == '""':
optval = '' optval = ''
cursect[self.optionxform(optname)] = optval optname = self.optionxform(optname)
cursect[optname] = optval
else: else:
# a non-fatal parsing error occurred. set up the # a non-fatal parsing error occurred. set up the
# exception but keep going. the exception will be # exception but keep going. the exception will be