[Python-checkins] bpo-23835: Restore legacy defaults= behavior for RawConfigParser (#3191)
Łukasz Langa
webhook-mailer at python.org
Thu Aug 24 12:43:59 EDT 2017
https://github.com/python/cpython/commit/a5fab17fc11433b2418f626dc51e8a3d07b198ca
commit: a5fab17fc11433b2418f626dc51e8a3d07b198ca
branch: master
author: Łukasz Langa <lukasz at langa.pl>
committer: GitHub <noreply at github.com>
date: 2017-08-24T09:43:53-07:00
summary:
bpo-23835: Restore legacy defaults= behavior for RawConfigParser (#3191)
The fix for bpo-23835 fixed ConfigParser behavior in defaults= handling.
Unfortunately, it caused a backwards compatibility regression with
RawConfigParser objects which allow for non-string values.
This commit restores the legacy behavior for RawConfigParser only.
files:
M Doc/library/configparser.rst
M Lib/configparser.py
M Lib/test/test_configparser.py
diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst
index c31a7e94651..acca6470111 100644
--- a/Doc/library/configparser.rst
+++ b/Doc/library/configparser.rst
@@ -1213,8 +1213,10 @@ RawConfigParser Objects
default_section=configparser.DEFAULTSECT[, \
interpolation])
- Legacy variant of the :class:`ConfigParser` with interpolation disabled
- by default and unsafe ``add_section`` and ``set`` methods.
+ Legacy variant of the :class:`ConfigParser`. It has interpolation
+ disabled by default and allows for non-string section names, option
+ names, and values via its unsafe ``add_section`` and ``set`` methods,
+ as well as the legacy ``defaults=`` keyword argument handling.
.. note::
Consider using :class:`ConfigParser` instead which checks types of
diff --git a/Lib/configparser.py b/Lib/configparser.py
index 360924008dc..e172ac8b36f 100644
--- a/Lib/configparser.py
+++ b/Lib/configparser.py
@@ -635,7 +635,7 @@ def __init__(self, defaults=None, dict_type=_default_dict,
if converters is not _UNSET:
self._converters.update(converters)
if defaults:
- self.read_dict({default_section: defaults})
+ self._read_defaults(defaults)
def defaults(self):
return self._defaults
@@ -1121,6 +1121,12 @@ def _join_multiline_values(self):
section,
name, val)
+ def _read_defaults(self, defaults):
+ """Read the defaults passed in the initializer.
+ Note: values can be non-string."""
+ for key, value in defaults.items():
+ self._defaults[self.optionxform(key)] = value
+
def _handle_error(self, exc, fpname, lineno, line):
if not exc:
exc = ParsingError(fpname)
@@ -1198,6 +1204,11 @@ def add_section(self, section):
self._validate_value_types(section=section)
super().add_section(section)
+ def _read_defaults(self, defaults):
+ """Reads the defaults passed in the initializer, implicitly converting
+ values to strings like the rest of the API."""
+ self.read_dict({self.default_section: defaults})
+
class SafeConfigParser(ConfigParser):
"""ConfigParser alias for backwards compatibility purposes."""
diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py
index be22fa40310..d8969efc4db 100644
--- a/Lib/test/test_configparser.py
+++ b/Lib/test/test_configparser.py
@@ -855,15 +855,6 @@ def test_invalid_multiline_value(self):
self.assertEqual(cf.get('DEFAULT', 'test'), 'test')
self.assertEqual(cf['DEFAULT']['test'], 'test')
- def test_defaults_keyword(self):
- # test that bpo-23835 is fixed
- cf = self.newconfig(defaults={1: 2.4})
- self.assertEqual(cf[self.default_section]['1'], '2.4')
- self.assertAlmostEqual(cf[self.default_section].getfloat('1'), 2.4)
- cf = self.newconfig(defaults={"A": 5.2})
- self.assertEqual(cf[self.default_section]['a'], '5.2')
- self.assertAlmostEqual(cf[self.default_section].getfloat('a'), 5.2)
-
class StrictTestCase(BasicTestCase, unittest.TestCase):
config_class = configparser.RawConfigParser
@@ -959,6 +950,15 @@ def test_add_section_default(self):
cf = self.newconfig()
self.assertRaises(ValueError, cf.add_section, self.default_section)
+ def test_defaults_keyword(self):
+ """bpo-23835 fix for ConfigParser"""
+ cf = self.newconfig(defaults={1: 2.4})
+ self.assertEqual(cf[self.default_section]['1'], '2.4')
+ self.assertAlmostEqual(cf[self.default_section].getfloat('1'), 2.4)
+ cf = self.newconfig(defaults={"A": 5.2})
+ self.assertEqual(cf[self.default_section]['a'], '5.2')
+ self.assertAlmostEqual(cf[self.default_section].getfloat('a'), 5.2)
+
class ConfigParserTestCaseNoInterpolation(BasicTestCase, unittest.TestCase):
config_class = configparser.ConfigParser
@@ -1099,6 +1099,15 @@ def test_set_nonstring_types(self):
cf.set('non-string', 1, 1)
self.assertEqual(cf.get('non-string', 1), 1)
+ def test_defaults_keyword(self):
+ """bpo-23835 legacy behavior for RawConfigParser"""
+ with self.assertRaises(AttributeError) as ctx:
+ self.newconfig(defaults={1: 2.4})
+ err = ctx.exception
+ self.assertEqual(str(err), "'int' object has no attribute 'lower'")
+ cf = self.newconfig(defaults={"A": 5.2})
+ self.assertAlmostEqual(cf[self.default_section]['a'], 5.2)
+
class RawConfigParserTestCaseNonStandardDelimiters(RawConfigParserTestCase):
delimiters = (':=', '$')
More information about the Python-checkins
mailing list