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