diff options
author | Victor Stinner <vstinner@python.org> | 2023-05-24 09:32:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-24 09:32:18 (GMT) |
commit | 7b00940f69ab26212ea375860a1956e157dd2c30 (patch) | |
tree | cb879b99dd188e65617e97a5f8f30101a20e57d5 | |
parent | 08d592389603500af398d278af4842cff6f22c33 (diff) | |
download | cpython-7b00940f69ab26212ea375860a1956e157dd2c30.zip cpython-7b00940f69ab26212ea375860a1956e157dd2c30.tar.gz cpython-7b00940f69ab26212ea375860a1956e157dd2c30.tar.bz2 |
gh-104773: PEP 594: Remove the sndhdr module (#104774)
Remove the Lib/test/sndhdrdata/ directory.
-rw-r--r-- | .gitattributes | 1 | ||||
-rw-r--r-- | Doc/library/sndhdr.rst | 104 | ||||
-rw-r--r-- | Doc/library/superseded.rst | 1 | ||||
-rw-r--r-- | Doc/whatsnew/3.11.rst | 2 | ||||
-rw-r--r-- | Doc/whatsnew/3.12.rst | 2 | ||||
-rw-r--r-- | Doc/whatsnew/3.13.rst | 6 | ||||
-rw-r--r-- | Lib/sndhdr.py | 271 | ||||
-rw-r--r-- | Lib/test/sndhdrdata/README | 5 | ||||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.8svx | bin | 110 -> 0 bytes | |||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.aifc | bin | 106 -> 0 bytes | |||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.aiff | bin | 108 -> 0 bytes | |||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.au | bin | 64 -> 0 bytes | |||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.hcom | bin | 256 -> 0 bytes | |||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.sndt | bin | 129 -> 0 bytes | |||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.voc | bin | 63 -> 0 bytes | |||
-rw-r--r-- | Lib/test/sndhdrdata/sndhdr.wav | bin | 64 -> 0 bytes | |||
-rw-r--r-- | Lib/test/test_sndhdr.py | 40 | ||||
-rw-r--r-- | Makefile.pre.in | 1 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-05-23-01-37-40.gh-issue-104773.8c-GsG.rst | 2 | ||||
-rw-r--r-- | Python/stdlib_module_names.h | 1 |
20 files changed, 10 insertions, 426 deletions
diff --git a/.gitattributes b/.gitattributes index 4ed9506..bab1ef0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -18,7 +18,6 @@ *.zip binary # Specific binary files -Lib/test/sndhdrdata/sndhdr.* binary PC/classicAppCompat.* binary # Text files that should not be subject to eol conversion diff --git a/Doc/library/sndhdr.rst b/Doc/library/sndhdr.rst deleted file mode 100644 index fa9323e..0000000 --- a/Doc/library/sndhdr.rst +++ /dev/null @@ -1,104 +0,0 @@ -:mod:`sndhdr` --- Determine type of sound file -============================================== - -.. module:: sndhdr - :synopsis: Determine type of a sound file. - :deprecated: - -.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org> -.. Based on comments in the module source file. - -**Source code:** :source:`Lib/sndhdr.py` - -.. index:: - single: A-LAW - single: u-LAW - -.. deprecated-removed:: 3.11 3.13 - The :mod:`sndhdr` module is deprecated - (see :pep:`PEP 594 <594#sndhdr>` for details and alternatives). - --------------- - -The :mod:`sndhdr` provides utility functions which attempt to determine the type -of sound data which is in a file. When these functions are able to determine -what type of sound data is stored in a file, they return a -:func:`~collections.namedtuple`, containing five attributes: (``filetype``, -``framerate``, ``nchannels``, ``nframes``, ``sampwidth``). The value for *type* -indicates the data type and will be one of the strings ``'aifc'``, ``'aiff'``, -``'au'``, ``'hcom'``, ``'sndr'``, ``'sndt'``, ``'voc'``, ``'wav'``, ``'8svx'``, -``'sb'``, ``'ub'``, or ``'ul'``. The *sampling_rate* will be either the actual -value or ``0`` if unknown or difficult to decode. Similarly, *channels* will be -either the number of channels or ``0`` if it cannot be determined or if the -value is difficult to decode. The value for *frames* will be either the number -of frames or ``-1``. The last item in the tuple, *bits_per_sample*, will either -be the sample size in bits or ``'A'`` for A-LAW or ``'U'`` for u-LAW. - - -.. function:: what(filename) - - Determines the type of sound data stored in the file *filename* using - :func:`whathdr`. If it succeeds, returns a namedtuple as described above, otherwise - ``None`` is returned. - - .. versionchanged:: 3.5 - Result changed from a tuple to a namedtuple. - - -.. function:: whathdr(filename) - - Determines the type of sound data stored in a file based on the file header. - The name of the file is given by *filename*. This function returns a namedtuple as - described above on success, or ``None``. - - .. versionchanged:: 3.5 - Result changed from a tuple to a namedtuple. - -The following sound header types are recognized, as listed below with the return value -from :func:`whathdr`: and :func:`what`: - -+------------+------------------------------------+ -| Value | Sound header format | -+============+====================================+ -| ``'aifc'`` | Compressed Audio Interchange Files | -+------------+------------------------------------+ -| ``'aiff'`` | Audio Interchange Files | -+------------+------------------------------------+ -| ``'au'`` | Au Files | -+------------+------------------------------------+ -| ``'hcom'`` | HCOM Files | -+------------+------------------------------------+ -| ``'sndt'`` | Sndtool Sound Files | -+------------+------------------------------------+ -| ``'voc'`` | Creative Labs Audio Files | -+------------+------------------------------------+ -| ``'wav'`` | Waveform Audio File Format Files | -+------------+------------------------------------+ -| ``'8svx'`` | 8-Bit Sampled Voice Files | -+------------+------------------------------------+ -| ``'sb'`` | Signed Byte Audio Data Files | -+------------+------------------------------------+ -| ``'ub'`` | UB Files | -+------------+------------------------------------+ -| ``'ul'`` | uLAW Audio Files | -+------------+------------------------------------+ - -.. data:: tests - - A list of functions performing the individual tests. Each function takes two - arguments: the byte-stream and an open file-like object. When :func:`what` is - called with a byte-stream, the file-like object will be ``None``. - - The test function should return a string describing the image type if the test - succeeded, or ``None`` if it failed. - -Example: - -.. code-block:: pycon - - >>> import sndhdr - >>> imghdr.what('bass.wav') - 'wav' - >>> imghdr.whathdr('bass.wav') - 'wav' - diff --git a/Doc/library/superseded.rst b/Doc/library/superseded.rst index a96d042..cad4e9c 100644 --- a/Doc/library/superseded.rst +++ b/Doc/library/superseded.rst @@ -22,7 +22,6 @@ backwards compatibility. They have been superseded by other modules. optparse.rst ossaudiodev.rst pipes.rst - sndhdr.rst spwd.rst sunau.rst uu.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index d024b85..4ad6846 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -1733,7 +1733,7 @@ Modules +---------------------+---------------------+---------------------+---------------------+---------------------+ | :mod:`aifc` | :mod:`chunk` | :mod:`msilib` | :mod:`pipes` | :mod:`!telnetlib` | +---------------------+---------------------+---------------------+---------------------+---------------------+ - | :mod:`audioop` | :mod:`crypt` | :mod:`nis` | :mod:`sndhdr` | :mod:`uu` | + | :mod:`audioop` | :mod:`crypt` | :mod:`nis` | :mod:`!sndhdr` | :mod:`uu` | +---------------------+---------------------+---------------------+---------------------+---------------------+ | :mod:`!cgi` | :mod:`imghdr` | :mod:`nntplib` | :mod:`spwd` | :mod:`xdrlib` | +---------------------+---------------------+---------------------+---------------------+---------------------+ diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 417da22..50e7583 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -816,7 +816,7 @@ Modules (see :pep:`594`): * :mod:`nntplib` * :mod:`ossaudiodev` * :mod:`pipes` -* :mod:`sndhdr` +* :mod:`!sndhdr` * :mod:`spwd` * :mod:`sunau` * :mod:`!telnetlib` diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 4bd9a73..1d4a4ca 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -147,6 +147,12 @@ Removed (Contributed by Victor Stinner in :gh:`104773`.) +* :pep:`594`: Remove the :mod:`!sndhdr` module, deprecated in Python 3.11: use + the projects `filetype <https://pypi.org/project/filetype/>`_, `puremagic + <https://pypi.org/project/puremagic/>`_, or `python-magic + <https://pypi.org/project/python-magic/>`_ instead. + (Contributed by Victor Stinner in :gh:`104773`.) + Porting to Python 3.13 ====================== diff --git a/Lib/sndhdr.py b/Lib/sndhdr.py deleted file mode 100644 index 45def9a..0000000 --- a/Lib/sndhdr.py +++ /dev/null @@ -1,271 +0,0 @@ -"""Routines to help recognizing sound files. - -Function whathdr() recognizes various types of sound file headers. -It understands almost all headers that SOX can decode. - -The return tuple contains the following items, in this order: -- file type (as SOX understands it) -- sampling rate (0 if unknown or hard to decode) -- number of channels (0 if unknown or hard to decode) -- number of frames in the file (-1 if unknown or hard to decode) -- number of bits/sample, or 'U' for U-LAW, or 'A' for A-LAW - -If the file doesn't have a recognizable type, it returns None. -If the file can't be opened, OSError is raised. - -To compute the total time, divide the number of frames by the -sampling rate (a frame contains a sample for each channel). - -Function what() calls whathdr(). (It used to also use some -heuristics for raw data, but this doesn't work very well.) - -Finally, the function test() is a simple main program that calls -what() for all files mentioned on the argument list. For directory -arguments it calls what() for all files in that directory. Default -argument is "." (testing all files in the current directory). The -option -r tells it to recurse down directories found inside -explicitly given directories. -""" - -import warnings - -warnings._deprecated(__name__, remove=(3, 13)) - -# The file structure is top-down except that the test program and its -# subroutine come last. - -__all__ = ['what', 'whathdr'] - -from collections import namedtuple - -SndHeaders = namedtuple('SndHeaders', - 'filetype framerate nchannels nframes sampwidth') - -SndHeaders.filetype.__doc__ = ("""The value for type indicates the data type -and will be one of the strings 'aifc', 'aiff', 'au','hcom', -'sndr', 'sndt', 'voc', 'wav', '8svx', 'sb', 'ub', or 'ul'.""") -SndHeaders.framerate.__doc__ = ("""The sampling_rate will be either the actual -value or 0 if unknown or difficult to decode.""") -SndHeaders.nchannels.__doc__ = ("""The number of channels or 0 if it cannot be -determined or if the value is difficult to decode.""") -SndHeaders.nframes.__doc__ = ("""The value for frames will be either the number -of frames or -1.""") -SndHeaders.sampwidth.__doc__ = ("""Either the sample size in bits or -'A' for A-LAW or 'U' for u-LAW.""") - -def what(filename): - """Guess the type of a sound file.""" - res = whathdr(filename) - return res - - -def whathdr(filename): - """Recognize sound headers.""" - with open(filename, 'rb') as f: - h = f.read(512) - for tf in tests: - res = tf(h, f) - if res: - return SndHeaders(*res) - return None - - -#-----------------------------------# -# Subroutines per sound header type # -#-----------------------------------# - -tests = [] - -def test_aifc(h, f): - """AIFC and AIFF files""" - 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': - fmt = 'aifc' - elif h[8:12] == b'AIFF': - fmt = 'aiff' - else: - return None - f.seek(0) - try: - a = aifc.open(f, 'r') - except (EOFError, aifc.Error): - return None - return (fmt, a.getframerate(), a.getnchannels(), - a.getnframes(), 8 * a.getsampwidth()) - -tests.append(test_aifc) - - -def test_au(h, f): - """AU and SND files""" - if h.startswith(b'.snd'): - func = get_long_be - elif h[:4] in (b'\0ds.', b'dns.'): - func = get_long_le - else: - return None - filetype = 'au' - hdr_size = func(h[4:8]) - data_size = func(h[8:12]) - encoding = func(h[12:16]) - rate = func(h[16:20]) - nchannels = func(h[20:24]) - sample_size = 1 # default - if encoding == 1: - sample_bits = 'U' - elif encoding == 2: - sample_bits = 8 - elif encoding == 3: - sample_bits = 16 - sample_size = 2 - else: - sample_bits = '?' - frame_size = sample_size * nchannels - if frame_size: - nframe = data_size / frame_size - else: - nframe = -1 - return filetype, rate, nchannels, nframe, sample_bits - -tests.append(test_au) - - -def test_hcom(h, f): - """HCOM file""" - if h[65:69] != b'FSSD' or h[128:132] != b'HCOM': - return None - divisor = get_long_be(h[144:148]) - if divisor: - rate = 22050 / divisor - else: - rate = 0 - return 'hcom', rate, 1, -1, 8 - -tests.append(test_hcom) - - -def test_voc(h, f): - """VOC file""" - if not h.startswith(b'Creative Voice File\032'): - return None - sbseek = get_short_le(h[20:22]) - rate = 0 - if 0 <= sbseek < 500 and h[sbseek] == 1: - ratecode = 256 - h[sbseek+4] - if ratecode: - rate = int(1000000.0 / ratecode) - return 'voc', rate, 1, -1, 8 - -tests.append(test_voc) - - -def test_wav(h, f): - """WAV file""" - import wave - # 'RIFF' <len> 'WAVE' 'fmt ' <len> - if not h.startswith(b'RIFF') or h[8:12] != b'WAVE' or h[12:16] != b'fmt ': - return None - f.seek(0) - try: - w = wave.open(f, 'r') - except (EOFError, wave.Error): - return None - return ('wav', w.getframerate(), w.getnchannels(), - w.getnframes(), 8*w.getsampwidth()) - -tests.append(test_wav) - - -def test_8svx(h, f): - """8SVX file""" - if not h.startswith(b'FORM') or h[8:12] != b'8SVX': - return None - # Should decode it to get #channels -- assume always 1 - return '8svx', 0, 1, 0, 8 - -tests.append(test_8svx) - - -def test_sndt(h, f): - """SNDT file""" - if h.startswith(b'SOUND'): - nsamples = get_long_le(h[8:12]) - rate = get_short_le(h[20:22]) - return 'sndt', rate, 1, nsamples, 8 - -tests.append(test_sndt) - - -def test_sndr(h, f): - """SNDR file""" - if h.startswith(b'\0\0'): - rate = get_short_le(h[2:4]) - if 4000 <= rate <= 25000: - return 'sndr', rate, 1, -1, 8 - -tests.append(test_sndr) - - -#-------------------------------------------# -# Subroutines to extract numbers from bytes # -#-------------------------------------------# - -def get_long_be(b): - return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3] - -def get_long_le(b): - return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0] - -def get_short_be(b): - return (b[0] << 8) | b[1] - -def get_short_le(b): - return (b[1] << 8) | b[0] - - -#--------------------# -# Small test program # -#--------------------# - -def test(): - import sys - recursive = 0 - if sys.argv[1:] and sys.argv[1] == '-r': - del sys.argv[1:2] - recursive = 1 - try: - if sys.argv[1:]: - testall(sys.argv[1:], recursive, 1) - else: - testall(['.'], recursive, 1) - except KeyboardInterrupt: - sys.stderr.write('\n[Interrupted]\n') - sys.exit(1) - -def testall(list, recursive, toplevel): - import sys - import os - for filename in list: - if os.path.isdir(filename): - print(filename + '/:', end=' ') - if recursive or toplevel: - print('recursing down:') - import glob - names = glob.glob(os.path.join(glob.escape(filename), '*')) - testall(names, recursive, 0) - else: - print('*** directory (use -r) ***') - else: - print(filename + ':', end=' ') - sys.stdout.flush() - try: - print(what(filename)) - except OSError: - print('*** not found ***') - -if __name__ == '__main__': - test() diff --git a/Lib/test/sndhdrdata/README b/Lib/test/sndhdrdata/README deleted file mode 100644 index b2cb664..0000000 --- a/Lib/test/sndhdrdata/README +++ /dev/null @@ -1,5 +0,0 @@ -Sound file samples used by Lib/test/test_sndhdr.py and generated using the -following commands: - - dd if=/dev/zero of=sndhdr.raw bs=20 count=1 - sox -s -2 -c 2 -r 44100 sndhdr.raw sndhdr.<format> diff --git a/Lib/test/sndhdrdata/sndhdr.8svx b/Lib/test/sndhdrdata/sndhdr.8svx Binary files differdeleted file mode 100644 index 8cd6cde..0000000 --- a/Lib/test/sndhdrdata/sndhdr.8svx +++ /dev/null diff --git a/Lib/test/sndhdrdata/sndhdr.aifc b/Lib/test/sndhdrdata/sndhdr.aifc Binary files differdeleted file mode 100644 index 8aae4e7..0000000 --- a/Lib/test/sndhdrdata/sndhdr.aifc +++ /dev/null diff --git a/Lib/test/sndhdrdata/sndhdr.aiff b/Lib/test/sndhdrdata/sndhdr.aiff Binary files differdeleted file mode 100644 index 8c279a7..0000000 --- a/Lib/test/sndhdrdata/sndhdr.aiff +++ /dev/null diff --git a/Lib/test/sndhdrdata/sndhdr.au b/Lib/test/sndhdrdata/sndhdr.au Binary files differdeleted file mode 100644 index 67c9e8f..0000000 --- a/Lib/test/sndhdrdata/sndhdr.au +++ /dev/null diff --git a/Lib/test/sndhdrdata/sndhdr.hcom b/Lib/test/sndhdrdata/sndhdr.hcom Binary files differdeleted file mode 100644 index debb02d..0000000 --- a/Lib/test/sndhdrdata/sndhdr.hcom +++ /dev/null diff --git a/Lib/test/sndhdrdata/sndhdr.sndt b/Lib/test/sndhdrdata/sndhdr.sndt Binary files differdeleted file mode 100644 index e1ca9cb..0000000 --- a/Lib/test/sndhdrdata/sndhdr.sndt +++ /dev/null diff --git a/Lib/test/sndhdrdata/sndhdr.voc b/Lib/test/sndhdrdata/sndhdr.voc Binary files differdeleted file mode 100644 index 53a91fd..0000000 --- a/Lib/test/sndhdrdata/sndhdr.voc +++ /dev/null diff --git a/Lib/test/sndhdrdata/sndhdr.wav b/Lib/test/sndhdrdata/sndhdr.wav Binary files differdeleted file mode 100644 index 0dca367..0000000 --- a/Lib/test/sndhdrdata/sndhdr.wav +++ /dev/null diff --git a/Lib/test/test_sndhdr.py b/Lib/test/test_sndhdr.py deleted file mode 100644 index 4d97437..0000000 --- a/Lib/test/test_sndhdr.py +++ /dev/null @@ -1,40 +0,0 @@ -import pickle -import unittest -from test.support import findfile -from test.support import warnings_helper - -sndhdr = warnings_helper.import_deprecated("sndhdr") - - -class TestFormats(unittest.TestCase): - def test_data(self): - for filename, expected in ( - ('sndhdr.8svx', ('8svx', 0, 1, 0, 8)), - ('sndhdr.aifc', ('aifc', 44100, 2, 5, 16)), - ('sndhdr.aiff', ('aiff', 44100, 2, 5, 16)), - ('sndhdr.au', ('au', 44100, 2, 5.0, 16)), - ('sndhdr.hcom', ('hcom', 22050.0, 1, -1, 8)), - ('sndhdr.sndt', ('sndt', 44100, 1, 5, 8)), - ('sndhdr.voc', ('voc', 0, 1, -1, 8)), - ('sndhdr.wav', ('wav', 44100, 2, 5, 16)), - ): - filename = findfile(filename, subdir="sndhdrdata") - what = sndhdr.what(filename) - self.assertNotEqual(what, None, filename) - self.assertSequenceEqual(what, expected) - self.assertEqual(what.filetype, expected[0]) - self.assertEqual(what.framerate, expected[1]) - self.assertEqual(what.nchannels, expected[2]) - self.assertEqual(what.nframes, expected[3]) - self.assertEqual(what.sampwidth, expected[4]) - - def test_pickleable(self): - filename = findfile('sndhdr.aifc', subdir="sndhdrdata") - what = sndhdr.what(filename) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - dump = pickle.dumps(what, proto) - self.assertEqual(pickle.loads(dump), what) - - -if __name__ == '__main__': - unittest.main() diff --git a/Makefile.pre.in b/Makefile.pre.in index 091df3e..033fdf9 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2119,7 +2119,6 @@ TESTSUBDIRS= idlelib/idle_test \ test/imghdrdata \ test/leakers \ test/libregrtest \ - test/sndhdrdata \ test/subprocessdata \ test/support \ test/support/_hypothesis_stubs \ diff --git a/Misc/NEWS.d/next/Library/2023-05-23-01-37-40.gh-issue-104773.8c-GsG.rst b/Misc/NEWS.d/next/Library/2023-05-23-01-37-40.gh-issue-104773.8c-GsG.rst new file mode 100644 index 0000000..2289161 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-23-01-37-40.gh-issue-104773.8c-GsG.rst @@ -0,0 +1,2 @@ +:pep:`594`: Remove the :mod:`!sndhdr` module, deprecated in Python 3.11. +Patch by Victor Stinner. diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index f5defe8..245c3a1 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -236,7 +236,6 @@ static const char* _Py_stdlib_module_names[] = { "signal", "site", "smtplib", -"sndhdr", "socket", "socketserver", "spwd", |