Skip to content

Commit

Permalink
gh-89336: Remove configparser APIs that were deprecated for 3.12 (#92503
Browse files Browse the repository at this point in the history
)

https://github.com/python/cpython/issue/89336: Remove configparser 3.12 deprecations.

Co-authored-by: Hugo van Kemenade <[email protected]>
  • Loading branch information
gpshead and hugovk authored Jun 21, 2022
1 parent 4abab6b commit 296e4ef
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 119 deletions.
29 changes: 3 additions & 26 deletions Doc/library/configparser.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1206,28 +1206,6 @@ ConfigParser Objects
names is stripped before :meth:`optionxform` is called.


.. method:: readfp(fp, filename=None)

.. deprecated:: 3.2
Use :meth:`read_file` instead.

.. versionchanged:: 3.2
:meth:`readfp` now iterates on *fp* instead of calling ``fp.readline()``.

For existing code calling :meth:`readfp` with arguments which don't
support iteration, the following generator may be used as a wrapper
around the file-like object::

def readline_generator(fp):
line = fp.readline()
while line:
yield line
line = fp.readline()

Instead of ``parser.readfp(fp)`` use
``parser.read_file(readline_generator(fp))``.


.. data:: MAX_INTERPOLATION_DEPTH

The maximum depth for recursive interpolation for :meth:`get` when the *raw*
Expand Down Expand Up @@ -1361,10 +1339,9 @@ Exceptions

Exception raised when errors occur attempting to parse a file.

.. versionchanged:: 3.2
The ``filename`` attribute and :meth:`__init__` argument were renamed to
``source`` for consistency.

.. versionchanged:: 3.12
The ``filename`` attribute and :meth:`__init__` constructor argument were
removed. They have been available using the name ``source`` since 3.2.

.. rubric:: Footnotes

Expand Down
10 changes: 10 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@ although there is currently no date scheduled for their removal.
Removed
=======

* Several names deprecated in the :mod:`configparser` way back in 3.2 have
been removed per :gh:`89336`:

* :class:`configparser.ParsingError` no longer has a ``filename`` attribute
or argument. Use the ``source`` attribute and argument instead.
* :mod:`configparser` no longer has a ``SafeConfigParser`` class. Use the
shorter :class:`~configparser.ConfigParser` name instead.
* :class:`configparser.ConfigParser` no longer has a ``readfp`` method.
Use :meth:`~configparser.ConfigParser.read_file` instead.

* The following undocumented :mod:`sqlite3` features, deprecated in Python
3.10, are now removed:

Expand Down
61 changes: 5 additions & 56 deletions Lib/configparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@
import sys
import warnings

__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError",
__all__ = ("NoSectionError", "DuplicateOptionError", "DuplicateSectionError",
"NoOptionError", "InterpolationError", "InterpolationDepthError",
"InterpolationMissingOptionError", "InterpolationSyntaxError",
"ParsingError", "MissingSectionHeaderError",
"ConfigParser", "SafeConfigParser", "RawConfigParser",
"ConfigParser", "RawConfigParser",
"Interpolation", "BasicInterpolation", "ExtendedInterpolation",
"LegacyInterpolation", "SectionProxy", "ConverterMapping",
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH")

_default_dict = dict
DEFAULTSECT = "DEFAULT"
Expand Down Expand Up @@ -297,41 +297,12 @@ def __init__(self, option, section, rawval):
class ParsingError(Error):
"""Raised when a configuration file does not follow legal syntax."""

def __init__(self, source=None, filename=None):
# Exactly one of `source'/`filename' arguments has to be given.
# `filename' kept for compatibility.
if filename and source:
raise ValueError("Cannot specify both `filename' and `source'. "
"Use `source'.")
elif not filename and not source:
raise ValueError("Required argument `source' not given.")
elif filename:
source = filename
Error.__init__(self, 'Source contains parsing errors: %r' % source)
def __init__(self, source):
super().__init__(f'Source contains parsing errors: {source!r}')
self.source = source
self.errors = []
self.args = (source, )

@property
def filename(self):
"""Deprecated, use `source'."""
warnings.warn(
"The 'filename' attribute will be removed in Python 3.12. "
"Use 'source' instead.",
DeprecationWarning, stacklevel=2
)
return self.source

@filename.setter
def filename(self, value):
"""Deprecated, user `source'."""
warnings.warn(
"The 'filename' attribute will be removed in Python 3.12. "
"Use 'source' instead.",
DeprecationWarning, stacklevel=2
)
self.source = value

def append(self, lineno, line):
self.errors.append((lineno, line))
self.message += '\n\t[line %2d]: %s' % (lineno, line)
Expand Down Expand Up @@ -768,15 +739,6 @@ def read_dict(self, dictionary, source='<dict>'):
elements_added.add((section, key))
self.set(section, key, value)

def readfp(self, fp, filename=None):
"""Deprecated, use read_file instead."""
warnings.warn(
"This method will be removed in Python 3.12. "
"Use 'parser.read_file()' instead.",
DeprecationWarning, stacklevel=2
)
self.read_file(fp, source=filename)

def get(self, section, option, *, raw=False, vars=None, fallback=_UNSET):
"""Get an option value for a given section.
Expand Down Expand Up @@ -1239,19 +1201,6 @@ def _read_defaults(self, defaults):
self._interpolation = hold_interpolation


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 Python 3.12."
" Use ConfigParser directly instead.",
DeprecationWarning, stacklevel=2
)


class SectionProxy(MutableMapping):
"""A proxy for a single section from a parser."""

Expand Down
42 changes: 5 additions & 37 deletions Lib/test/test_configparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1612,23 +1612,12 @@ def test_interpolation_depth_error(self):
self.assertEqual(error.section, 'section')

def test_parsing_error(self):
with self.assertRaises(ValueError) as cm:
with self.assertRaises(TypeError) as cm:
configparser.ParsingError()
self.assertEqual(str(cm.exception), "Required argument `source' not "
"given.")
with self.assertRaises(ValueError) as cm:
configparser.ParsingError(source='source', filename='filename')
self.assertEqual(str(cm.exception), "Cannot specify both `filename' "
"and `source'. Use `source'.")
error = configparser.ParsingError(filename='source')
error = configparser.ParsingError(source='source')
self.assertEqual(error.source, 'source')
error = configparser.ParsingError('source')
self.assertEqual(error.source, 'source')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always", DeprecationWarning)
self.assertEqual(error.filename, 'source')
error.filename = 'filename'
self.assertEqual(error.source, 'filename')
for warning in w:
self.assertTrue(warning.category is DeprecationWarning)

def test_interpolation_validation(self):
parser = configparser.ConfigParser()
Expand All @@ -1647,27 +1636,6 @@ def test_interpolation_validation(self):
self.assertEqual(str(cm.exception), "bad interpolation variable "
"reference '%(()'")

def test_readfp_deprecation(self):
sio = io.StringIO("""
[section]
option = value
""")
parser = configparser.ConfigParser()
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always", DeprecationWarning)
parser.readfp(sio, filename='StringIO')
for warning in w:
self.assertTrue(warning.category is DeprecationWarning)
self.assertEqual(len(parser), 2)
self.assertEqual(parser['section']['option'], 'value')

def test_safeconfigparser_deprecation(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always", DeprecationWarning)
parser = configparser.SafeConfigParser()
for warning in w:
self.assertTrue(warning.category is DeprecationWarning)

def test_legacyinterpolation_deprecation(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always", DeprecationWarning)
Expand Down Expand Up @@ -1841,7 +1809,7 @@ def test_parsingerror(self):
self.assertEqual(e1.source, e2.source)
self.assertEqual(e1.errors, e2.errors)
self.assertEqual(repr(e1), repr(e2))
e1 = configparser.ParsingError(filename='filename')
e1 = configparser.ParsingError('filename')
e1.append(1, 'line1')
e1.append(2, 'line2')
e1.append(3, 'line3')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Removed :mod:`configparser` module APIs:
the ``SafeConfigParser`` class alias, the ``ParsingError.filename``
property and parameter, and the ``ConfigParser.readfp`` method, all
of which were deprecated since Python 3.2.

0 comments on commit 296e4ef

Please sign in to comment.