diff options
author | Łukasz Langa <lukasz@langa.pl> | 2010-12-16 01:16:22 (GMT) |
---|---|---|
committer | Łukasz Langa <lukasz@langa.pl> | 2010-12-16 01:16:22 (GMT) |
commit | 7f64c8a5121576fd8f92010b7a936b89581c4051 (patch) | |
tree | 9052d6bc0ef45cedd2d73b5be4f53a0f5d1f472a /Lib | |
parent | bb9686f66fb517b16324958cbb3ba9f1b52b45c6 (diff) | |
download | cpython-7f64c8a5121576fd8f92010b7a936b89581c4051.zip cpython-7f64c8a5121576fd8f92010b7a936b89581c4051.tar.gz cpython-7f64c8a5121576fd8f92010b7a936b89581c4051.tar.bz2 |
Broken ConfigParser removed, SafeConfigParser renamed to ConfigParser.
Life is beatiful once again.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/configparser.py | 53 | ||||
-rw-r--r-- | Lib/test/test_cfgparser.py | 205 |
2 files changed, 116 insertions, 142 deletions
diff --git a/Lib/configparser.py b/Lib/configparser.py index b5623cd..aba444c 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -5,11 +5,11 @@ and followed by "name: value" entries, with continuations and such in the style of RFC 822. Intrinsic defaults can be specified by passing them into the -SafeConfigParser constructor as a dictionary. +ConfigParser constructor as a dictionary. class: -SafeConfigParser -- responsible for parsing a list of +ConfigParser -- responsible for parsing a list of configuration files, and managing the parsed database. methods: @@ -265,9 +265,8 @@ class InterpolationMissingOptionError(InterpolationError): class InterpolationSyntaxError(InterpolationError): """Raised when the source text contains invalid syntax. - Current implementation raises this exception only for SafeConfigParser - instances when the source text into which substitutions are made - does not conform to the required syntax. + Current implementation raises this exception when the source text into + which substitutions are made does not conform to the required syntax. """ @@ -369,7 +368,7 @@ class Interpolation: class BasicInterpolation(Interpolation): - """Interpolation as implemented in the classic SafeConfigParser. + """Interpolation as implemented in the classic ConfigParser. The option values can contain format strings which refer to other values in the same section, or values in the special default section. @@ -512,8 +511,8 @@ class ExtendedInterpolation(Interpolation): "found: %r" % (rest,)) -class BrokenInterpolation(Interpolation): - """Deprecated interpolation as implemented in the classic ConfigParser. +class LegacyInterpolation(Interpolation): + """Deprecated interpolation used in old versions of ConfigParser. Use BasicInterpolation or ExtendedInterpolation instead.""" _KEYCRE = re.compile(r"%\(([^)]*)\)s|.") @@ -598,12 +597,6 @@ class RawConfigParser(MutableMapping): default_section=DEFAULTSECT, interpolation=_UNSET): - if self.__class__ is RawConfigParser: - warnings.warn( - "The RawConfigParser class will be removed in future versions." - " Use 'SafeConfigParser(interpolation=None)' instead.", - DeprecationWarning, stacklevel=2 - ) self._dict = dict_type self._sections = self._dict() self._defaults = self._dict() @@ -1142,8 +1135,8 @@ class RawConfigParser(MutableMapping): - we allow valueless options but the value is not None For compatibility reasons this method is not used in classic set() - for RawConfigParsers and ConfigParsers. It is invoked in every - case for mapping protocol access and in SafeConfigParser.set(). + for RawConfigParsers. It is invoked in every case for mapping protocol + access and in ConfigParser.set(). """ if not isinstance(section, str): raise TypeError("section names must be strings") @@ -1157,21 +1150,6 @@ class RawConfigParser(MutableMapping): class ConfigParser(RawConfigParser): """ConfigParser implementing interpolation.""" - _DEFAULT_INTERPOLATION = BrokenInterpolation() - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - if self.__class__ is ConfigParser: - warnings.warn( - "The ConfigParser class will be removed in future versions." - " Use SafeConfigParser instead.", - DeprecationWarning, stacklevel=2 - ) - - -class SafeConfigParser(ConfigParser): - """ConfigParser implementing sane interpolation.""" - _DEFAULT_INTERPOLATION = BasicInterpolation() def set(self, section, option, value=None): @@ -1188,6 +1166,19 @@ class SafeConfigParser(ConfigParser): super().add_section(section) +class SafeConfigParser(ConfigParser): + """ConfigParser alias for backwards compatibility purposes.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + warnings.warn( + "The SafeConfigParser class has been renamed to ConfigParser " + "in Python 3.2. This alias will be removed in future versions." + " Use ConfigParser directly instead.", + DeprecationWarning, stacklevel=2 + ) + + class SectionProxy(MutableMapping): """A proxy for a single section from a parser.""" diff --git a/Lib/test/test_cfgparser.py b/Lib/test/test_cfgparser.py index 7b91518..08a313a 100644 --- a/Lib/test/test_cfgparser.py +++ b/Lib/test/test_cfgparser.py @@ -5,7 +5,6 @@ import os import sys import textwrap import unittest -import warnings from test import support @@ -48,9 +47,7 @@ class CfgParserTestCaseClass(unittest.TestCase): default_section=self.default_section, interpolation=self.interpolation, ) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", category=DeprecationWarning) - instance = self.config_class(**arguments) + instance = self.config_class(**arguments) return instance def fromstring(self, string, defaults=None): @@ -708,11 +705,6 @@ class ConfigParserTestCase(BasicTestCase): config_class = configparser.ConfigParser def test_interpolation(self): - rawval = { - configparser.ConfigParser: ("something %(with11)s " - "lots of interpolation (11 steps)"), - configparser.SafeConfigParser: "%(with1)s", - } cf = self.get_interpolation_config() eq = self.assertEqual eq(cf.get("Foo", "bar"), "something with interpolation (1 step)") @@ -721,21 +713,25 @@ class ConfigParserTestCase(BasicTestCase): eq(cf.get("Foo", "bar10"), "something with lots of interpolation (10 steps)") e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11") - self.assertEqual(e.args, ("bar11", "Foo", rawval[self.config_class])) + if self.interpolation == configparser._UNSET: + self.assertEqual(e.args, ("bar11", "Foo", "%(with1)s")) + elif isinstance(self.interpolation, configparser.LegacyInterpolation): + self.assertEqual(e.args, ("bar11", "Foo", + "something %(with11)s lots of interpolation (11 steps)")) def test_interpolation_missing_value(self): - rawval = { - configparser.ConfigParser: '%(reference)s', - configparser.SafeConfigParser: '', - } cf = self.get_interpolation_config() e = self.get_error(cf, configparser.InterpolationMissingOptionError, "Interpolation Error", "name") self.assertEqual(e.reference, "reference") self.assertEqual(e.section, "Interpolation Error") self.assertEqual(e.option, "name") - self.assertEqual(e.args, ('name', 'Interpolation Error', - rawval[self.config_class], 'reference')) + if self.interpolation == configparser._UNSET: + self.assertEqual(e.args, ('name', 'Interpolation Error', + '', 'reference')) + elif isinstance(self.interpolation, configparser.LegacyInterpolation): + self.assertEqual(e.args, ('name', 'Interpolation Error', + '%(reference)s', 'reference')) def test_items(self): self.check_items_config([('default', '<default>'), @@ -743,35 +739,75 @@ class ConfigParserTestCase(BasicTestCase): ('key', '|value|'), ('name', 'value')]) + def test_safe_interpolation(self): + # See http://www.python.org/sf/511737 + cf = self.fromstring("[section]\n" + "option1{eq}xxx\n" + "option2{eq}%(option1)s/xxx\n" + "ok{eq}%(option1)s/%%s\n" + "not_ok{eq}%(option2)s/%%s".format( + eq=self.delimiters[0])) + self.assertEqual(cf.get("section", "ok"), "xxx/%s") + if self.interpolation == configparser._UNSET: + self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s") + elif isinstance(self.interpolation, configparser.LegacyInterpolation): + with self.assertRaises(TypeError): + cf.get("section", "not_ok") + + def test_set_malformatted_interpolation(self): + cf = self.fromstring("[sect]\n" + "option1{eq}foo\n".format(eq=self.delimiters[0])) + + self.assertEqual(cf.get('sect', "option1"), "foo") + + self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo") + self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%") + self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo") + + self.assertEqual(cf.get('sect', "option1"), "foo") + + # bug #5741: double percents are *not* malformed + cf.set("sect", "option2", "foo%%bar") + self.assertEqual(cf.get("sect", "option2"), "foo%bar") + def test_set_nonstring_types(self): + cf = self.fromstring("[sect]\n" + "option1{eq}foo\n".format(eq=self.delimiters[0])) + # Check that we get a TypeError when setting non-string values + # in an existing section: + self.assertRaises(TypeError, cf.set, "sect", "option1", 1) + self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0) + self.assertRaises(TypeError, cf.set, "sect", "option1", object()) + self.assertRaises(TypeError, cf.set, "sect", "option2", 1) + self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0) + self.assertRaises(TypeError, cf.set, "sect", "option2", object()) + self.assertRaises(TypeError, cf.set, "sect", 123, "invalid opt name!") + self.assertRaises(TypeError, cf.add_section, 123) + + def test_add_section_default(self): cf = self.newconfig() - cf.add_section('non-string') - cf.set('non-string', 'int', 1) - cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%(']) - cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1, - '%(list)': '%(list)'}) - cf.set('non-string', 'string_with_interpolation', '%(list)s') - self.assertEqual(cf.get('non-string', 'int', raw=True), 1) - self.assertRaises(TypeError, cf.get, 'non-string', 'int') - self.assertEqual(cf.get('non-string', 'list', raw=True), - [0, 1, 1, 2, 3, 5, 8, 13, '%(']) - self.assertRaises(TypeError, cf.get, 'non-string', 'list') - self.assertEqual(cf.get('non-string', 'dict', raw=True), - {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'}) - self.assertRaises(TypeError, cf.get, 'non-string', 'dict') - self.assertEqual(cf.get('non-string', 'string_with_interpolation', - raw=True), '%(list)s') - self.assertRaises(ValueError, cf.get, 'non-string', - 'string_with_interpolation', raw=False) - cf.add_section(123) - cf.set(123, 'this is sick', True) - self.assertEqual(cf.get(123, 'this is sick', raw=True), True) - with self.assertRaises(TypeError): - cf.get(123, 'this is sick') - cf.optionxform = lambda x: x - cf.set('non-string', 1, 1) - self.assertRaises(TypeError, cf.get, 'non-string', 1, 1) - self.assertEqual(cf.get('non-string', 1, raw=True), 1) + self.assertRaises(ValueError, cf.add_section, self.default_section) + +class ConfigParserTestCaseLegacyInterpolation(ConfigParserTestCase): + config_class = configparser.ConfigParser + interpolation = configparser.LegacyInterpolation() + + def test_set_malformatted_interpolation(self): + cf = self.fromstring("[sect]\n" + "option1{eq}foo\n".format(eq=self.delimiters[0])) + + self.assertEqual(cf.get('sect', "option1"), "foo") + + cf.set("sect", "option1", "%foo") + self.assertEqual(cf.get('sect', "option1"), "%foo") + cf.set("sect", "option1", "foo%") + self.assertEqual(cf.get('sect', "option1"), "foo%") + cf.set("sect", "option1", "f%oo") + self.assertEqual(cf.get('sect', "option1"), "f%oo") + + # bug #5741: double percents are *not* malformed + cf.set("sect", "option2", "foo%%bar") + self.assertEqual(cf.get("sect", "option2"), "foo%%bar") class ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase): delimiters = (':=', '$') @@ -872,56 +908,8 @@ class RawConfigParserTestSambaConf(BasicTestCase): self.assertEqual(cf.get("global", "hosts allow"), "127.") self.assertEqual(cf.get("tmp", "echo command"), "cat %s; rm %s") -class SafeConfigParserTestCase(ConfigParserTestCase): - config_class = configparser.SafeConfigParser - - def test_safe_interpolation(self): - # See http://www.python.org/sf/511737 - cf = self.fromstring("[section]\n" - "option1{eq}xxx\n" - "option2{eq}%(option1)s/xxx\n" - "ok{eq}%(option1)s/%%s\n" - "not_ok{eq}%(option2)s/%%s".format( - eq=self.delimiters[0])) - self.assertEqual(cf.get("section", "ok"), "xxx/%s") - self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s") - - def test_set_malformatted_interpolation(self): - cf = self.fromstring("[sect]\n" - "option1{eq}foo\n".format(eq=self.delimiters[0])) - - self.assertEqual(cf.get('sect', "option1"), "foo") - - self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo") - self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%") - self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo") - - self.assertEqual(cf.get('sect', "option1"), "foo") - - # bug #5741: double percents are *not* malformed - cf.set("sect", "option2", "foo%%bar") - self.assertEqual(cf.get("sect", "option2"), "foo%bar") - - def test_set_nonstring_types(self): - cf = self.fromstring("[sect]\n" - "option1{eq}foo\n".format(eq=self.delimiters[0])) - # Check that we get a TypeError when setting non-string values - # in an existing section: - self.assertRaises(TypeError, cf.set, "sect", "option1", 1) - self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0) - self.assertRaises(TypeError, cf.set, "sect", "option1", object()) - self.assertRaises(TypeError, cf.set, "sect", "option2", 1) - self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0) - self.assertRaises(TypeError, cf.set, "sect", "option2", object()) - self.assertRaises(TypeError, cf.set, "sect", 123, "invalid opt name!") - self.assertRaises(TypeError, cf.add_section, 123) - - def test_add_section_default(self): - cf = self.newconfig() - self.assertRaises(ValueError, cf.add_section, self.default_section) - -class SafeConfigParserTestCaseExtendedInterpolation(BasicTestCase): - config_class = configparser.SafeConfigParser +class ConfigParserTestCaseExtendedInterpolation(BasicTestCase): + config_class = configparser.ConfigParser interpolation = configparser.ExtendedInterpolation() default_section = 'common' @@ -984,15 +972,11 @@ class SafeConfigParserTestCaseExtendedInterpolation(BasicTestCase): -class SafeConfigParserTestCaseNonStandardDelimiters(SafeConfigParserTestCase): - delimiters = (':=', '$') - comment_prefixes = ('//', '"') - -class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase): +class ConfigParserTestCaseNoValue(ConfigParserTestCase): allow_no_value = True -class SafeConfigParserTestCaseTrickyFile(CfgParserTestCaseClass): - config_class = configparser.SafeConfigParser +class ConfigParserTestCaseTrickyFile(CfgParserTestCaseClass): + config_class = configparser.ConfigParser delimiters = {'='} comment_prefixes = {'#'} allow_no_value = True @@ -1047,9 +1031,7 @@ class Issue7005TestCase(unittest.TestCase): def prepare(self, config_class): # This is the default, but that's the point. - with warnings.catch_warnings(): - warnings.simplefilter("ignore", category=DeprecationWarning) - cp = config_class(allow_no_value=False) + cp = config_class(allow_no_value=False) cp.add_section("section") cp.set("section", "option", None) sio = io.StringIO() @@ -1057,8 +1039,10 @@ class Issue7005TestCase(unittest.TestCase): return sio.getvalue() def test_none_as_value_stringified(self): - output = self.prepare(configparser.ConfigParser) - self.assertEqual(output, self.expected_output) + cp = configparser.ConfigParser(allow_no_value=False) + cp.add_section("section") + with self.assertRaises(TypeError): + cp.set("section", "option", None) def test_none_as_value_stringified_raw(self): output = self.prepare(configparser.RawConfigParser) @@ -1112,15 +1096,14 @@ def test_main(): support.run_unittest( ConfigParserTestCase, ConfigParserTestCaseNonStandardDelimiters, + ConfigParserTestCaseNoValue, + ConfigParserTestCaseExtendedInterpolation, + ConfigParserTestCaseLegacyInterpolation, + ConfigParserTestCaseTrickyFile, MultilineValuesTestCase, RawConfigParserTestCase, RawConfigParserTestCaseNonStandardDelimiters, RawConfigParserTestSambaConf, - SafeConfigParserTestCase, - SafeConfigParserTestCaseExtendedInterpolation, - SafeConfigParserTestCaseNonStandardDelimiters, - SafeConfigParserTestCaseNoValue, - SafeConfigParserTestCaseTrickyFile, SortedTestCase, Issue7005TestCase, StrictTestCase, @@ -1139,6 +1122,6 @@ def test_coverage(coverdir): if __name__ == "__main__": if "-c" in sys.argv: - test_coverage('/tmp/cmd.cover') + test_coverage('/tmp/configparser.cover') else: test_main() |