]> granicus.if.org Git - python/commitdiff
Broken ConfigParser removed, SafeConfigParser renamed to ConfigParser.
authorŁukasz Langa <lukasz@langa.pl>
Thu, 16 Dec 2010 01:16:22 +0000 (01:16 +0000)
committerŁukasz Langa <lukasz@langa.pl>
Thu, 16 Dec 2010 01:16:22 +0000 (01:16 +0000)
Life is beatiful once again.

Doc/library/configparser.rst
Lib/configparser.py
Lib/test/test_cfgparser.py

index 154d06259018f5df8f7ac79e7032a7f14503fb77..421015a2da41d9a6ae61f86d9d991d060121de82 100644 (file)
    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
 ----------
 
index b5623cdbad9615ebf7211c430fe8cd33a7ebf177..aba444cb33c32eb002d45eb1c479af0ff2b16d6a 100644 (file)
@@ -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."""
 
index 7b91518dacc8c73943c63acbcc081168c9692f75..08a313a819e9bb1211ab84cf38d81ce88df89284 100644 (file)
@@ -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()