Fix #19546: onfigparser exceptions expose implementation details. Patch by Claudiu Popa.

This commit is contained in:
Łukasz Langa 2014-09-04 01:36:33 -07:00
parent f29468118b
commit 949053bff2
3 changed files with 62 additions and 6 deletions

View File

@ -410,7 +410,7 @@ class BasicInterpolation(Interpolation):
v = map[var] v = map[var]
except KeyError: except KeyError:
raise InterpolationMissingOptionError( raise InterpolationMissingOptionError(
option, section, rest, var) option, section, rest, var) from None
if "%" in v: if "%" in v:
self._interpolate_some(parser, option, accum, v, self._interpolate_some(parser, option, accum, v,
section, map, depth + 1) section, map, depth + 1)
@ -482,7 +482,7 @@ class ExtendedInterpolation(Interpolation):
"More than one ':' found: %r" % (rest,)) "More than one ':' found: %r" % (rest,))
except (KeyError, NoSectionError, NoOptionError): except (KeyError, NoSectionError, NoOptionError):
raise InterpolationMissingOptionError( raise InterpolationMissingOptionError(
option, section, rest, ":".join(path)) option, section, rest, ":".join(path)) from None
if "$" in v: if "$" in v:
self._interpolate_some(parser, opt, accum, v, sect, self._interpolate_some(parser, opt, accum, v, sect,
dict(parser.items(sect, raw=True)), dict(parser.items(sect, raw=True)),
@ -515,7 +515,7 @@ class LegacyInterpolation(Interpolation):
value = value % vars value = value % vars
except KeyError as e: except KeyError as e:
raise InterpolationMissingOptionError( raise InterpolationMissingOptionError(
option, section, rawval, e.args[0]) option, section, rawval, e.args[0]) from None
else: else:
break break
if value and "%(" in value: if value and "%(" in value:
@ -647,7 +647,7 @@ class RawConfigParser(MutableMapping):
try: try:
opts = self._sections[section].copy() opts = self._sections[section].copy()
except KeyError: except KeyError:
raise NoSectionError(section) raise NoSectionError(section) from None
opts.update(self._defaults) opts.update(self._defaults)
return list(opts.keys()) return list(opts.keys())
@ -876,7 +876,7 @@ class RawConfigParser(MutableMapping):
try: try:
sectdict = self._sections[section] sectdict = self._sections[section]
except KeyError: except KeyError:
raise NoSectionError(section) raise NoSectionError(section) from None
sectdict[self.optionxform(option)] = value sectdict[self.optionxform(option)] = value
def write(self, fp, space_around_delimiters=True): def write(self, fp, space_around_delimiters=True):
@ -917,7 +917,7 @@ class RawConfigParser(MutableMapping):
try: try:
sectdict = self._sections[section] sectdict = self._sections[section]
except KeyError: except KeyError:
raise NoSectionError(section) raise NoSectionError(section) from None
option = self.optionxform(option) option = self.optionxform(option)
existed = option in sectdict existed = option in sectdict
if existed: if existed:

View File

@ -1763,6 +1763,58 @@ class InlineCommentStrippingTestCase(unittest.TestCase):
self.assertEqual(s['k2'], 'v2') self.assertEqual(s['k2'], 'v2')
self.assertEqual(s['k3'], 'v3;#//still v3# and still v3') self.assertEqual(s['k3'], 'v3;#//still v3# and still v3')
class ExceptionContextTestCase(unittest.TestCase):
""" Test that implementation details doesn't leak
through raising exceptions. """
def test_get_basic_interpolation(self):
parser = configparser.ConfigParser()
parser.read_string("""
[Paths]
home_dir: /Users
my_dir: %(home_dir1)s/lumberjack
my_pictures: %(my_dir)s/Pictures
""")
cm = self.assertRaises(configparser.InterpolationMissingOptionError)
with cm:
parser.get('Paths', 'my_dir')
self.assertIs(cm.exception.__suppress_context__, True)
def test_get_extended_interpolation(self):
parser = configparser.ConfigParser(
interpolation=configparser.ExtendedInterpolation())
parser.read_string("""
[Paths]
home_dir: /Users
my_dir: ${home_dir1}/lumberjack
my_pictures: ${my_dir}/Pictures
""")
cm = self.assertRaises(configparser.InterpolationMissingOptionError)
with cm:
parser.get('Paths', 'my_dir')
self.assertIs(cm.exception.__suppress_context__, True)
def test_missing_options(self):
parser = configparser.ConfigParser()
parser.read_string("""
[Paths]
home_dir: /Users
""")
with self.assertRaises(configparser.NoSectionError) as cm:
parser.options('test')
self.assertIs(cm.exception.__suppress_context__, True)
def test_missing_section(self):
config = configparser.ConfigParser()
with self.assertRaises(configparser.NoSectionError) as cm:
config.set('Section1', 'an_int', '15')
self.assertIs(cm.exception.__suppress_context__, True)
def test_remove_option(self):
config = configparser.ConfigParser()
with self.assertRaises(configparser.NoSectionError) as cm:
config.remove_option('Section1', 'an_int')
self.assertIs(cm.exception.__suppress_context__, True)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -129,6 +129,10 @@ Core and Builtins
Library Library
------- -------
- Issue #19546: configparser exceptions no longer expose implementation details.
Chained KeyErrors are removed, which leads to cleaner tracebacks. Patch by
Claudiu Popa.
- Issue #22051: turtledemo no longer reloads examples to re-run them. - Issue #22051: turtledemo no longer reloads examples to re-run them.
Initialization of variables and gui setup should be done in main(), Initialization of variables and gui setup should be done in main(),
which is called each time a demo is run, but not on import. which is called each time a demo is run, but not on import.