diff options
-rw-r--r-- | Doc/library/configparser.rst | 99 | ||||
-rw-r--r-- | Lib/configparser.py | 53 | ||||
-rw-r--r-- | Lib/test/test_cfgparser.py | 205 |
3 files changed, 155 insertions, 202 deletions
diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index 154d062..421015a 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -17,10 +17,10 @@ single: ini file single: Windows ini file -This module provides the :class:`SafeConfigParser` class which implements -a basic configuration language which provides a structure similar to what's -found in Microsoft Windows INI files. You can use this to write Python -programs which can be customized by end users easily. +This module provides the :class:`ConfigParser` class which implements a basic +configuration language which provides a structure similar to what's found in +Microsoft Windows INI files. You can use this to write Python programs which +can be customized by end users easily. .. note:: @@ -67,7 +67,7 @@ creating the above configuration file programatically. .. doctest:: >>> import configparser - >>> config = configparser.SafeConfigParser() + >>> config = configparser.ConfigParser() >>> config['DEFAULT'] = {'ServerAliveInterval': '45', ... 'Compression': 'yes', ... 'CompressionLevel': '9'} @@ -92,7 +92,7 @@ back and explore the data it holds. .. doctest:: >>> import configparser - >>> config = configparser.SafeConfigParser() + >>> config = configparser.ConfigParser() >>> config.sections() [] >>> config.read('example.ini') @@ -283,13 +283,13 @@ For example: Interpolation of values ----------------------- -On top of the core functionality, :class:`SafeConfigParser` supports +On top of the core functionality, :class:`ConfigParser` supports interpolation. This means values can be preprocessed before returning them from ``get()`` calls. .. class:: BasicInterpolation() - The default implementation used by :class:`SafeConfigParser`. It enables + The default implementation used by :class:`ConfigParser`. It enables values to contain format strings which refer to other values in the same section, or values in the special default section [1]_. Additional default values can be provided on initialization. @@ -304,7 +304,7 @@ from ``get()`` calls. my_pictures: %(my_dir)s/Pictures - In the example above, :class:`SafeConfigParser` with *interpolation* set to + In the example above, :class:`ConfigParser` with *interpolation* set to ``BasicInterpolation()`` would resolve ``%(home_dir)s`` to the value of ``home_dir`` (``/Users`` in this case). ``%(my_dir)s`` in effect would resolve to ``/Users/lumberjack``. All interpolations are done on demand so @@ -444,7 +444,7 @@ the :meth:`__init__` options: .. doctest:: - >>> parser = configparser.SafeConfigParser() + >>> parser = configparser.ConfigParser() >>> parser.read_dict({'section1': {'key1': 'value1', ... 'key2': 'value2', ... 'key3': 'value3'}, @@ -465,7 +465,7 @@ the :meth:`__init__` options: .. doctest:: >>> from collections import OrderedDict - >>> parser = configparser.SafeConfigParser() + >>> parser = configparser.ConfigParser() >>> parser.read_dict( ... OrderedDict(( ... ('s1', @@ -511,7 +511,7 @@ the :meth:`__init__` options: ... skip-bdb ... skip-innodb # we don't need ACID today ... """ - >>> config = configparser.SafeConfigParser(allow_no_value=True) + >>> config = configparser.ConfigParser(allow_no_value=True) >>> config.read_string(sample_config) >>> # Settings with values are treated as before: @@ -534,7 +534,7 @@ the :meth:`__init__` options: This means values (but not keys) can contain the delimiters. See also the *space_around_delimiters* argument to - :meth:`SafeConfigParser.write`. + :meth:`ConfigParser.write`. * *comment_prefixes*, default value: ``_COMPATIBLE`` (``'#'`` valid on empty lines, ``';'`` valid also on non-empty lines) @@ -604,8 +604,7 @@ the :meth:`__init__` options: advanced variant inspired by ``zc.buildout``. More on the subject in the `dedicated documentation section <#interpolation-of-values>`_. - .. note:: :class:`RawConfigParser` is using ``None`` by default and - :class:`ConfigParser` is using ``configparser.BrokenInterpolation``. + .. note:: :class:`RawConfigParser` is using ``None`` by default. More advanced customization may be achieved by overriding default values of @@ -622,7 +621,7 @@ may be overriden by subclasses or by attribute assignment. .. doctest:: - >>> custom = configparser.SafeConfigParser() + >>> custom = configparser.ConfigParser() >>> custom['section1'] = {'funky': 'nope'} >>> custom['section1'].getboolean('funky') Traceback (most recent call last): @@ -652,7 +651,7 @@ may be overriden by subclasses or by attribute assignment. ... [Section2] ... AnotherKey = Value ... """ - >>> typical = configparser.SafeConfigParser() + >>> typical = configparser.ConfigParser() >>> typical.read_string(config) >>> list(typical['Section1'].keys()) ['key'] @@ -670,11 +669,11 @@ may be overriden by subclasses or by attribute assignment. Legacy API Examples ------------------- -Mainly because of backwards compatibility concerns, :mod:`configparser` provides -also a legacy API with explicit ``get``/``set`` methods. While there are valid -use cases for the methods outlined below, mapping protocol access is preferred -for new projects. The legacy API is at times more advanced, low-level and -downright counterintuitive. +Mainly because of backwards compatibility concerns, :mod:`configparser` +provides also a legacy API with explicit ``get``/``set`` methods. While there +are valid use cases for the methods outlined below, mapping protocol access is +preferred for new projects. The legacy API is at times more advanced, +low-level and downright counterintuitive. An example of writing to a configuration file:: @@ -682,12 +681,11 @@ An example of writing to a configuration file:: config = configparser.RawConfigParser() - # Please note that using RawConfigParser's and the raw mode of - # ConfigParser's respective set functions, you can assign non-string values - # to keys internally, but will receive an error when attempting to write to - # a file or when you get it in non-raw mode. Setting values using the - # mapping protocol or SafeConfigParser's set() does not allow such - # assignments to take place. + # Please note that using RawConfigParser's set functions, you can assign + # non-string values to keys internally, but will receive an error when + # attempting to write to a file or when you get it in non-raw mode. Setting + # values using the mapping protocol or ConfigParser's set() does not allow + # such assignments to take place. config.add_section('Section1') config.set('Section1', 'int', '15') config.set('Section1', 'bool', 'true') @@ -718,11 +716,11 @@ An example of reading the configuration file again:: if config.getboolean('Section1', 'bool'): print(config.get('Section1', 'foo')) -To get interpolation, use :class:`SafeConfigParser`:: +To get interpolation, use :class:`ConfigParser`:: import configparser - cfg = configparser.SafeConfigParser() + cfg = configparser.ConfigParser() cfg.read('example.cfg') # Set the optional `raw` argument of get() to True if you wish to disable @@ -751,13 +749,13 @@ To get interpolation, use :class:`SafeConfigParser`:: print(cfg.get('Section1', 'monster', fallback=None)) # -> None -Default values are available in all three types of ConfigParsers. They are -used in interpolation if an option used is not defined elsewhere. :: +Default values are available in both types of ConfigParsers. They are used in +interpolation if an option used is not defined elsewhere. :: import configparser # New instance with 'bar' and 'baz' defaulting to 'Life' and 'hard' each - config = configparser.SafeConfigParser({'bar': 'Life', 'baz': 'hard'}) + config = configparser.ConfigParser({'bar': 'Life', 'baz': 'hard'}) config.read('example.cfg') print(config.get('Section1', 'foo')) # -> "Python is fun!" @@ -766,12 +764,12 @@ used in interpolation if an option used is not defined elsewhere. :: print(config.get('Section1', 'foo')) # -> "Life is hard!" -.. _safeconfigparser-objects: +.. _configparser-objects: -SafeConfigParser Objects ------------------------- +ConfigParser Objects +-------------------- -.. class:: SafeConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation()) +.. class:: ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation()) The main configuration parser. When *defaults* is given, it is initialized into the dictionary of intrinsic defaults. When *dict_type* is given, it @@ -877,7 +875,7 @@ SafeConfigParser Objects import configparser, os - config = configparser.SafeConfigParser() + config = configparser.ConfigParser() config.read_file(open('defaults.cfg')) config.read(['site.cfg', os.path.expanduser('~/.myapp.cfg')], encoding='cp1250') @@ -1047,13 +1045,13 @@ RawConfigParser Objects .. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configaparser.DEFAULTSECT, interpolation=None) - Legacy variant of the :class:`SafeConfigParser` with interpolation disabled + Legacy variant of the :class:`ConfigParser` with interpolation disabled by default and unsafe ``add_section`` and ``set`` methods. .. note:: - Consider using :class:`SafeConfigParser` instead which checks types of + Consider using :class:`ConfigParser` instead which checks types of the values to be stored internally. If you don't want interpolation, you - can use ``SafeConfigParser(interpolation=None)``. + can use ``ConfigParser(interpolation=None)``. .. method:: add_section(section) @@ -1081,25 +1079,6 @@ RawConfigParser Objects which does not allow such assignments to take place. -.. _configparser-objects: - -ConfigParser Objects --------------------- - -.. class:: ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BrokenInterpolation()) - - .. deprecated:: 3.2 - Whenever you can, consider using :class:`SafeConfigParser`. The - :class:`ConfigParser` provides the same functionality but its - implementation is less predictable. It does not validate the - interpolation syntax used within a configuration file. It also does not - enable escaping the interpolation character (when using - :class:`SafeConfigParser`, a key can have ``%`` as part of the value by - specifying ``%%`` in the file). On top of that, this class doesn't ensure - whether values passed to the parser object are strings which may lead to - inconsistent internal state. - - Exceptions ---------- 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() |