Skip to content

Commit 296e4ef

Browse files
gpsheadhugovk
andauthored
gh-89336: Remove configparser APIs that were deprecated for 3.12 (#92503)
https://github.com/python/cpython/issue/89336: Remove configparser 3.12 deprecations. Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
1 parent 4abab6b commit 296e4ef

File tree

5 files changed

+27
-119
lines changed

5 files changed

+27
-119
lines changed

Doc/library/configparser.rst

+3-26
Original file line numberDiff line numberDiff line change
@@ -1206,28 +1206,6 @@ ConfigParser Objects
12061206
names is stripped before :meth:`optionxform` is called.
12071207

12081208

1209-
.. method:: readfp(fp, filename=None)
1210-
1211-
.. deprecated:: 3.2
1212-
Use :meth:`read_file` instead.
1213-
1214-
.. versionchanged:: 3.2
1215-
:meth:`readfp` now iterates on *fp* instead of calling ``fp.readline()``.
1216-
1217-
For existing code calling :meth:`readfp` with arguments which don't
1218-
support iteration, the following generator may be used as a wrapper
1219-
around the file-like object::
1220-
1221-
def readline_generator(fp):
1222-
line = fp.readline()
1223-
while line:
1224-
yield line
1225-
line = fp.readline()
1226-
1227-
Instead of ``parser.readfp(fp)`` use
1228-
``parser.read_file(readline_generator(fp))``.
1229-
1230-
12311209
.. data:: MAX_INTERPOLATION_DEPTH
12321210

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

13621340
Exception raised when errors occur attempting to parse a file.
13631341

1364-
.. versionchanged:: 3.2
1365-
The ``filename`` attribute and :meth:`__init__` argument were renamed to
1366-
``source`` for consistency.
1367-
1342+
.. versionchanged:: 3.12
1343+
The ``filename`` attribute and :meth:`__init__` constructor argument were
1344+
removed. They have been available using the name ``source`` since 3.2.
13681345

13691346
.. rubric:: Footnotes
13701347

Doc/whatsnew/3.12.rst

+10
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,16 @@ although there is currently no date scheduled for their removal.
178178
Removed
179179
=======
180180

181+
* Several names deprecated in the :mod:`configparser` way back in 3.2 have
182+
been removed per :gh:`89336`:
183+
184+
* :class:`configparser.ParsingError` no longer has a ``filename`` attribute
185+
or argument. Use the ``source`` attribute and argument instead.
186+
* :mod:`configparser` no longer has a ``SafeConfigParser`` class. Use the
187+
shorter :class:`~configparser.ConfigParser` name instead.
188+
* :class:`configparser.ConfigParser` no longer has a ``readfp`` method.
189+
Use :meth:`~configparser.ConfigParser.read_file` instead.
190+
181191
* The following undocumented :mod:`sqlite3` features, deprecated in Python
182192
3.10, are now removed:
183193

Lib/configparser.py

+5-56
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,14 @@
148148
import sys
149149
import warnings
150150

151-
__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError",
151+
__all__ = ("NoSectionError", "DuplicateOptionError", "DuplicateSectionError",
152152
"NoOptionError", "InterpolationError", "InterpolationDepthError",
153153
"InterpolationMissingOptionError", "InterpolationSyntaxError",
154154
"ParsingError", "MissingSectionHeaderError",
155-
"ConfigParser", "SafeConfigParser", "RawConfigParser",
155+
"ConfigParser", "RawConfigParser",
156156
"Interpolation", "BasicInterpolation", "ExtendedInterpolation",
157157
"LegacyInterpolation", "SectionProxy", "ConverterMapping",
158-
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
158+
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH")
159159

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

300-
def __init__(self, source=None, filename=None):
301-
# Exactly one of `source'/`filename' arguments has to be given.
302-
# `filename' kept for compatibility.
303-
if filename and source:
304-
raise ValueError("Cannot specify both `filename' and `source'. "
305-
"Use `source'.")
306-
elif not filename and not source:
307-
raise ValueError("Required argument `source' not given.")
308-
elif filename:
309-
source = filename
310-
Error.__init__(self, 'Source contains parsing errors: %r' % source)
300+
def __init__(self, source):
301+
super().__init__(f'Source contains parsing errors: {source!r}')
311302
self.source = source
312303
self.errors = []
313304
self.args = (source, )
314305

315-
@property
316-
def filename(self):
317-
"""Deprecated, use `source'."""
318-
warnings.warn(
319-
"The 'filename' attribute will be removed in Python 3.12. "
320-
"Use 'source' instead.",
321-
DeprecationWarning, stacklevel=2
322-
)
323-
return self.source
324-
325-
@filename.setter
326-
def filename(self, value):
327-
"""Deprecated, user `source'."""
328-
warnings.warn(
329-
"The 'filename' attribute will be removed in Python 3.12. "
330-
"Use 'source' instead.",
331-
DeprecationWarning, stacklevel=2
332-
)
333-
self.source = value
334-
335306
def append(self, lineno, line):
336307
self.errors.append((lineno, line))
337308
self.message += '\n\t[line %2d]: %s' % (lineno, line)
@@ -768,15 +739,6 @@ def read_dict(self, dictionary, source='<dict>'):
768739
elements_added.add((section, key))
769740
self.set(section, key, value)
770741

771-
def readfp(self, fp, filename=None):
772-
"""Deprecated, use read_file instead."""
773-
warnings.warn(
774-
"This method will be removed in Python 3.12. "
775-
"Use 'parser.read_file()' instead.",
776-
DeprecationWarning, stacklevel=2
777-
)
778-
self.read_file(fp, source=filename)
779-
780742
def get(self, section, option, *, raw=False, vars=None, fallback=_UNSET):
781743
"""Get an option value for a given section.
782744
@@ -1239,19 +1201,6 @@ def _read_defaults(self, defaults):
12391201
self._interpolation = hold_interpolation
12401202

12411203

1242-
class SafeConfigParser(ConfigParser):
1243-
"""ConfigParser alias for backwards compatibility purposes."""
1244-
1245-
def __init__(self, *args, **kwargs):
1246-
super().__init__(*args, **kwargs)
1247-
warnings.warn(
1248-
"The SafeConfigParser class has been renamed to ConfigParser "
1249-
"in Python 3.2. This alias will be removed in Python 3.12."
1250-
" Use ConfigParser directly instead.",
1251-
DeprecationWarning, stacklevel=2
1252-
)
1253-
1254-
12551204
class SectionProxy(MutableMapping):
12561205
"""A proxy for a single section from a parser."""
12571206

Lib/test/test_configparser.py

+5-37
Original file line numberDiff line numberDiff line change
@@ -1612,23 +1612,12 @@ def test_interpolation_depth_error(self):
16121612
self.assertEqual(error.section, 'section')
16131613

16141614
def test_parsing_error(self):
1615-
with self.assertRaises(ValueError) as cm:
1615+
with self.assertRaises(TypeError) as cm:
16161616
configparser.ParsingError()
1617-
self.assertEqual(str(cm.exception), "Required argument `source' not "
1618-
"given.")
1619-
with self.assertRaises(ValueError) as cm:
1620-
configparser.ParsingError(source='source', filename='filename')
1621-
self.assertEqual(str(cm.exception), "Cannot specify both `filename' "
1622-
"and `source'. Use `source'.")
1623-
error = configparser.ParsingError(filename='source')
1617+
error = configparser.ParsingError(source='source')
1618+
self.assertEqual(error.source, 'source')
1619+
error = configparser.ParsingError('source')
16241620
self.assertEqual(error.source, 'source')
1625-
with warnings.catch_warnings(record=True) as w:
1626-
warnings.simplefilter("always", DeprecationWarning)
1627-
self.assertEqual(error.filename, 'source')
1628-
error.filename = 'filename'
1629-
self.assertEqual(error.source, 'filename')
1630-
for warning in w:
1631-
self.assertTrue(warning.category is DeprecationWarning)
16321621

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

1650-
def test_readfp_deprecation(self):
1651-
sio = io.StringIO("""
1652-
[section]
1653-
option = value
1654-
""")
1655-
parser = configparser.ConfigParser()
1656-
with warnings.catch_warnings(record=True) as w:
1657-
warnings.simplefilter("always", DeprecationWarning)
1658-
parser.readfp(sio, filename='StringIO')
1659-
for warning in w:
1660-
self.assertTrue(warning.category is DeprecationWarning)
1661-
self.assertEqual(len(parser), 2)
1662-
self.assertEqual(parser['section']['option'], 'value')
1663-
1664-
def test_safeconfigparser_deprecation(self):
1665-
with warnings.catch_warnings(record=True) as w:
1666-
warnings.simplefilter("always", DeprecationWarning)
1667-
parser = configparser.SafeConfigParser()
1668-
for warning in w:
1669-
self.assertTrue(warning.category is DeprecationWarning)
1670-
16711639
def test_legacyinterpolation_deprecation(self):
16721640
with warnings.catch_warnings(record=True) as w:
16731641
warnings.simplefilter("always", DeprecationWarning)
@@ -1841,7 +1809,7 @@ def test_parsingerror(self):
18411809
self.assertEqual(e1.source, e2.source)
18421810
self.assertEqual(e1.errors, e2.errors)
18431811
self.assertEqual(repr(e1), repr(e2))
1844-
e1 = configparser.ParsingError(filename='filename')
1812+
e1 = configparser.ParsingError('filename')
18451813
e1.append(1, 'line1')
18461814
e1.append(2, 'line2')
18471815
e1.append(3, 'line3')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Removed :mod:`configparser` module APIs:
2+
the ``SafeConfigParser`` class alias, the ``ParsingError.filename``
3+
property and parameter, and the ``ConfigParser.readfp`` method, all
4+
of which were deprecated since Python 3.2.

0 commit comments

Comments
 (0)