From 036da3bd43aa2593d17d2fb73d4794f9965c577d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 25 May 2023 17:20:48 +0200 Subject: [PATCH] gh-104773: PEP 594: Remove the aifc module (#104933) * Remove .aifc and .aiff test files of Lib/test/audiodata/ * Remove Lib/test/Sine-1000Hz-300ms.aif test file --- Doc/library/aifc.rst | 247 ----- Doc/library/superseded.rst | 1 - Doc/library/wave.rst | 2 +- Doc/tools/.nitignore | 1 - Doc/whatsnew/2.0.rst | 2 +- Doc/whatsnew/3.11.rst | 2 +- Doc/whatsnew/3.12.rst | 2 +- Doc/whatsnew/3.13.rst | 3 + Doc/whatsnew/3.4.rst | 8 +- Doc/whatsnew/3.7.rst | 4 +- Lib/aifc.py | 984 ------------------ Lib/test/Sine-1000Hz-300ms.aif | Bin 61696 -> 0 bytes Lib/test/audiodata/pluck-alaw.aifc | Bin 6910 -> 0 bytes Lib/test/audiodata/pluck-pcm16.aiff | Bin 13506 -> 0 bytes Lib/test/audiodata/pluck-pcm24.aiff | Bin 20120 -> 0 bytes Lib/test/audiodata/pluck-pcm32.aiff | Bin 26734 -> 0 bytes Lib/test/audiodata/pluck-pcm8.aiff | Bin 6892 -> 0 bytes Lib/test/audiodata/pluck-ulaw.aifc | Bin 6910 -> 0 bytes Lib/test/test_aifc.py | 439 -------- Lib/wave.py | 4 +- Misc/NEWS.d/3.7.0b3.rst | 2 +- Misc/NEWS.d/3.8.0a1.rst | 2 +- ...-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst | 2 + Python/stdlib_module_names.h | 1 - Tools/wasm/wasm_assets.py | 2 +- 25 files changed, 20 insertions(+), 1688 deletions(-) delete mode 100644 Doc/library/aifc.rst delete mode 100644 Lib/aifc.py delete mode 100644 Lib/test/Sine-1000Hz-300ms.aif delete mode 100644 Lib/test/audiodata/pluck-alaw.aifc delete mode 100644 Lib/test/audiodata/pluck-pcm16.aiff delete mode 100644 Lib/test/audiodata/pluck-pcm24.aiff delete mode 100644 Lib/test/audiodata/pluck-pcm32.aiff delete mode 100644 Lib/test/audiodata/pluck-pcm8.aiff delete mode 100644 Lib/test/audiodata/pluck-ulaw.aifc delete mode 100644 Lib/test/test_aifc.py create mode 100644 Misc/NEWS.d/next/Library/2023-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst diff --git a/Doc/library/aifc.rst b/Doc/library/aifc.rst deleted file mode 100644 index 9f20a30193fa..000000000000 --- a/Doc/library/aifc.rst +++ /dev/null @@ -1,247 +0,0 @@ -:mod:`aifc` --- Read and write AIFF and AIFC files -================================================== - -.. module:: aifc - :synopsis: Read and write audio files in AIFF or AIFC format. - :deprecated: - -**Source code:** :source:`Lib/aifc.py` - -.. index:: - single: Audio Interchange File Format - single: AIFF - single: AIFF-C - - -.. deprecated-removed:: 3.11 3.13 - The :mod:`aifc` module is deprecated - (see :pep:`PEP 594 <594#aifc>` for details). - --------------- - -This module provides support for reading and writing AIFF and AIFF-C files. -AIFF is Audio Interchange File Format, a format for storing digital audio -samples in a file. AIFF-C is a newer version of the format that includes the -ability to compress the audio data. - -Audio files have a number of parameters that describe the audio data. The -sampling rate or frame rate is the number of times per second the sound is -sampled. The number of channels indicate if the audio is mono, stereo, or -quadro. Each frame consists of one sample per channel. The sample size is the -size in bytes of each sample. Thus a frame consists of -``nchannels * samplesize`` bytes, and a second's worth of audio consists of -``nchannels * samplesize * framerate`` bytes. - -For example, CD quality audio has a sample size of two bytes (16 bits), uses two -channels (stereo) and has a frame rate of 44,100 frames/second. This gives a -frame size of 4 bytes (2\*2), and a second's worth occupies 2\*2\*44100 bytes -(176,400 bytes). - -Module :mod:`aifc` defines the following function: - - -.. function:: open(file, mode=None) - - Open an AIFF or AIFF-C file and return an object instance with methods that are - described below. The argument *file* is either a string naming a file or a - :term:`file object`. *mode* must be ``'r'`` or ``'rb'`` when the file must be - opened for reading, or ``'w'`` or ``'wb'`` when the file must be opened for writing. - If omitted, ``file.mode`` is used if it exists, otherwise ``'rb'`` is used. When - used for writing, the file object should be seekable, unless you know ahead of - time how many samples you are going to write in total and use - :meth:`writeframesraw` and :meth:`setnframes`. - The :func:`.open` function may be used in a :keyword:`with` statement. When - the :keyword:`!with` block completes, the :meth:`~aifc.close` method is called. - - .. versionchanged:: 3.4 - Support for the :keyword:`with` statement was added. - -Objects returned by :func:`.open` when a file is opened for reading have the -following methods: - - -.. method:: aifc.getnchannels() - - Return the number of audio channels (1 for mono, 2 for stereo). - - -.. method:: aifc.getsampwidth() - - Return the size in bytes of individual samples. - - -.. method:: aifc.getframerate() - - Return the sampling rate (number of audio frames per second). - - -.. method:: aifc.getnframes() - - Return the number of audio frames in the file. - - -.. method:: aifc.getcomptype() - - Return a bytes array of length 4 describing the type of compression - used in the audio file. For AIFF files, the returned value is - ``b'NONE'``. - - -.. method:: aifc.getcompname() - - Return a bytes array convertible to a human-readable description - of the type of compression used in the audio file. For AIFF files, - the returned value is ``b'not compressed'``. - - -.. method:: aifc.getparams() - - Returns a :func:`~collections.namedtuple` ``(nchannels, sampwidth, - framerate, nframes, comptype, compname)``, equivalent to output of the - :meth:`get\*` methods. - - -.. method:: aifc.getmarkers() - - Return a list of markers in the audio file. A marker consists of a tuple of - three elements. The first is the mark ID (an integer), the second is the mark - position in frames from the beginning of the data (an integer), the third is the - name of the mark (a string). - - -.. method:: aifc.getmark(id) - - Return the tuple as described in :meth:`getmarkers` for the mark with the given - *id*. - - -.. method:: aifc.readframes(nframes) - - Read and return the next *nframes* frames from the audio file. The returned - data is a string containing for each frame the uncompressed samples of all - channels. - - -.. method:: aifc.rewind() - - Rewind the read pointer. The next :meth:`readframes` will start from the - beginning. - - -.. method:: aifc.setpos(pos) - - Seek to the specified frame number. - - -.. method:: aifc.tell() - - Return the current frame number. - - -.. method:: aifc.close() - - Close the AIFF file. After calling this method, the object can no longer be - used. - -Objects returned by :func:`.open` when a file is opened for writing have all the -above methods, except for :meth:`readframes` and :meth:`setpos`. In addition -the following methods exist. The :meth:`get\*` methods can only be called after -the corresponding :meth:`set\*` methods have been called. Before the first -:meth:`writeframes` or :meth:`writeframesraw`, all parameters except for the -number of frames must be filled in. - - -.. method:: aifc.aiff() - - Create an AIFF file. The default is that an AIFF-C file is created, unless the - name of the file ends in ``'.aiff'`` in which case the default is an AIFF file. - - -.. method:: aifc.aifc() - - Create an AIFF-C file. The default is that an AIFF-C file is created, unless - the name of the file ends in ``'.aiff'`` in which case the default is an AIFF - file. - - -.. method:: aifc.setnchannels(nchannels) - - Specify the number of channels in the audio file. - - -.. method:: aifc.setsampwidth(width) - - Specify the size in bytes of audio samples. - - -.. method:: aifc.setframerate(rate) - - Specify the sampling frequency in frames per second. - - -.. method:: aifc.setnframes(nframes) - - Specify the number of frames that are to be written to the audio file. If this - parameter is not set, or not set correctly, the file needs to support seeking. - - -.. method:: aifc.setcomptype(type, name) - - .. index:: - single: u-LAW - single: A-LAW - single: G.722 - - Specify the compression type. If not specified, the audio data will - not be compressed. In AIFF files, compression is not possible. - The name parameter should be a human-readable description of the - compression type as a bytes array, the type parameter should be a - bytes array of length 4. Currently the following compression types - are supported: ``b'NONE'``, ``b'ULAW'``, ``b'ALAW'``, ``b'G722'``. - - -.. method:: aifc.setparams(nchannels, sampwidth, framerate, comptype, compname) - - Set all the above parameters at once. The argument is a tuple consisting of the - various parameters. This means that it is possible to use the result of a - :meth:`getparams` call as argument to :meth:`setparams`. - - -.. method:: aifc.setmark(id, pos, name) - - Add a mark with the given id (larger than 0), and the given name at the given - position. This method can be called at any time before :meth:`close`. - - -.. method:: aifc.tell() - :noindex: - - Return the current write position in the output file. Useful in combination - with :meth:`setmark`. - - -.. method:: aifc.writeframes(data) - - Write data to the output file. This method can only be called after the audio - file parameters have been set. - - .. versionchanged:: 3.4 - Any :term:`bytes-like object` is now accepted. - - -.. method:: aifc.writeframesraw(data) - - Like :meth:`writeframes`, except that the header of the audio file is not - updated. - - .. versionchanged:: 3.4 - Any :term:`bytes-like object` is now accepted. - - -.. method:: aifc.close() - :noindex: - - Close the AIFF file. The header of the file is updated to reflect the actual - size of the audio data. After calling this method, the object can no longer be - used. - diff --git a/Doc/library/superseded.rst b/Doc/library/superseded.rst index 7e05f0edf4b1..d2e052779b5e 100644 --- a/Doc/library/superseded.rst +++ b/Doc/library/superseded.rst @@ -10,7 +10,6 @@ backwards compatibility. They have been superseded by other modules. .. toctree:: - aifc.rst audioop.rst chunk.rst imghdr.rst diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 04a28d97d619..4dcbc3d4c2d1 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -119,7 +119,7 @@ Wave_read objects, as returned by :func:`.open`, have the following methods: Rewind the file pointer to the beginning of the audio stream. -The following two methods are defined for compatibility with the :mod:`aifc` +The following two methods are defined for compatibility with the old :mod:`!aifc` module, and don't do anything interesting. diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index 9f3a99e90bc9..3d0354c3ab2a 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -75,7 +75,6 @@ Doc/install/index.rst Doc/library/__future__.rst Doc/library/_thread.rst Doc/library/abc.rst -Doc/library/aifc.rst Doc/library/ast.rst Doc/library/asyncio-dev.rst Doc/library/asyncio-eventloop.rst diff --git a/Doc/whatsnew/2.0.rst b/Doc/whatsnew/2.0.rst index e6c7ec93a16a..b1e584987fb1 100644 --- a/Doc/whatsnew/2.0.rst +++ b/Doc/whatsnew/2.0.rst @@ -1031,7 +1031,7 @@ Module changes Lots of improvements and bugfixes were made to Python's extensive standard library; some of the affected modules include :mod:`readline`, :mod:`ConfigParser`, :mod:`!cgi`, :mod:`calendar`, :mod:`posix`, :mod:`readline`, -:mod:`xmllib`, :mod:`aifc`, :mod:`chunk, wave`, :mod:`random`, :mod:`shelve`, +:mod:`xmllib`, :mod:`!aifc`, :mod:`chunk, wave`, :mod:`random`, :mod:`shelve`, and :mod:`!nntplib`. Consult the CVS logs for the exact patch-by-patch details. Brian Gallew contributed OpenSSL support for the :mod:`socket` module. OpenSSL diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index ece273c7d090..982d20b622ba 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -1731,7 +1731,7 @@ Modules slated for removal in Python 3.13: +---------------------+---------------------+---------------------+---------------------+---------------------+ - | :mod:`aifc` | :mod:`chunk` | :mod:`!msilib` | :mod:`!pipes` | :mod:`!telnetlib` | + | :mod:`!aifc` | :mod:`chunk` | :mod:`!msilib` | :mod:`!pipes` | :mod:`!telnetlib` | +---------------------+---------------------+---------------------+---------------------+---------------------+ | :mod:`audioop` | :mod:`!crypt` | :mod:`!nis` | :mod:`!sndhdr` | :mod:`!uu` | +---------------------+---------------------+---------------------+---------------------+---------------------+ diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 7c184063fba5..b8a5a0c01253 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -918,7 +918,7 @@ and will be removed in Python 3.13. Modules (see :pep:`594`): -* :mod:`aifc` +* :mod:`!aifc` * :mod:`audioop` * :mod:`!cgi` * :mod:`!cgitb` diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 38526e1df87a..9c95d1c70b5a 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -221,6 +221,9 @@ Removed the :mod:`base64` module is a modern alternative. (Contributed by Victor Stinner in :gh:`104773`.) +* :pep:`594`: Remove the :mod:`!aifc` module, deprecated in Python 3.11. + (Contributed by Victor Stinner in :gh:`104773`.) + Porting to Python 3.13 ====================== diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index b9008328b49f..bcc941065d9a 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -605,15 +605,15 @@ Using ``ABC`` as a base class has essentially the same effect as specifying aifc ---- -The :meth:`~aifc.aifc.getparams` method now returns a namedtuple rather than a +The :meth:`~!aifc.aifc.getparams` method now returns a namedtuple rather than a plain tuple. (Contributed by Claudiu Popa in :issue:`17818`.) -:func:`aifc.open` now supports the context management protocol: when used in a -:keyword:`with` block, the :meth:`~aifc.aifc.close` method of the returned +:func:`!aifc.open` now supports the context management protocol: when used in a +:keyword:`with` block, the :meth:`~!aifc.aifc.close` method of the returned object will be called automatically at the end of the block. (Contributed by Serhiy Storchacha in :issue:`16486`.) -The :meth:`~aifc.aifc.writeframesraw` and :meth:`~aifc.aifc.writeframes` +The :meth:`~!aifc.aifc.writeframesraw` and :meth:`~!aifc.aifc.writeframes` methods now accept any :term:`bytes-like object`. (Contributed by Serhiy Storchaka in :issue:`8311`.) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index fa89b7db9736..24244ff17b1e 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1940,8 +1940,8 @@ Deprecated Python modules, functions and methods aifc ---- -:func:`aifc.openfp` has been deprecated and will be removed in Python 3.9. -Use :func:`aifc.open` instead. +:func:`!aifc.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`!aifc.open` instead. (Contributed by Brian Curtin in :issue:`31985`.) diff --git a/Lib/aifc.py b/Lib/aifc.py deleted file mode 100644 index 5254987e22bc..000000000000 --- a/Lib/aifc.py +++ /dev/null @@ -1,984 +0,0 @@ -"""Stuff to parse AIFF-C and AIFF files. - -Unless explicitly stated otherwise, the description below is true -both for AIFF-C files and AIFF files. - -An AIFF-C file has the following structure. - - +-----------------+ - | FORM | - +-----------------+ - | | - +----+------------+ - | | AIFC | - | +------------+ - | | | - | | . | - | | . | - | | . | - +----+------------+ - -An AIFF file has the string "AIFF" instead of "AIFC". - -A chunk consists of an identifier (4 bytes) followed by a size (4 bytes, -big endian order), followed by the data. The size field does not include -the size of the 8 byte header. - -The following chunk types are recognized. - - FVER - (AIFF-C only). - MARK - <# of markers> (2 bytes) - list of markers: - (2 bytes, must be > 0) - (4 bytes) - ("pstring") - COMM - <# of channels> (2 bytes) - <# of sound frames> (4 bytes) - (2 bytes) - (10 bytes, IEEE 80-bit extended - floating point) - in AIFF-C files only: - (4 bytes) - ("pstring") - SSND - (4 bytes, not used by this program) - (4 bytes, not used by this program) - - -A pstring consists of 1 byte length, a string of characters, and 0 or 1 -byte pad to make the total length even. - -Usage. - -Reading AIFF files: - f = aifc.open(file, 'r') -where file is either the name of a file or an open file pointer. -The open file pointer must have methods read(), seek(), and close(). -In some types of audio files, if the setpos() method is not used, -the seek() method is not necessary. - -This returns an instance of a class with the following public methods: - getnchannels() -- returns number of audio channels (1 for - mono, 2 for stereo) - getsampwidth() -- returns sample width in bytes - getframerate() -- returns sampling frequency - getnframes() -- returns number of audio frames - getcomptype() -- returns compression type ('NONE' for AIFF files) - getcompname() -- returns human-readable version of - compression type ('not compressed' for AIFF files) - getparams() -- returns a namedtuple consisting of all of the - above in the above order - getmarkers() -- get the list of marks in the audio file or None - if there are no marks - getmark(id) -- get mark with the specified id (raises an error - if the mark does not exist) - readframes(n) -- returns at most n frames of audio - rewind() -- rewind to the beginning of the audio stream - setpos(pos) -- seek to the specified position - tell() -- return the current position - close() -- close the instance (make it unusable) -The position returned by tell(), the position given to setpos() and -the position of marks are all compatible and have nothing to do with -the actual position in the file. -The close() method is called automatically when the class instance -is destroyed. - -Writing AIFF files: - f = aifc.open(file, 'w') -where file is either the name of a file or an open file pointer. -The open file pointer must have methods write(), tell(), seek(), and -close(). - -This returns an instance of a class with the following public methods: - aiff() -- create an AIFF file (AIFF-C default) - aifc() -- create an AIFF-C file - setnchannels(n) -- set the number of channels - setsampwidth(n) -- set the sample width - setframerate(n) -- set the frame rate - setnframes(n) -- set the number of frames - setcomptype(type, name) - -- set the compression type and the - human-readable compression type - setparams(tuple) - -- set all parameters at once - setmark(id, pos, name) - -- add specified mark to the list of marks - tell() -- return current position in output file (useful - in combination with setmark()) - writeframesraw(data) - -- write audio frames without pathing up the - file header - writeframes(data) - -- write audio frames and patch up the file header - close() -- patch up the file header and close the - output file -You should set the parameters before the first writeframesraw or -writeframes. The total number of frames does not need to be set, -but when it is set to the correct value, the header does not have to -be patched up. -It is best to first set all parameters, perhaps possibly the -compression type, and then write audio frames using writeframesraw. -When all frames have been written, either call writeframes(b'') or -close() to patch up the sizes in the header. -Marks can be added anytime. If there are any marks, you must call -close() after all frames have been written. -The close() method is called automatically when the class instance -is destroyed. - -When a file is opened with the extension '.aiff', an AIFF file is -written, otherwise an AIFF-C file is written. This default can be -changed by calling aiff() or aifc() before the first writeframes or -writeframesraw. -""" - -import struct -import builtins -import warnings - -__all__ = ["Error", "open"] - - -warnings._deprecated(__name__, remove=(3, 13)) - - -class Error(Exception): - pass - -_AIFC_version = 0xA2805140 # Version 1 of AIFF-C - -def _read_long(file): - try: - return struct.unpack('>l', file.read(4))[0] - except struct.error: - raise EOFError from None - -def _read_ulong(file): - try: - return struct.unpack('>L', file.read(4))[0] - except struct.error: - raise EOFError from None - -def _read_short(file): - try: - return struct.unpack('>h', file.read(2))[0] - except struct.error: - raise EOFError from None - -def _read_ushort(file): - try: - return struct.unpack('>H', file.read(2))[0] - except struct.error: - raise EOFError from None - -def _read_string(file): - length = ord(file.read(1)) - if length == 0: - data = b'' - else: - data = file.read(length) - if length & 1 == 0: - dummy = file.read(1) - return data - -_HUGE_VAL = 1.79769313486231e+308 # See - -def _read_float(f): # 10 bytes - expon = _read_short(f) # 2 bytes - sign = 1 - if expon < 0: - sign = -1 - expon = expon + 0x8000 - himant = _read_ulong(f) # 4 bytes - lomant = _read_ulong(f) # 4 bytes - if expon == himant == lomant == 0: - f = 0.0 - elif expon == 0x7FFF: - f = _HUGE_VAL - else: - expon = expon - 16383 - f = (himant * 0x100000000 + lomant) * pow(2.0, expon - 63) - return sign * f - -def _write_short(f, x): - f.write(struct.pack('>h', x)) - -def _write_ushort(f, x): - f.write(struct.pack('>H', x)) - -def _write_long(f, x): - f.write(struct.pack('>l', x)) - -def _write_ulong(f, x): - f.write(struct.pack('>L', x)) - -def _write_string(f, s): - if len(s) > 255: - raise ValueError("string exceeds maximum pstring length") - f.write(struct.pack('B', len(s))) - f.write(s) - if len(s) & 1 == 0: - f.write(b'\x00') - -def _write_float(f, x): - import math - if x < 0: - sign = 0x8000 - x = x * -1 - else: - sign = 0 - if x == 0: - expon = 0 - himant = 0 - lomant = 0 - else: - fmant, expon = math.frexp(x) - if expon > 16384 or fmant >= 1 or fmant != fmant: # Infinity or NaN - expon = sign|0x7FFF - himant = 0 - lomant = 0 - else: # Finite - expon = expon + 16382 - if expon < 0: # denormalized - fmant = math.ldexp(fmant, expon) - expon = 0 - expon = expon | sign - fmant = math.ldexp(fmant, 32) - fsmant = math.floor(fmant) - himant = int(fsmant) - fmant = math.ldexp(fmant - fsmant, 32) - fsmant = math.floor(fmant) - lomant = int(fsmant) - _write_ushort(f, expon) - _write_ulong(f, himant) - _write_ulong(f, lomant) - -with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - from chunk import Chunk -from collections import namedtuple - -_aifc_params = namedtuple('_aifc_params', - 'nchannels sampwidth framerate nframes comptype compname') - -_aifc_params.nchannels.__doc__ = 'Number of audio channels (1 for mono, 2 for stereo)' -_aifc_params.sampwidth.__doc__ = 'Sample width in bytes' -_aifc_params.framerate.__doc__ = 'Sampling frequency' -_aifc_params.nframes.__doc__ = 'Number of audio frames' -_aifc_params.comptype.__doc__ = 'Compression type ("NONE" for AIFF files)' -_aifc_params.compname.__doc__ = ("""\ -A human-readable version of the compression type -('not compressed' for AIFF files)""") - - -class Aifc_read: - # Variables used in this class: - # - # These variables are available to the user though appropriate - # methods of this class: - # _file -- the open file with methods read(), close(), and seek() - # set through the __init__() method - # _nchannels -- the number of audio channels - # available through the getnchannels() method - # _nframes -- the number of audio frames - # available through the getnframes() method - # _sampwidth -- the number of bytes per audio sample - # available through the getsampwidth() method - # _framerate -- the sampling frequency - # available through the getframerate() method - # _comptype -- the AIFF-C compression type ('NONE' if AIFF) - # available through the getcomptype() method - # _compname -- the human-readable AIFF-C compression type - # available through the getcomptype() method - # _markers -- the marks in the audio file - # available through the getmarkers() and getmark() - # methods - # _soundpos -- the position in the audio stream - # available through the tell() method, set through the - # setpos() method - # - # These variables are used internally only: - # _version -- the AIFF-C version number - # _decomp -- the decompressor from builtin module cl - # _comm_chunk_read -- 1 iff the COMM chunk has been read - # _aifc -- 1 iff reading an AIFF-C file - # _ssnd_seek_needed -- 1 iff positioned correctly in audio - # file for readframes() - # _ssnd_chunk -- instantiation of a chunk class for the SSND chunk - # _framesize -- size of one frame in the file - - _file = None # Set here since __del__ checks it - - def initfp(self, file): - self._version = 0 - self._convert = None - self._markers = [] - self._soundpos = 0 - self._file = file - chunk = Chunk(file) - if chunk.getname() != b'FORM': - raise Error('file does not start with FORM id') - formdata = chunk.read(4) - if formdata == b'AIFF': - self._aifc = 0 - elif formdata == b'AIFC': - self._aifc = 1 - else: - raise Error('not an AIFF or AIFF-C file') - self._comm_chunk_read = 0 - self._ssnd_chunk = None - while 1: - self._ssnd_seek_needed = 1 - try: - chunk = Chunk(self._file) - except EOFError: - break - chunkname = chunk.getname() - if chunkname == b'COMM': - self._read_comm_chunk(chunk) - self._comm_chunk_read = 1 - elif chunkname == b'SSND': - self._ssnd_chunk = chunk - dummy = chunk.read(8) - self._ssnd_seek_needed = 0 - elif chunkname == b'FVER': - self._version = _read_ulong(chunk) - elif chunkname == b'MARK': - self._readmark(chunk) - chunk.skip() - if not self._comm_chunk_read or not self._ssnd_chunk: - raise Error('COMM chunk and/or SSND chunk missing') - - def __init__(self, f): - if isinstance(f, str): - file_object = builtins.open(f, 'rb') - try: - self.initfp(file_object) - except: - file_object.close() - raise - else: - # assume it is an open file object already - self.initfp(f) - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - # - # User visible methods. - # - def getfp(self): - return self._file - - def rewind(self): - self._ssnd_seek_needed = 1 - self._soundpos = 0 - - def close(self): - file = self._file - if file is not None: - self._file = None - file.close() - - def tell(self): - return self._soundpos - - def getnchannels(self): - return self._nchannels - - def getnframes(self): - return self._nframes - - def getsampwidth(self): - return self._sampwidth - - def getframerate(self): - return self._framerate - - def getcomptype(self): - return self._comptype - - def getcompname(self): - return self._compname - -## def getversion(self): -## return self._version - - def getparams(self): - return _aifc_params(self.getnchannels(), self.getsampwidth(), - self.getframerate(), self.getnframes(), - self.getcomptype(), self.getcompname()) - - def getmarkers(self): - if len(self._markers) == 0: - return None - return self._markers - - def getmark(self, id): - for marker in self._markers: - if id == marker[0]: - return marker - raise Error('marker {0!r} does not exist'.format(id)) - - def setpos(self, pos): - if pos < 0 or pos > self._nframes: - raise Error('position not in range') - self._soundpos = pos - self._ssnd_seek_needed = 1 - - def readframes(self, nframes): - if self._ssnd_seek_needed: - self._ssnd_chunk.seek(0) - dummy = self._ssnd_chunk.read(8) - pos = self._soundpos * self._framesize - if pos: - self._ssnd_chunk.seek(pos + 8) - self._ssnd_seek_needed = 0 - if nframes == 0: - return b'' - data = self._ssnd_chunk.read(nframes * self._framesize) - if self._convert and data: - data = self._convert(data) - self._soundpos = self._soundpos + len(data) // (self._nchannels - * self._sampwidth) - return data - - # - # Internal methods. - # - - def _alaw2lin(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - return audioop.alaw2lin(data, 2) - - def _ulaw2lin(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - return audioop.ulaw2lin(data, 2) - - def _adpcm2lin(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - if not hasattr(self, '_adpcmstate'): - # first time - self._adpcmstate = None - data, self._adpcmstate = audioop.adpcm2lin(data, 2, self._adpcmstate) - return data - - def _sowt2lin(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - return audioop.byteswap(data, 2) - - def _read_comm_chunk(self, chunk): - self._nchannels = _read_short(chunk) - self._nframes = _read_long(chunk) - self._sampwidth = (_read_short(chunk) + 7) // 8 - self._framerate = int(_read_float(chunk)) - if self._sampwidth <= 0: - raise Error('bad sample width') - if self._nchannels <= 0: - raise Error('bad # of channels') - self._framesize = self._nchannels * self._sampwidth - if self._aifc: - #DEBUG: SGI's soundeditor produces a bad size :-( - kludge = 0 - if chunk.chunksize == 18: - kludge = 1 - warnings.warn('Warning: bad COMM chunk size') - chunk.chunksize = 23 - #DEBUG end - self._comptype = chunk.read(4) - #DEBUG start - if kludge: - length = ord(chunk.file.read(1)) - if length & 1 == 0: - length = length + 1 - chunk.chunksize = chunk.chunksize + length - chunk.file.seek(-1, 1) - #DEBUG end - self._compname = _read_string(chunk) - if self._comptype != b'NONE': - if self._comptype == b'G722': - self._convert = self._adpcm2lin - elif self._comptype in (b'ulaw', b'ULAW'): - self._convert = self._ulaw2lin - elif self._comptype in (b'alaw', b'ALAW'): - self._convert = self._alaw2lin - elif self._comptype in (b'sowt', b'SOWT'): - self._convert = self._sowt2lin - else: - raise Error('unsupported compression type') - self._sampwidth = 2 - else: - self._comptype = b'NONE' - self._compname = b'not compressed' - - def _readmark(self, chunk): - nmarkers = _read_short(chunk) - # Some files appear to contain invalid counts. - # Cope with this by testing for EOF. - try: - for i in range(nmarkers): - id = _read_short(chunk) - pos = _read_long(chunk) - name = _read_string(chunk) - if pos or name: - # some files appear to have - # dummy markers consisting of - # a position 0 and name '' - self._markers.append((id, pos, name)) - except EOFError: - w = ('Warning: MARK chunk contains only %s marker%s instead of %s' % - (len(self._markers), '' if len(self._markers) == 1 else 's', - nmarkers)) - warnings.warn(w) - -class Aifc_write: - # Variables used in this class: - # - # These variables are user settable through appropriate methods - # of this class: - # _file -- the open file with methods write(), close(), tell(), seek() - # set through the __init__() method - # _comptype -- the AIFF-C compression type ('NONE' in AIFF) - # set through the setcomptype() or setparams() method - # _compname -- the human-readable AIFF-C compression type - # set through the setcomptype() or setparams() method - # _nchannels -- the number of audio channels - # set through the setnchannels() or setparams() method - # _sampwidth -- the number of bytes per audio sample - # set through the setsampwidth() or setparams() method - # _framerate -- the sampling frequency - # set through the setframerate() or setparams() method - # _nframes -- the number of audio frames written to the header - # set through the setnframes() or setparams() method - # _aifc -- whether we're writing an AIFF-C file or an AIFF file - # set through the aifc() method, reset through the - # aiff() method - # - # These variables are used internally only: - # _version -- the AIFF-C version number - # _comp -- the compressor from builtin module cl - # _nframeswritten -- the number of audio frames actually written - # _datalength -- the size of the audio samples written to the header - # _datawritten -- the size of the audio samples actually written - - _file = None # Set here since __del__ checks it - - def __init__(self, f): - if isinstance(f, str): - file_object = builtins.open(f, 'wb') - try: - self.initfp(file_object) - except: - file_object.close() - raise - - # treat .aiff file extensions as non-compressed audio - if f.endswith('.aiff'): - self._aifc = 0 - else: - # assume it is an open file object already - self.initfp(f) - - def initfp(self, file): - self._file = file - self._version = _AIFC_version - self._comptype = b'NONE' - self._compname = b'not compressed' - self._convert = None - self._nchannels = 0 - self._sampwidth = 0 - self._framerate = 0 - self._nframes = 0 - self._nframeswritten = 0 - self._datawritten = 0 - self._datalength = 0 - self._markers = [] - self._marklength = 0 - self._aifc = 1 # AIFF-C is default - - def __del__(self): - self.close() - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - # - # User visible methods. - # - def aiff(self): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - self._aifc = 0 - - def aifc(self): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - self._aifc = 1 - - def setnchannels(self, nchannels): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - if nchannels < 1: - raise Error('bad # of channels') - self._nchannels = nchannels - - def getnchannels(self): - if not self._nchannels: - raise Error('number of channels not set') - return self._nchannels - - def setsampwidth(self, sampwidth): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - if sampwidth < 1 or sampwidth > 4: - raise Error('bad sample width') - self._sampwidth = sampwidth - - def getsampwidth(self): - if not self._sampwidth: - raise Error('sample width not set') - return self._sampwidth - - def setframerate(self, framerate): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - if framerate <= 0: - raise Error('bad frame rate') - self._framerate = framerate - - def getframerate(self): - if not self._framerate: - raise Error('frame rate not set') - return self._framerate - - def setnframes(self, nframes): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - self._nframes = nframes - - def getnframes(self): - return self._nframeswritten - - def setcomptype(self, comptype, compname): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - if comptype not in (b'NONE', b'ulaw', b'ULAW', - b'alaw', b'ALAW', b'G722', b'sowt', b'SOWT'): - raise Error('unsupported compression type') - self._comptype = comptype - self._compname = compname - - def getcomptype(self): - return self._comptype - - def getcompname(self): - return self._compname - -## def setversion(self, version): -## if self._nframeswritten: -## raise Error, 'cannot change parameters after starting to write' -## self._version = version - - def setparams(self, params): - nchannels, sampwidth, framerate, nframes, comptype, compname = params - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - if comptype not in (b'NONE', b'ulaw', b'ULAW', - b'alaw', b'ALAW', b'G722', b'sowt', b'SOWT'): - raise Error('unsupported compression type') - self.setnchannels(nchannels) - self.setsampwidth(sampwidth) - self.setframerate(framerate) - self.setnframes(nframes) - self.setcomptype(comptype, compname) - - def getparams(self): - if not self._nchannels or not self._sampwidth or not self._framerate: - raise Error('not all parameters set') - return _aifc_params(self._nchannels, self._sampwidth, self._framerate, - self._nframes, self._comptype, self._compname) - - def setmark(self, id, pos, name): - if id <= 0: - raise Error('marker ID must be > 0') - if pos < 0: - raise Error('marker position must be >= 0') - if not isinstance(name, bytes): - raise Error('marker name must be bytes') - for i in range(len(self._markers)): - if id == self._markers[i][0]: - self._markers[i] = id, pos, name - return - self._markers.append((id, pos, name)) - - def getmark(self, id): - for marker in self._markers: - if id == marker[0]: - return marker - raise Error('marker {0!r} does not exist'.format(id)) - - def getmarkers(self): - if len(self._markers) == 0: - return None - return self._markers - - def tell(self): - return self._nframeswritten - - def writeframesraw(self, data): - if not isinstance(data, (bytes, bytearray)): - data = memoryview(data).cast('B') - self._ensure_header_written(len(data)) - nframes = len(data) // (self._sampwidth * self._nchannels) - if self._convert: - data = self._convert(data) - self._file.write(data) - self._nframeswritten = self._nframeswritten + nframes - self._datawritten = self._datawritten + len(data) - - def writeframes(self, data): - self.writeframesraw(data) - if self._nframeswritten != self._nframes or \ - self._datalength != self._datawritten: - self._patchheader() - - def close(self): - if self._file is None: - return - try: - self._ensure_header_written(0) - if self._datawritten & 1: - # quick pad to even size - self._file.write(b'\x00') - self._datawritten = self._datawritten + 1 - self._writemarkers() - if self._nframeswritten != self._nframes or \ - self._datalength != self._datawritten or \ - self._marklength: - self._patchheader() - finally: - # Prevent ref cycles - self._convert = None - f = self._file - self._file = None - f.close() - - # - # Internal methods. - # - - def _lin2alaw(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - return audioop.lin2alaw(data, 2) - - def _lin2ulaw(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - return audioop.lin2ulaw(data, 2) - - def _lin2adpcm(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - if not hasattr(self, '_adpcmstate'): - self._adpcmstate = None - data, self._adpcmstate = audioop.lin2adpcm(data, 2, self._adpcmstate) - return data - - def _lin2sowt(self, data): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - return audioop.byteswap(data, 2) - - def _ensure_header_written(self, datasize): - if not self._nframeswritten: - if self._comptype in (b'ULAW', b'ulaw', - b'ALAW', b'alaw', b'G722', - b'sowt', b'SOWT'): - if not self._sampwidth: - self._sampwidth = 2 - if self._sampwidth != 2: - raise Error('sample width must be 2 when compressing ' - 'with ulaw/ULAW, alaw/ALAW, sowt/SOWT ' - 'or G7.22 (ADPCM)') - if not self._nchannels: - raise Error('# channels not specified') - if not self._sampwidth: - raise Error('sample width not specified') - if not self._framerate: - raise Error('sampling rate not specified') - self._write_header(datasize) - - def _init_compression(self): - if self._comptype == b'G722': - self._convert = self._lin2adpcm - elif self._comptype in (b'ulaw', b'ULAW'): - self._convert = self._lin2ulaw - elif self._comptype in (b'alaw', b'ALAW'): - self._convert = self._lin2alaw - elif self._comptype in (b'sowt', b'SOWT'): - self._convert = self._lin2sowt - - def _write_header(self, initlength): - if self._aifc and self._comptype != b'NONE': - self._init_compression() - self._file.write(b'FORM') - if not self._nframes: - self._nframes = initlength // (self._nchannels * self._sampwidth) - self._datalength = self._nframes * self._nchannels * self._sampwidth - if self._datalength & 1: - self._datalength = self._datalength + 1 - if self._aifc: - if self._comptype in (b'ulaw', b'ULAW', b'alaw', b'ALAW'): - self._datalength = self._datalength // 2 - if self._datalength & 1: - self._datalength = self._datalength + 1 - elif self._comptype == b'G722': - self._datalength = (self._datalength + 3) // 4 - if self._datalength & 1: - self._datalength = self._datalength + 1 - try: - self._form_length_pos = self._file.tell() - except (AttributeError, OSError): - self._form_length_pos = None - commlength = self._write_form_length(self._datalength) - if self._aifc: - self._file.write(b'AIFC') - self._file.write(b'FVER') - _write_ulong(self._file, 4) - _write_ulong(self._file, self._version) - else: - self._file.write(b'AIFF') - self._file.write(b'COMM') - _write_ulong(self._file, commlength) - _write_short(self._file, self._nchannels) - if self._form_length_pos is not None: - self._nframes_pos = self._file.tell() - _write_ulong(self._file, self._nframes) - if self._comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'): - _write_short(self._file, 8) - else: - _write_short(self._file, self._sampwidth * 8) - _write_float(self._file, self._framerate) - if self._aifc: - self._file.write(self._comptype) - _write_string(self._file, self._compname) - self._file.write(b'SSND') - if self._form_length_pos is not None: - self._ssnd_length_pos = self._file.tell() - _write_ulong(self._file, self._datalength + 8) - _write_ulong(self._file, 0) - _write_ulong(self._file, 0) - - def _write_form_length(self, datalength): - if self._aifc: - commlength = 18 + 5 + len(self._compname) - if commlength & 1: - commlength = commlength + 1 - verslength = 12 - else: - commlength = 18 - verslength = 0 - _write_ulong(self._file, 4 + verslength + self._marklength + \ - 8 + commlength + 16 + datalength) - return commlength - - def _patchheader(self): - curpos = self._file.tell() - if self._datawritten & 1: - datalength = self._datawritten + 1 - self._file.write(b'\x00') - else: - datalength = self._datawritten - if datalength == self._datalength and \ - self._nframes == self._nframeswritten and \ - self._marklength == 0: - self._file.seek(curpos, 0) - return - self._file.seek(self._form_length_pos, 0) - dummy = self._write_form_length(datalength) - self._file.seek(self._nframes_pos, 0) - _write_ulong(self._file, self._nframeswritten) - self._file.seek(self._ssnd_length_pos, 0) - _write_ulong(self._file, datalength + 8) - self._file.seek(curpos, 0) - self._nframes = self._nframeswritten - self._datalength = datalength - - def _writemarkers(self): - if len(self._markers) == 0: - return - self._file.write(b'MARK') - length = 2 - for marker in self._markers: - id, pos, name = marker - length = length + len(name) + 1 + 6 - if len(name) & 1 == 0: - length = length + 1 - _write_ulong(self._file, length) - self._marklength = length + 8 - _write_short(self._file, len(self._markers)) - for marker in self._markers: - id, pos, name = marker - _write_short(self._file, id) - _write_ulong(self._file, pos) - _write_string(self._file, name) - -def open(f, mode=None): - if mode is None: - if hasattr(f, 'mode'): - mode = f.mode - else: - mode = 'rb' - if mode in ('r', 'rb'): - return Aifc_read(f) - elif mode in ('w', 'wb'): - return Aifc_write(f) - else: - raise Error("mode must be 'r', 'rb', 'w', or 'wb'") - - -if __name__ == '__main__': - import sys - if not sys.argv[1:]: - sys.argv.append('/usr/demos/data/audio/bach.aiff') - fn = sys.argv[1] - with open(fn, 'r') as f: - print("Reading", fn) - print("nchannels =", f.getnchannels()) - print("nframes =", f.getnframes()) - print("sampwidth =", f.getsampwidth()) - print("framerate =", f.getframerate()) - print("comptype =", f.getcomptype()) - print("compname =", f.getcompname()) - if sys.argv[2:]: - gn = sys.argv[2] - print("Writing", gn) - with open(gn, 'w') as g: - g.setparams(f.getparams()) - while 1: - data = f.readframes(1024) - if not data: - break - g.writeframes(data) - print("Done.") diff --git a/Lib/test/Sine-1000Hz-300ms.aif b/Lib/test/Sine-1000Hz-300ms.aif deleted file mode 100644 index bf08f5ce859429eeeab213fd29a201b0d851b9c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 61696 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 a>Ds!v*8g{&=>O)C0{(AY=>KP|=>Gv*xd*}k diff --git a/Lib/test/audiodata/pluck-pcm24.aiff b/Lib/test/audiodata/pluck-pcm24.aiff deleted file mode 100644 index 8eba145a44d37a837b00428c6e39c6d68e25ac4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 20120 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', 0)) - b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG') - self.assertRaises(aifc.Error, aifc.open, b1) - self.assertRaises(aifc.Error, aifc.open, b2) - - def test_read_no_comm_chunk(self): - b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF') - self.assertRaises(aifc.Error, aifc.open, b) - - def test_read_no_ssnd_chunk(self): - b = b'FORM' + struct.pack('>L', 4) + b'AIFC' - b += b'COMM' + struct.pack('>LhlhhLL', 38, 1, 0, 8, - 0x4000 | 12, 11025<<18, 0) - b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' - with self.assertRaisesRegex(aifc.Error, 'COMM chunk and/or SSND chunk' - ' missing'): - aifc.open(io.BytesIO(b)) - - def test_read_wrong_compression_type(self): - b = b'FORM' + struct.pack('>L', 4) + b'AIFC' - b += b'COMM' + struct.pack('>LhlhhLL', 23, 1, 0, 8, - 0x4000 | 12, 11025<<18, 0) - b += b'WRNG' + struct.pack('B', 0) - self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b)) - - def test_read_wrong_number_of_channels(self): - for nchannels in 0, -1: - b = b'FORM' + struct.pack('>L', 4) + b'AIFC' - b += b'COMM' + struct.pack('>LhlhhLL', 38, nchannels, 0, 8, - 0x4000 | 12, 11025<<18, 0) - b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' - b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 - with self.assertRaisesRegex(aifc.Error, 'bad # of channels'): - aifc.open(io.BytesIO(b)) - - def test_read_wrong_sample_width(self): - for sampwidth in 0, -1: - b = b'FORM' + struct.pack('>L', 4) + b'AIFC' - b += b'COMM' + struct.pack('>LhlhhLL', 38, 1, 0, sampwidth, - 0x4000 | 12, 11025<<18, 0) - b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' - b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 - with self.assertRaisesRegex(aifc.Error, 'bad sample width'): - aifc.open(io.BytesIO(b)) - - def test_read_wrong_marks(self): - b = b'FORM' + struct.pack('>L', 4) + b'AIFF' - b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8, - 0x4000 | 12, 11025<<18, 0) - b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 - b += b'MARK' + struct.pack('>LhB', 3, 1, 1) - with self.assertWarns(UserWarning) as cm: - f = aifc.open(io.BytesIO(b)) - self.assertEqual(str(cm.warning), 'Warning: MARK chunk contains ' - 'only 0 markers instead of 1') - self.assertEqual(f.getmarkers(), None) - - def test_read_comm_kludge_compname_even(self): - b = b'FORM' + struct.pack('>L', 4) + b'AIFC' - b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8, - 0x4000 | 12, 11025<<18, 0) - b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00' - b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 - with self.assertWarns(UserWarning) as cm: - f = aifc.open(io.BytesIO(b)) - self.assertEqual(str(cm.warning), 'Warning: bad COMM chunk size') - self.assertEqual(f.getcompname(), b'even') - - def test_read_comm_kludge_compname_odd(self): - b = b'FORM' + struct.pack('>L', 4) + b'AIFC' - b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8, - 0x4000 | 12, 11025<<18, 0) - b += b'NONE' + struct.pack('B', 3) + b'odd' - b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 - with self.assertWarns(UserWarning) as cm: - f = aifc.open(io.BytesIO(b)) - self.assertEqual(str(cm.warning), 'Warning: bad COMM chunk size') - self.assertEqual(f.getcompname(), b'odd') - - def test_write_params_raises(self): - fout = aifc.open(io.BytesIO(), 'wb') - wrong_params = (0, 0, 0, 0, b'WRNG', '') - self.assertRaises(aifc.Error, fout.setparams, wrong_params) - self.assertRaises(aifc.Error, fout.getparams) - self.assertRaises(aifc.Error, fout.setnchannels, 0) - self.assertRaises(aifc.Error, fout.getnchannels) - self.assertRaises(aifc.Error, fout.setsampwidth, 0) - self.assertRaises(aifc.Error, fout.getsampwidth) - self.assertRaises(aifc.Error, fout.setframerate, 0) - self.assertRaises(aifc.Error, fout.getframerate) - self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '') - fout.aiff() - fout.setnchannels(1) - fout.setsampwidth(1) - fout.setframerate(1) - fout.setnframes(1) - fout.writeframes(b'\x00') - self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1)) - self.assertRaises(aifc.Error, fout.setnchannels, 1) - self.assertRaises(aifc.Error, fout.setsampwidth, 1) - self.assertRaises(aifc.Error, fout.setframerate, 1) - self.assertRaises(aifc.Error, fout.setnframes, 1) - self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '') - self.assertRaises(aifc.Error, fout.aiff) - self.assertRaises(aifc.Error, fout.aifc) - - def test_write_params_singles(self): - fout = aifc.open(io.BytesIO(), 'wb') - fout.aifc() - fout.setnchannels(1) - fout.setsampwidth(2) - fout.setframerate(3) - fout.setnframes(4) - fout.setcomptype(b'NONE', b'name') - self.assertEqual(fout.getnchannels(), 1) - self.assertEqual(fout.getsampwidth(), 2) - self.assertEqual(fout.getframerate(), 3) - self.assertEqual(fout.getnframes(), 0) - self.assertEqual(fout.tell(), 0) - self.assertEqual(fout.getcomptype(), b'NONE') - self.assertEqual(fout.getcompname(), b'name') - fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels()) - self.assertEqual(fout.getnframes(), 4) - self.assertEqual(fout.tell(), 4) - - def test_write_params_bunch(self): - fout = aifc.open(io.BytesIO(), 'wb') - fout.aifc() - p = (1, 2, 3, 4, b'NONE', b'name') - fout.setparams(p) - self.assertEqual(fout.getparams(), p) - fout.initfp(None) - - def test_write_header_raises(self): - fout = aifc.open(io.BytesIO(), 'wb') - self.assertRaises(aifc.Error, fout.close) - fout = aifc.open(io.BytesIO(), 'wb') - fout.setnchannels(1) - self.assertRaises(aifc.Error, fout.close) - fout = aifc.open(io.BytesIO(), 'wb') - fout.setnchannels(1) - fout.setsampwidth(1) - self.assertRaises(aifc.Error, fout.close) - - def test_write_header_comptype_raises(self): - for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'): - fout = aifc.open(io.BytesIO(), 'wb') - fout.setsampwidth(1) - fout.setcomptype(comptype, b'') - self.assertRaises(aifc.Error, fout.close) - fout.initfp(None) - - def test_write_markers_raises(self): - fout = aifc.open(io.BytesIO(), 'wb') - self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'') - self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'') - self.assertRaises(aifc.Error, fout.setmark, 1, 0, None) - self.assertRaises(aifc.Error, fout.getmark, 1) - fout.initfp(None) - - def test_write_aiff_by_extension(self): - sampwidth = 2 - filename = TESTFN + '.aiff' - fout = self.fout = aifc.open(filename, 'wb') - self.addCleanup(unlink, filename) - fout.setparams((1, sampwidth, 1, 1, b'ULAW', b'')) - frames = b'\x00' * fout.getnchannels() * sampwidth - fout.writeframes(frames) - fout.close() - f = self.f = aifc.open(filename, 'rb') - self.assertEqual(f.getcomptype(), b'NONE') - f.close() - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/wave.py b/Lib/wave.py index d5858e5d4b80..76b73de1d67a 100644 --- a/Lib/wave.py +++ b/Lib/wave.py @@ -21,9 +21,9 @@ This returns an instance of a class with the following public methods: getparams() -- returns a namedtuple consisting of all of the above in the above order getmarkers() -- returns None (for compatibility with the - aifc module) + old aifc module) getmark(id) -- raises an error since the mark does not - exist (for compatibility with the aifc module) + exist (for compatibility with the old aifc module) readframes(n) -- returns at most n frames of audio rewind() -- rewind to the beginning of the audio stream setpos(pos) -- seek to the specified position diff --git a/Misc/NEWS.d/3.7.0b3.rst b/Misc/NEWS.d/3.7.0b3.rst index 980110646b29..c86963b7e42d 100644 --- a/Misc/NEWS.d/3.7.0b3.rst +++ b/Misc/NEWS.d/3.7.0b3.rst @@ -325,7 +325,7 @@ documentation. .. section: Library Improved exceptions raised for invalid number of channels and sample width -when read an audio file in modules :mod:`aifc`, :mod:`wave` and +when read an audio file in modules :mod:`!aifc`, :mod:`wave` and :mod:`!sunau`. .. diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index 75902b471694..2634832b78a9 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -5576,7 +5576,7 @@ documentation. .. section: Library Improved exceptions raised for invalid number of channels and sample width -when read an audio file in modules :mod:`aifc`, :mod:`wave` and +when read an audio file in modules :mod:`!aifc`, :mod:`wave` and :mod:`!sunau`. .. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst b/Misc/NEWS.d/next/Library/2023-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst new file mode 100644 index 000000000000..162afb6f2727 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst @@ -0,0 +1,2 @@ +:pep:`594`: Remove the :mod:`!aifc` 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 db574febd20f..d7ea70213c93 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -89,7 +89,6 @@ static const char* _Py_stdlib_module_names[] = { "_winapi", "_zoneinfo", "abc", -"aifc", "antigravity", "argparse", "array", diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index 2cf5ac515a4d..eb45c7dc4109 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -78,7 +78,7 @@ OMIT_NETWORKING_FILES = ( OMIT_MODULE_FILES = { "_asyncio": ["asyncio/"], - "audioop": ["aifc.py", "wave.py"], + "audioop": ["wave.py"], "_curses": ["curses/"], "_ctypes": ["ctypes/"], "_decimal": ["decimal.py"], -- 2.47.3