Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Revert "bpo-45173 Remove configparser deprecations"
This reverts commit df2284b.
  • Loading branch information
hugovk committed Jan 27, 2022
commit ebfa178a7598409f02b2eb5a278ea072fc6e3324
25 changes: 22 additions & 3 deletions Doc/library/configparser.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,28 @@ 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 @@ -1338,9 +1360,6 @@ Exceptions
The ``filename`` attribute and :meth:`__init__` argument were renamed to
``source`` for consistency.

.. versionchanged:: 3.11
The deprecated ``filename`` attribute was removed.


.. rubric:: Footnotes

Expand Down
7 changes: 0 additions & 7 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -501,13 +501,6 @@ Removed
the ``l*gettext()`` functions.
(Contributed by Dong-hee Na and Serhiy Storchaka in :issue:`44235`.)

* Removed from the :mod:`configparser` module:
the :class:`SafeConfigParser` class,
the :attr:`filename` property of the :class:`ParsingError` class,
the :meth:`readfp` method of the :class:`ConfigParser` class,
deprecated since Python 3.2.
(Contributed by Hugo van Kemenade in :issue:`45173`.)

* The :func:`@asyncio.coroutine <asyncio.coroutine>` :term:`decorator` enabling
legacy generator-based coroutines to be compatible with async/await code.
The function has been deprecated since Python 3.8 and the removal was
Expand Down
45 changes: 44 additions & 1 deletion Lib/configparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,13 @@
import os
import re
import sys
import warnings

__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError",
"NoOptionError", "InterpolationError", "InterpolationDepthError",
"InterpolationMissingOptionError", "InterpolationSyntaxError",
"ParsingError", "MissingSectionHeaderError",
"ConfigParser", "RawConfigParser",
"ConfigParser", "SafeConfigParser", "RawConfigParser",
"Interpolation", "BasicInterpolation", "ExtendedInterpolation",
"LegacyInterpolation", "SectionProxy", "ConverterMapping",
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
Expand Down Expand Up @@ -311,6 +312,26 @@ def __init__(self, source=None, filename=None):
self.errors = []
self.args = (source, )

@property
def filename(self):
"""Deprecated, use `source'."""
warnings.warn(
"The 'filename' attribute will be removed in future versions. "
"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 future versions. "
"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 @@ -733,6 +754,15 @@ 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 future versions. "
"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 @@ -1195,6 +1225,19 @@ 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 future versions."
" Use ConfigParser directly instead.",
DeprecationWarning, stacklevel=2
)


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

Expand Down
28 changes: 28 additions & 0 deletions Lib/test/test_configparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,13 @@ def test_parsing_error(self):
"and `source'. Use `source'.")
error = configparser.ParsingError(filename='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 @@ -1630,6 +1637,27 @@ 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_sectionproxy_repr(self):
parser = configparser.ConfigParser()
parser.read_string("""
Expand Down