Merged solution for #11858 from 3.2.
diff --git a/Lib/configparser.py b/Lib/configparser.py
index fe28b13..611d699 100644
--- a/Lib/configparser.py
+++ b/Lib/configparser.py
@@ -482,17 +482,17 @@
if m is None:
raise InterpolationSyntaxError(option, section,
"bad interpolation variable reference %r" % rest)
- path = parser.optionxform(m.group(1)).split(':')
+ path = m.group(1).split(':')
rest = rest[m.end():]
sect = section
opt = option
try:
if len(path) == 1:
- opt = path[0]
+ opt = parser.optionxform(path[0])
v = map[opt]
elif len(path) == 2:
sect = path[0]
- opt = path[1]
+ opt = parser.optionxform(path[1])
v = parser.get(sect, opt, raw=True)
else:
raise InterpolationSyntaxError(
@@ -1057,6 +1057,8 @@
if not optname:
e = self._handle_error(e, fpname, lineno, line)
optname = self.optionxform(optname.rstrip())
+ if hasattr(self, '__ping__'):
+ import pdb; pdb.set_trace()
if (self._strict and
(sectname, optname) in elements_added):
raise DuplicateOptionError(sectname, optname,
diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py
index a29da93..03e400d 100644
--- a/Lib/test/test_configparser.py
+++ b/Lib/test/test_configparser.py
@@ -20,10 +20,16 @@
def values(self):
return [i[1] for i in self.items()]
- def iteritems(self): return iter(self.items())
- def iterkeys(self): return iter(self.keys())
+ def iteritems(self):
+ return iter(self.items())
+
+ def iterkeys(self):
+ return iter(self.keys())
+
+ def itervalues(self):
+ return iter(self.values())
+
__iter__ = iterkeys
- def itervalues(self): return iter(self.values())
class CfgParserTestCaseClass(unittest.TestCase):
@@ -986,6 +992,14 @@
config_class = configparser.ConfigParser
interpolation = configparser.ExtendedInterpolation()
default_section = 'common'
+ strict = True
+
+ def fromstring(self, string, defaults=None, optionxform=None):
+ cf = self.newconfig(defaults)
+ if optionxform:
+ cf.optionxform = optionxform
+ cf.read_string(string)
+ return cf
def test_extended_interpolation(self):
cf = self.fromstring(textwrap.dedent("""
@@ -1070,6 +1084,56 @@
self.assertEqual(cm.exception.reference, 'dollars:${sick')
self.assertEqual(cm.exception.args[2], '}') #rawval
+ def test_case_sensitivity_basic(self):
+ ini = textwrap.dedent("""
+ [common]
+ optionlower = value
+ OptionUpper = Value
+
+ [Common]
+ optionlower = a better ${common:optionlower}
+ OptionUpper = A Better ${common:OptionUpper}
+
+ [random]
+ foolower = ${common:optionlower} redefined
+ FooUpper = ${Common:OptionUpper} Redefined
+ """).strip()
+
+ cf = self.fromstring(ini)
+ eq = self.assertEqual
+ eq(cf['common']['optionlower'], 'value')
+ eq(cf['common']['OptionUpper'], 'Value')
+ eq(cf['Common']['optionlower'], 'a better value')
+ eq(cf['Common']['OptionUpper'], 'A Better Value')
+ eq(cf['random']['foolower'], 'value redefined')
+ eq(cf['random']['FooUpper'], 'A Better Value Redefined')
+
+ def test_case_sensitivity_conflicts(self):
+ ini = textwrap.dedent("""
+ [common]
+ option = value
+ Option = Value
+
+ [Common]
+ option = a better ${common:option}
+ Option = A Better ${common:Option}
+
+ [random]
+ foo = ${common:option} redefined
+ Foo = ${Common:Option} Redefined
+ """).strip()
+ with self.assertRaises(configparser.DuplicateOptionError):
+ cf = self.fromstring(ini)
+
+ # raw options
+ cf = self.fromstring(ini, optionxform=lambda opt: opt)
+ eq = self.assertEqual
+ eq(cf['common']['option'], 'value')
+ eq(cf['common']['Option'], 'Value')
+ eq(cf['Common']['option'], 'a better value')
+ eq(cf['Common']['Option'], 'A Better Value')
+ eq(cf['random']['foo'], 'value redefined')
+ eq(cf['random']['Foo'], 'A Better Value Redefined')
def test_other_errors(self):
cf = self.fromstring("""