Allow spaces in section names.
Do not expose the __name__ when reporting the list of options available for a section since that is for internal use. This closes SourceForge bug #115357. Additionally, define InterpolationDepthError and MAX_INTERPOLATION_DEPTH. The exception is raised by get*() when value interpolation cannot be completed within the defined recursion limit. The constant is only informative; changing it will not affect the allowed depth. Fix the exit from get() so that None is not returned if the depth is met or exceeded; either return the value of raise InterpolationDepthError.
This commit is contained in:
parent
6372fe1e40
commit
2a37f9f862
|
@ -91,6 +91,8 @@ import re
|
||||||
|
|
||||||
DEFAULTSECT = "DEFAULT"
|
DEFAULTSECT = "DEFAULT"
|
||||||
|
|
||||||
|
MAX_INTERPOLATION_DEPTH = 10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# exception classes
|
# exception classes
|
||||||
|
@ -130,15 +132,16 @@ class InterpolationError(Error):
|
||||||
self.option = option
|
self.option = option
|
||||||
self.section = section
|
self.section = section
|
||||||
|
|
||||||
class MissingSectionHeaderError(Error):
|
class InterpolationDepthError(Error):
|
||||||
def __init__(self, filename, lineno, line):
|
def __init__(self, option, section, rawval):
|
||||||
Error.__init__(
|
Error.__init__(self,
|
||||||
self,
|
"Value interpolation too deeply recursive:\n"
|
||||||
'File contains no section headers.\nfile: %s, line: %d\n%s' %
|
"\tsection: [%s]\n"
|
||||||
(filename, lineno, line))
|
"\toption : %s\n"
|
||||||
self.filename = filename
|
"\trawval : %s\n"
|
||||||
self.lineno = lineno
|
% (section, option, rawval))
|
||||||
self.line = line
|
self.option = option
|
||||||
|
self.section = section
|
||||||
|
|
||||||
class ParsingError(Error):
|
class ParsingError(Error):
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
|
@ -150,6 +153,16 @@ class ParsingError(Error):
|
||||||
self.errors.append((lineno, line))
|
self.errors.append((lineno, line))
|
||||||
self._msg = self._msg + '\n\t[line %2d]: %s' % (lineno, line)
|
self._msg = self._msg + '\n\t[line %2d]: %s' % (lineno, line)
|
||||||
|
|
||||||
|
class MissingSectionHeaderError(ParsingError):
|
||||||
|
def __init__(self, filename, lineno, line):
|
||||||
|
Error.__init__(
|
||||||
|
self,
|
||||||
|
'File contains no section headers.\nfile: %s, line: %d\n%s' %
|
||||||
|
(filename, lineno, line))
|
||||||
|
self.filename = filename
|
||||||
|
self.lineno = lineno
|
||||||
|
self.line = line
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigParser:
|
class ConfigParser:
|
||||||
|
@ -183,7 +196,7 @@ class ConfigParser:
|
||||||
|
|
||||||
The DEFAULT section is not acknowledged.
|
The DEFAULT section is not acknowledged.
|
||||||
"""
|
"""
|
||||||
return self.__sections.has_key(section)
|
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."""
|
||||||
|
@ -192,15 +205,13 @@ class ConfigParser:
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise NoSectionError(section)
|
raise NoSectionError(section)
|
||||||
opts.update(self.__defaults)
|
opts.update(self.__defaults)
|
||||||
|
if opts.has_key('__name__'):
|
||||||
|
del opts['__name__']
|
||||||
return opts.keys()
|
return opts.keys()
|
||||||
|
|
||||||
def has_option(self, section, option):
|
def has_option(self, section, option):
|
||||||
"""Return whether the given section has the given option."""
|
"""Return whether the given section has the given option."""
|
||||||
try:
|
return option in self.options(section)
|
||||||
opts = self.__sections[section]
|
|
||||||
except KeyError:
|
|
||||||
raise NoSectionError(section)
|
|
||||||
return opts.has_key(option)
|
|
||||||
|
|
||||||
def read(self, filenames):
|
def read(self, filenames):
|
||||||
"""Read and parse a filename or a list of filenames.
|
"""Read and parse a filename or a list of filenames.
|
||||||
|
@ -266,10 +277,11 @@ class ConfigParser:
|
||||||
rawval = d[option]
|
rawval = d[option]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise NoOptionError(option, section)
|
raise NoOptionError(option, section)
|
||||||
# do the string interpolation
|
|
||||||
if raw:
|
if raw:
|
||||||
return rawval
|
return rawval
|
||||||
|
|
||||||
|
# do the string interpolation
|
||||||
value = rawval # Make it a pretty variable name
|
value = rawval # Make it a pretty variable name
|
||||||
depth = 0
|
depth = 0
|
||||||
while depth < 10: # Loop through this until it's done
|
while depth < 10: # Loop through this until it's done
|
||||||
|
@ -280,7 +292,10 @@ class ConfigParser:
|
||||||
except KeyError, key:
|
except KeyError, key:
|
||||||
raise InterpolationError(key, option, section, rawval)
|
raise InterpolationError(key, option, section, rawval)
|
||||||
else:
|
else:
|
||||||
return value
|
break
|
||||||
|
if value.find("%(") >= 0:
|
||||||
|
raise InterpolationDepthError(option, section, rawval)
|
||||||
|
return value
|
||||||
|
|
||||||
def __get(self, section, conv, option):
|
def __get(self, section, conv, option):
|
||||||
return conv(self.get(section, option))
|
return conv(self.get(section, option))
|
||||||
|
@ -365,7 +380,7 @@ class ConfigParser:
|
||||||
# of \w, _ is allowed in section header names.
|
# of \w, _ is allowed in section header names.
|
||||||
SECTCRE = re.compile(
|
SECTCRE = re.compile(
|
||||||
r'\[' # [
|
r'\[' # [
|
||||||
r'(?P<header>[-\w_.*,(){}]+)' # a lot of stuff found by IvL
|
r'(?P<header>[-\w_.*,(){} ]+)' # a lot of stuff found by IvL
|
||||||
r'\]' # ]
|
r'\]' # ]
|
||||||
)
|
)
|
||||||
OPTCRE = re.compile(
|
OPTCRE = re.compile(
|
||||||
|
|
Loading…
Reference in New Issue