Skip to content

Commit c1d93b6

Browse files
brettcannontiran
andauthored
bpo-47061: deprecate the aifc module (GH-32134)
Co-authored-by: Christian Heimes <[email protected]>
1 parent 944f09a commit c1d93b6

File tree

10 files changed

+95
-6
lines changed

10 files changed

+95
-6
lines changed

Doc/whatsnew/3.11.rst

+8
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,14 @@ Deprecated
608608
(:pep:`594`).
609609
(Contributed by Hugo van Kemenade in :issue:`47022`.)
610610

611+
* :pep:`594` led to the deprecations of the following modules which are
612+
slated for removal in Python 3.13:
613+
614+
* :mod:`aifc`
615+
616+
(Contributed by Brett Cannon in :issue:`47061`.)
617+
618+
611619
Removed
612620
=======
613621

Lib/aifc.py

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@
140140

141141
__all__ = ["Error", "open"]
142142

143+
144+
warnings._deprecated(__name__, remove=(3, 13))
145+
146+
143147
class Error(Exception):
144148
pass
145149

Lib/sndhdr.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
__all__ = ['what', 'whathdr']
3434

3535
from collections import namedtuple
36+
import warnings
3637

3738
SndHeaders = namedtuple('SndHeaders',
3839
'filetype framerate nchannels nframes sampwidth')
@@ -73,7 +74,9 @@ def whathdr(filename):
7374
tests = []
7475

7576
def test_aifc(h, f):
76-
import aifc
77+
with warnings.catch_warnings():
78+
warnings.simplefilter('ignore', category=DeprecationWarning)
79+
import aifc
7780
if not h.startswith(b'FORM'):
7881
return None
7982
if h[8:12] == b'AIFC':

Lib/test/support/warnings_helper.py

+8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import contextlib
22
import functools
3+
import importlib
34
import re
45
import sys
56
import warnings
67

78

9+
def import_deprecated(name):
10+
"""Import *name* while suppressing DeprecationWarning."""
11+
with warnings.catch_warnings():
12+
warnings.simplefilter('ignore', category=DeprecationWarning)
13+
return importlib.import_module(name)
14+
15+
816
def check_syntax_warning(testcase, statement, errtext='',
917
*, lineno=1, offset=None):
1018
# Test also that a warning is emitted only once.

Lib/test/test___all__.py

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def tearDown(self):
4141
def check_all(self, modname):
4242
names = {}
4343
with warnings_helper.check_warnings(
44+
(f".*{modname}", DeprecationWarning),
4445
(".* (module|package)", DeprecationWarning),
4546
(".* (module|package)", PendingDeprecationWarning),
4647
("", ResourceWarning),

Lib/test/test_aifc.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
from test.support import findfile
22
from test.support.os_helper import TESTFN, unlink
3-
from test.support.warnings_helper import check_no_resource_warning
3+
from test.support.warnings_helper import check_no_resource_warning, import_deprecated
44
import unittest
55
from unittest import mock
66
from test import audiotests
77
from audioop import byteswap
88
import io
99
import sys
1010
import struct
11-
import aifc
11+
12+
13+
aifc = import_deprecated("aifc")
14+
1215

1316
class AifcTest(audiotests.AudioWriteTests,
1417
audiotests.AudioTestsWithSourceFile):

Lib/test/test_pyclbr.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,12 @@ def compare(parent1, children1, parent2, children2):
216216
def test_others(self):
217217
cm = self.checkModule
218218

219-
# These were once about the 10 longest modules
219+
# These were once some of the longest modules.
220+
cm('aifc', ignore=('_aifc_params',)) # set with = in module
220221
cm('random', ignore=('Random',)) # from _random import Random as CoreGenerator
221222
cm('cgi', ignore=('log',)) # set with = in module
222223
cm('pickle', ignore=('partial', 'PickleBuffer'))
223-
cm('aifc', ignore=('_aifc_params',)) # set with = in module
224-
cm('re._parser', ignore=('dump', 'groups', 'pos')) # from ._constants import *; property
224+
cm('sre_parse', ignore=('dump', 'groups', 'pos')) # from sre_constants import *; property
225225
cm(
226226
'pdb',
227227
# pyclbr does not handle elegantly `typing` or properties

Lib/test/test_warnings/__init__.py

+40
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,47 @@ class PyEnvironmentVariableTests(EnvironmentVariableTests, unittest.TestCase):
12191219
module = py_warnings
12201220

12211221

1222+
class _DeprecatedTest(BaseTest, unittest.TestCase):
1223+
1224+
"""Test _deprecated()."""
1225+
1226+
module = original_warnings
1227+
1228+
def test_warning(self):
1229+
version = (3, 11, 0, "final", 0)
1230+
test = [(4, 12), (4, 11), (4, 0), (3, 12)]
1231+
for remove in test:
1232+
msg = rf".*test_warnings.*{remove[0]}\.{remove[1]}"
1233+
filter = msg, DeprecationWarning
1234+
with self.subTest(remove=remove):
1235+
with warnings_helper.check_warnings(filter, quiet=False):
1236+
self.module._deprecated("test_warnings", remove=remove,
1237+
_version=version)
1238+
1239+
version = (3, 11, 0, "alpha", 0)
1240+
msg = r".*test_warnings.*3\.11"
1241+
with warnings_helper.check_warnings((msg, DeprecationWarning), quiet=False):
1242+
self.module._deprecated("test_warnings", remove=(3, 11),
1243+
_version=version)
1244+
1245+
def test_RuntimeError(self):
1246+
version = (3, 11, 0, "final", 0)
1247+
test = [(2, 0), (2, 12), (3, 10)]
1248+
for remove in test:
1249+
with self.subTest(remove=remove):
1250+
with self.assertRaises(RuntimeError):
1251+
self.module._deprecated("test_warnings", remove=remove,
1252+
_version=version)
1253+
for level in ["beta", "candidate", "final"]:
1254+
version = (3, 11, 0, level, 0)
1255+
with self.subTest(releaselevel=level):
1256+
with self.assertRaises(RuntimeError):
1257+
self.module._deprecated("test_warnings", remove=(3, 11),
1258+
_version=version)
1259+
1260+
12221261
class BootstrapTest(unittest.TestCase):
1262+
12231263
def test_issue_8766(self):
12241264
# "import encodings" emits a warning whereas the warnings is not loaded
12251265
# or not completely loaded (warnings imports indirectly encodings by

Lib/warnings.py

+21
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,27 @@ def __exit__(self, *exc_info):
483483
self._module._showwarnmsg_impl = self._showwarnmsg_impl
484484

485485

486+
_DEPRECATED_MSG = "{name!r} is deprecated and slated for removal in Python {remove}"
487+
488+
def _deprecated(name, message=_DEPRECATED_MSG, *, remove, _version=sys.version_info):
489+
"""Warn that *name* is deprecated or should be removed.
490+
491+
RuntimeError is raised if *remove* specifies a major/minor tuple older than
492+
the current Python version or the same version but past the alpha.
493+
494+
The *message* argument is formatted with *name* and *remove* as a Python
495+
version (e.g. "3.11").
496+
497+
"""
498+
remove_formatted = f"{remove[0]}.{remove[1]}"
499+
if (_version[:2] > remove) or (_version[:2] == remove and _version[3] != "alpha"):
500+
msg = f"{name!r} was slated for removal after Python {remove_formatted} alpha"
501+
raise RuntimeError(msg)
502+
else:
503+
msg = message.format(name=name, remove=remove_formatted)
504+
warn(msg, DeprecationWarning, stacklevel=3)
505+
506+
486507
# Private utility function called by _PyErr_WarnUnawaitedCoroutine
487508
def _warn_unawaited_coroutine(coro):
488509
msg_lines = [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Deprecate the aifc module.

0 commit comments

Comments
 (0)