Skip to content

Commit ac37ba0

Browse files
committed
Issue python#21159: Improve message in configparser.InterpolationMissingOptionError.
Patch from Łukasz Langa.
1 parent 4ce4f97 commit ac37ba0

File tree

3 files changed

+21
-18
lines changed

3 files changed

+21
-18
lines changed

Lib/configparser.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,9 @@ class InterpolationMissingOptionError(InterpolationError):
241241
"""A string substitution required a setting which was not available."""
242242

243243
def __init__(self, option, section, rawval, reference):
244-
msg = ("Bad value substitution:\n"
245-
"\tsection: [%s]\n"
246-
"\toption : %s\n"
247-
"\tkey : %s\n"
248-
"\trawval : %s\n"
249-
% (section, option, reference, rawval))
244+
msg = ("Bad value substitution: option {!r} in section {!r} contains "
245+
"an interpolation key {!r} which is not a valid option name. "
246+
"Raw value: {!r}".format(option, section, reference, rawval))
250247
InterpolationError.__init__(self, option, section, msg)
251248
self.reference = reference
252249
self.args = (option, section, rawval, reference)
@@ -264,11 +261,11 @@ class InterpolationDepthError(InterpolationError):
264261
"""Raised when substitutions are nested too deeply."""
265262

266263
def __init__(self, option, section, rawval):
267-
msg = ("Value interpolation too deeply recursive:\n"
268-
"\tsection: [%s]\n"
269-
"\toption : %s\n"
270-
"\trawval : %s\n"
271-
% (section, option, rawval))
264+
msg = ("Recursion limit exceeded in value substitution: option {!r} "
265+
"in section {!r} contains an interpolation key which "
266+
"cannot be substituted in {} steps. Raw value: {!r}"
267+
"".format(option, section, MAX_INTERPOLATION_DEPTH,
268+
rawval))
272269
InterpolationError.__init__(self, option, section, msg)
273270
self.args = (option, section, rawval)
274271

@@ -384,8 +381,9 @@ def before_set(self, parser, section, option, value):
384381

385382
def _interpolate_some(self, parser, option, accum, rest, section, map,
386383
depth):
384+
rawval = parser.get(section, option, raw=True, fallback=rest)
387385
if depth > MAX_INTERPOLATION_DEPTH:
388-
raise InterpolationDepthError(option, section, rest)
386+
raise InterpolationDepthError(option, section, rawval)
389387
while rest:
390388
p = rest.find("%")
391389
if p < 0:
@@ -410,7 +408,7 @@ def _interpolate_some(self, parser, option, accum, rest, section, map,
410408
v = map[var]
411409
except KeyError:
412410
raise InterpolationMissingOptionError(
413-
option, section, rest, var)
411+
option, section, rawval, var)
414412
if "%" in v:
415413
self._interpolate_some(parser, option, accum, v,
416414
section, map, depth + 1)
@@ -444,8 +442,9 @@ def before_set(self, parser, section, option, value):
444442

445443
def _interpolate_some(self, parser, option, accum, rest, section, map,
446444
depth):
445+
rawval = parser.get(section, option, raw=True, fallback=rest)
447446
if depth > MAX_INTERPOLATION_DEPTH:
448-
raise InterpolationDepthError(option, section, rest)
447+
raise InterpolationDepthError(option, section, rawval)
449448
while rest:
450449
p = rest.find("$")
451450
if p < 0:
@@ -482,7 +481,7 @@ def _interpolate_some(self, parser, option, accum, rest, section, map,
482481
"More than one ':' found: %r" % (rest,))
483482
except (KeyError, NoSectionError, NoOptionError):
484483
raise InterpolationMissingOptionError(
485-
option, section, rest, ":".join(path))
484+
option, section, rawval, ":".join(path))
486485
if "$" in v:
487486
self._interpolate_some(parser, opt, accum, v, sect,
488487
dict(parser.items(sect, raw=True)),

Lib/test/test_configparser.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,8 @@ def test_interpolation(self):
847847
"something with lots of interpolation (10 steps)")
848848
e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11")
849849
if self.interpolation == configparser._UNSET:
850-
self.assertEqual(e.args, ("bar11", "Foo", "%(with1)s"))
850+
self.assertEqual(e.args, ("bar11", "Foo",
851+
"something %(with11)s lots of interpolation (11 steps)"))
851852
elif isinstance(self.interpolation, configparser.LegacyInterpolation):
852853
self.assertEqual(e.args, ("bar11", "Foo",
853854
"something %(with11)s lots of interpolation (11 steps)"))
@@ -861,7 +862,7 @@ def test_interpolation_missing_value(self):
861862
self.assertEqual(e.option, "name")
862863
if self.interpolation == configparser._UNSET:
863864
self.assertEqual(e.args, ('name', 'Interpolation Error',
864-
'', 'reference'))
865+
'%(reference)s', 'reference'))
865866
elif isinstance(self.interpolation, configparser.LegacyInterpolation):
866867
self.assertEqual(e.args, ('name', 'Interpolation Error',
867868
'%(reference)s', 'reference'))
@@ -1177,7 +1178,7 @@ def test_strange_options(self):
11771178
with self.assertRaises(exception_class) as cm:
11781179
cf['interpolated']['$trying']
11791180
self.assertEqual(cm.exception.reference, 'dollars:${sick')
1180-
self.assertEqual(cm.exception.args[2], '}') #rawval
1181+
self.assertEqual(cm.exception.args[2], '${dollars:${sick}}') #rawval
11811182

11821183
def test_case_sensitivity_basic(self):
11831184
ini = textwrap.dedent("""

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ Core and Builtins
7575
Library
7676
-------
7777

78+
- Issue #21159: Improve message in configparser.InterpolationMissingOptionError.
79+
Patch from Łukasz Langa.
80+
7881
- Issue #23888: Handle fractional time in cookie expiry. Patch by ssh.
7982

8083
- Issue #23004: mock_open() now reads binary data correctly when the type of

0 commit comments

Comments
 (0)