Skip to content

Commit

Permalink
bpo-47061: deprecate the aifc module (GH-32134)
Browse files Browse the repository at this point in the history
Co-authored-by: Christian Heimes <[email protected]>
  • Loading branch information
brettcannon and tiran authored Apr 5, 2022
1 parent 944f09a commit c1d93b6
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 6 deletions.
8 changes: 8 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,14 @@ Deprecated
(:pep:`594`).
(Contributed by Hugo van Kemenade in :issue:`47022`.)

* :pep:`594` led to the deprecations of the following modules which are
slated for removal in Python 3.13:

* :mod:`aifc`

(Contributed by Brett Cannon in :issue:`47061`.)


Removed
=======

Expand Down
4 changes: 4 additions & 0 deletions Lib/aifc.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@

__all__ = ["Error", "open"]


warnings._deprecated(__name__, remove=(3, 13))


class Error(Exception):
pass

Expand Down
5 changes: 4 additions & 1 deletion Lib/sndhdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
__all__ = ['what', 'whathdr']

from collections import namedtuple
import warnings

SndHeaders = namedtuple('SndHeaders',
'filetype framerate nchannels nframes sampwidth')
Expand Down Expand Up @@ -73,7 +74,9 @@ def whathdr(filename):
tests = []

def test_aifc(h, f):
import aifc
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import aifc
if not h.startswith(b'FORM'):
return None
if h[8:12] == b'AIFC':
Expand Down
8 changes: 8 additions & 0 deletions Lib/test/support/warnings_helper.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import contextlib
import functools
import importlib
import re
import sys
import warnings


def import_deprecated(name):
"""Import *name* while suppressing DeprecationWarning."""
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
return importlib.import_module(name)


def check_syntax_warning(testcase, statement, errtext='',
*, lineno=1, offset=None):
# Test also that a warning is emitted only once.
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test___all__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def tearDown(self):
def check_all(self, modname):
names = {}
with warnings_helper.check_warnings(
(f".*{modname}", DeprecationWarning),
(".* (module|package)", DeprecationWarning),
(".* (module|package)", PendingDeprecationWarning),
("", ResourceWarning),
Expand Down
7 changes: 5 additions & 2 deletions Lib/test/test_aifc.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
from test.support import findfile
from test.support.os_helper import TESTFN, unlink
from test.support.warnings_helper import check_no_resource_warning
from test.support.warnings_helper import check_no_resource_warning, import_deprecated
import unittest
from unittest import mock
from test import audiotests
from audioop import byteswap
import io
import sys
import struct
import aifc


aifc = import_deprecated("aifc")


class AifcTest(audiotests.AudioWriteTests,
audiotests.AudioTestsWithSourceFile):
Expand Down
6 changes: 3 additions & 3 deletions Lib/test/test_pyclbr.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,12 @@ def compare(parent1, children1, parent2, children2):
def test_others(self):
cm = self.checkModule

# These were once about the 10 longest modules
# These were once some of the longest modules.
cm('aifc', ignore=('_aifc_params',)) # set with = in module
cm('random', ignore=('Random',)) # from _random import Random as CoreGenerator
cm('cgi', ignore=('log',)) # set with = in module
cm('pickle', ignore=('partial', 'PickleBuffer'))
cm('aifc', ignore=('_aifc_params',)) # set with = in module
cm('re._parser', ignore=('dump', 'groups', 'pos')) # from ._constants import *; property
cm('sre_parse', ignore=('dump', 'groups', 'pos')) # from sre_constants import *; property
cm(
'pdb',
# pyclbr does not handle elegantly `typing` or properties
Expand Down
40 changes: 40 additions & 0 deletions Lib/test/test_warnings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1219,7 +1219,47 @@ class PyEnvironmentVariableTests(EnvironmentVariableTests, unittest.TestCase):
module = py_warnings


class _DeprecatedTest(BaseTest, unittest.TestCase):

"""Test _deprecated()."""

module = original_warnings

def test_warning(self):
version = (3, 11, 0, "final", 0)
test = [(4, 12), (4, 11), (4, 0), (3, 12)]
for remove in test:
msg = rf".*test_warnings.*{remove[0]}\.{remove[1]}"
filter = msg, DeprecationWarning
with self.subTest(remove=remove):
with warnings_helper.check_warnings(filter, quiet=False):
self.module._deprecated("test_warnings", remove=remove,
_version=version)

version = (3, 11, 0, "alpha", 0)
msg = r".*test_warnings.*3\.11"
with warnings_helper.check_warnings((msg, DeprecationWarning), quiet=False):
self.module._deprecated("test_warnings", remove=(3, 11),
_version=version)

def test_RuntimeError(self):
version = (3, 11, 0, "final", 0)
test = [(2, 0), (2, 12), (3, 10)]
for remove in test:
with self.subTest(remove=remove):
with self.assertRaises(RuntimeError):
self.module._deprecated("test_warnings", remove=remove,
_version=version)
for level in ["beta", "candidate", "final"]:
version = (3, 11, 0, level, 0)
with self.subTest(releaselevel=level):
with self.assertRaises(RuntimeError):
self.module._deprecated("test_warnings", remove=(3, 11),
_version=version)


class BootstrapTest(unittest.TestCase):

def test_issue_8766(self):
# "import encodings" emits a warning whereas the warnings is not loaded
# or not completely loaded (warnings imports indirectly encodings by
Expand Down
21 changes: 21 additions & 0 deletions Lib/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,27 @@ def __exit__(self, *exc_info):
self._module._showwarnmsg_impl = self._showwarnmsg_impl


_DEPRECATED_MSG = "{name!r} is deprecated and slated for removal in Python {remove}"

def _deprecated(name, message=_DEPRECATED_MSG, *, remove, _version=sys.version_info):
"""Warn that *name* is deprecated or should be removed.
RuntimeError is raised if *remove* specifies a major/minor tuple older than
the current Python version or the same version but past the alpha.
The *message* argument is formatted with *name* and *remove* as a Python
version (e.g. "3.11").

This comment has been minimized.

Copy link
@methane

methane Apr 6, 2022

Member

FYI, this blank line is not recommended anymore.
python/peps@ab85e78

"""
remove_formatted = f"{remove[0]}.{remove[1]}"
if (_version[:2] > remove) or (_version[:2] == remove and _version[3] != "alpha"):
msg = f"{name!r} was slated for removal after Python {remove_formatted} alpha"
raise RuntimeError(msg)
else:
msg = message.format(name=name, remove=remove_formatted)
warn(msg, DeprecationWarning, stacklevel=3)


# Private utility function called by _PyErr_WarnUnawaitedCoroutine
def _warn_unawaited_coroutine(coro):
msg_lines = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecate the aifc module.

0 comments on commit c1d93b6

Please sign in to comment.