diff options
-rw-r--r-- | Doc/library/sunau.rst | 274 | ||||
-rw-r--r-- | Doc/library/superseded.rst | 1 | ||||
-rw-r--r-- | Doc/tools/.nitignore | 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 | 3 | ||||
-rw-r--r-- | Doc/whatsnew/3.4.rst | 8 | ||||
-rw-r--r-- | Doc/whatsnew/3.7.rst | 4 | ||||
-rw-r--r-- | Lib/sunau.py | 533 | ||||
-rw-r--r-- | Lib/test/audiodata/pluck-pcm16.au | bin | 13252 -> 0 bytes | |||
-rw-r--r-- | Lib/test/audiodata/pluck-pcm24.au | bin | 19866 -> 0 bytes | |||
-rw-r--r-- | Lib/test/audiodata/pluck-pcm32.au | bin | 26480 -> 0 bytes | |||
-rw-r--r-- | Lib/test/audiodata/pluck-pcm8.au | bin | 6638 -> 0 bytes | |||
-rw-r--r-- | Lib/test/audiodata/pluck-ulaw.au | bin | 6638 -> 0 bytes | |||
-rw-r--r-- | Lib/test/audiotest.au | bin | 28144 -> 0 bytes | |||
-rw-r--r-- | Lib/test/test_sunau.py | 160 | ||||
-rw-r--r-- | Misc/NEWS.d/3.7.0b3.rst | 2 | ||||
-rw-r--r-- | Misc/NEWS.d/3.8.0a1.rst | 2 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst | 2 | ||||
-rw-r--r-- | Python/stdlib_module_names.h | 1 | ||||
-rwxr-xr-x | Tools/wasm/wasm_assets.py | 2 |
21 files changed, 16 insertions, 981 deletions
diff --git a/Doc/library/sunau.rst b/Doc/library/sunau.rst deleted file mode 100644 index c7a38d9..0000000 --- a/Doc/library/sunau.rst +++ /dev/null @@ -1,274 +0,0 @@ -:mod:`sunau` --- Read and write Sun AU files -============================================ - -.. module:: sunau - :synopsis: Provide an interface to the Sun AU sound format. - :deprecated: - -.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il> - -**Source code:** :source:`Lib/sunau.py` - -.. deprecated-removed:: 3.11 3.13 - The :mod:`sunau` module is deprecated - (see :pep:`PEP 594 <594#sunau>` for details). - --------------- - -The :mod:`sunau` module provides a convenient interface to the Sun AU sound -format. Note that this module is interface-compatible with the modules -:mod:`aifc` and :mod:`wave`. - -An audio file consists of a header followed by the data. The fields of the -header are: - -+---------------+-----------------------------------------------+ -| Field | Contents | -+===============+===============================================+ -| magic word | The four bytes ``.snd``. | -+---------------+-----------------------------------------------+ -| header size | Size of the header, including info, in bytes. | -+---------------+-----------------------------------------------+ -| data size | Physical size of the data, in bytes. | -+---------------+-----------------------------------------------+ -| encoding | Indicates how the audio samples are encoded. | -+---------------+-----------------------------------------------+ -| sample rate | The sampling rate. | -+---------------+-----------------------------------------------+ -| # of channels | The number of channels in the samples. | -+---------------+-----------------------------------------------+ -| info | ASCII string giving a description of the | -| | audio file (padded with null bytes). | -+---------------+-----------------------------------------------+ - -Apart from the info field, all header fields are 4 bytes in size. They are all -32-bit unsigned integers encoded in big-endian byte order. - -The :mod:`sunau` module defines the following functions: - - -.. function:: open(file, mode) - - If *file* is a string, open the file by that name, otherwise treat it as a - seekable file-like object. *mode* can be any of - - ``'r'`` - Read only mode. - - ``'w'`` - Write only mode. - - Note that it does not allow read/write files. - - A *mode* of ``'r'`` returns an :class:`AU_read` object, while a *mode* of ``'w'`` - or ``'wb'`` returns an :class:`AU_write` object. - - -The :mod:`sunau` module defines the following exception: - -.. exception:: Error - - An error raised when something is impossible because of Sun AU specs or - implementation deficiency. - - -The :mod:`sunau` module defines the following data items: - -.. data:: AUDIO_FILE_MAGIC - - An integer every valid Sun AU file begins with, stored in big-endian form. This - is the string ``.snd`` interpreted as an integer. - - -.. data:: AUDIO_FILE_ENCODING_MULAW_8 - AUDIO_FILE_ENCODING_LINEAR_8 - AUDIO_FILE_ENCODING_LINEAR_16 - AUDIO_FILE_ENCODING_LINEAR_24 - AUDIO_FILE_ENCODING_LINEAR_32 - AUDIO_FILE_ENCODING_ALAW_8 - - Values of the encoding field from the AU header which are supported by this - module. - - -.. data:: AUDIO_FILE_ENCODING_FLOAT - AUDIO_FILE_ENCODING_DOUBLE - AUDIO_FILE_ENCODING_ADPCM_G721 - AUDIO_FILE_ENCODING_ADPCM_G722 - AUDIO_FILE_ENCODING_ADPCM_G723_3 - AUDIO_FILE_ENCODING_ADPCM_G723_5 - - Additional known values of the encoding field from the AU header, but which are - not supported by this module. - - -.. _au-read-objects: - -AU_read Objects ---------------- - -AU_read objects, as returned by :func:`.open` above, have the following methods: - - -.. method:: AU_read.close() - - Close the stream, and make the instance unusable. (This is called automatically - on deletion.) - - -.. method:: AU_read.getnchannels() - - Returns number of audio channels (1 for mono, 2 for stereo). - - -.. method:: AU_read.getsampwidth() - - Returns sample width in bytes. - - -.. method:: AU_read.getframerate() - - Returns sampling frequency. - - -.. method:: AU_read.getnframes() - - Returns number of audio frames. - - -.. method:: AU_read.getcomptype() - - Returns compression type. Supported compression types are ``'ULAW'``, ``'ALAW'`` - and ``'NONE'``. - - -.. method:: AU_read.getcompname() - - Human-readable version of :meth:`getcomptype`. The supported types have the - respective names ``'CCITT G.711 u-law'``, ``'CCITT G.711 A-law'`` and ``'not - compressed'``. - - -.. method:: AU_read.getparams() - - Returns a :func:`~collections.namedtuple` ``(nchannels, sampwidth, - framerate, nframes, comptype, compname)``, equivalent to output of the - :meth:`get\*` methods. - - -.. method:: AU_read.readframes(n) - - Reads and returns at most *n* frames of audio, as a :class:`bytes` object. The data - will be returned in linear format. If the original data is in u-LAW format, it - will be converted. - - -.. method:: AU_read.rewind() - - Rewind the file pointer to the beginning of the audio stream. - -The following two methods define a term "position" which is compatible between -them, and is otherwise implementation dependent. - - -.. method:: AU_read.setpos(pos) - - Set the file pointer to the specified position. Only values returned from - :meth:`tell` should be used for *pos*. - - -.. method:: AU_read.tell() - - Return current file pointer position. Note that the returned value has nothing - to do with the actual position in the file. - -The following two functions are defined for compatibility with the :mod:`aifc`, -and don't do anything interesting. - - -.. method:: AU_read.getmarkers() - - Returns ``None``. - - -.. method:: AU_read.getmark(id) - - Raise an error. - - -.. _au-write-objects: - -AU_write Objects ----------------- - -AU_write objects, as returned by :func:`.open` above, have the following methods: - - -.. method:: AU_write.setnchannels(n) - - Set the number of channels. - - -.. method:: AU_write.setsampwidth(n) - - Set the sample width (in bytes.) - - .. versionchanged:: 3.4 - Added support for 24-bit samples. - - -.. method:: AU_write.setframerate(n) - - Set the frame rate. - - -.. method:: AU_write.setnframes(n) - - Set the number of frames. This can be later changed, when and if more frames - are written. - - -.. method:: AU_write.setcomptype(type, name) - - Set the compression type and description. Only ``'NONE'`` and ``'ULAW'`` are - supported on output. - - -.. method:: AU_write.setparams(tuple) - - The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype, - compname)``, with values valid for the :meth:`set\*` methods. Set all - parameters. - - -.. method:: AU_write.tell() - - Return current position in the file, with the same disclaimer for the - :meth:`AU_read.tell` and :meth:`AU_read.setpos` methods. - - -.. method:: AU_write.writeframesraw(data) - - Write audio frames, without correcting *nframes*. - - .. versionchanged:: 3.4 - Any :term:`bytes-like object` is now accepted. - - -.. method:: AU_write.writeframes(data) - - Write audio frames and make sure *nframes* is correct. - - .. versionchanged:: 3.4 - Any :term:`bytes-like object` is now accepted. - - -.. method:: AU_write.close() - - Make sure *nframes* is correct, and close the file. - - This method is called upon deletion. - -Note that it is invalid to set any parameters after calling :meth:`writeframes` -or :meth:`writeframesraw`. - diff --git a/Doc/library/superseded.rst b/Doc/library/superseded.rst index a655c09..1ab7b08 100644 --- a/Doc/library/superseded.rst +++ b/Doc/library/superseded.rst @@ -21,6 +21,5 @@ backwards compatibility. They have been superseded by other modules. nntplib.rst optparse.rst spwd.rst - sunau.rst uu.rst xdrlib.rst diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index b8d3e7d..cdd896e 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -207,7 +207,6 @@ Doc/library/stdtypes.rst Doc/library/string.rst Doc/library/struct.rst Doc/library/subprocess.rst -Doc/library/sunau.rst Doc/library/sys.rst Doc/library/sys_path_init.rst Doc/library/sysconfig.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index e59604e..9734d43 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -1737,7 +1737,7 @@ Modules +---------------------+---------------------+---------------------+---------------------+---------------------+ | :mod:`!cgi` | :mod:`imghdr` | :mod:`nntplib` | :mod:`spwd` | :mod:`xdrlib` | +---------------------+---------------------+---------------------+---------------------+---------------------+ - | :mod:`!cgitb` | :mod:`mailcap` | :mod:`!ossaudiodev` | :mod:`sunau` | | + | :mod:`!cgitb` | :mod:`mailcap` | :mod:`!ossaudiodev` | :mod:`!sunau` | | +---------------------+---------------------+---------------------+---------------------+---------------------+ (Contributed by Brett Cannon in :issue:`47061` and Victor Stinner in diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 844d063..316296a 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -901,7 +901,7 @@ Modules (see :pep:`594`): * :mod:`!pipes` * :mod:`!sndhdr` * :mod:`spwd` -* :mod:`sunau` +* :mod:`!sunau` * :mod:`!telnetlib` * :mod:`uu` * :mod:`xdrlib` diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index d086f3c..83d539b 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -161,6 +161,9 @@ Removed use the `pygame project <https://www.pygame.org/>`_ for audio playback. (Contributed by Victor Stinner in :gh:`104780`.) +* :pep:`594`: Remove the :mod:`!sunau` 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 d4ed8ab..b900832 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1528,10 +1528,10 @@ work on Windows. This change was actually inadvertently made in 3.3.4. sunau ----- -The :meth:`~sunau.getparams` method now returns a namedtuple rather than a +The :meth:`~!sunau.getparams` method now returns a namedtuple rather than a plain tuple. (Contributed by Claudiu Popa in :issue:`18901`.) -:meth:`sunau.open` now supports the context management protocol: when used in a +:meth:`!sunau.open` now supports the context management protocol: when used in a :keyword:`with` block, the ``close`` method of the returned object will be called automatically at the end of the block. (Contributed by Serhiy Storchaka in :issue:`18878`.) @@ -1540,8 +1540,8 @@ in :issue:`18878`.) support for writing 24 sample using the module. (Contributed by Serhiy Storchaka in :issue:`19261`.) -The :meth:`~sunau.AU_write.writeframesraw` and -:meth:`~sunau.AU_write.writeframes` methods now accept any :term:`bytes-like +The :meth:`~!sunau.AU_write.writeframesraw` and +:meth:`~!sunau.AU_write.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 41d7e08..967608d 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -2061,8 +2061,8 @@ ssl sunau ----- -:func:`sunau.openfp` has been deprecated and will be removed in Python 3.9. -Use :func:`sunau.open` instead. +:func:`!sunau.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`!sunau.open` instead. (Contributed by Brian Curtin in :issue:`31985`.) diff --git a/Lib/sunau.py b/Lib/sunau.py deleted file mode 100644 index c6caab9..0000000 --- a/Lib/sunau.py +++ /dev/null @@ -1,533 +0,0 @@ -"""Stuff to parse Sun and NeXT audio files. - -An audio file consists of a header followed by the data. The structure -of the header is as follows. - - +---------------+ - | magic word | - +---------------+ - | header size | - +---------------+ - | data size | - +---------------+ - | encoding | - +---------------+ - | sample rate | - +---------------+ - | # of channels | - +---------------+ - | info | - | | - +---------------+ - -The magic word consists of the 4 characters '.snd'. Apart from the -info field, all header fields are 4 bytes in size. They are all -32-bit unsigned integers encoded in big-endian byte order. - -The header size really gives the start of the data. -The data size is the physical size of the data. From the other -parameters the number of frames can be calculated. -The encoding gives the way in which audio samples are encoded. -Possible values are listed below. -The info field currently consists of an ASCII string giving a -human-readable description of the audio file. The info field is -padded with NUL bytes to the header size. - -Usage. - -Reading audio files: - f = sunau.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(). -When the setpos() and rewind() methods are 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' or 'ULAW') - getcompname() -- returns human-readable version of - compression type ('not compressed' matches 'NONE') - getparams() -- returns a namedtuple consisting of all of the - above in the above order - getmarkers() -- returns None (for compatibility with the - aifc module) - getmark(id) -- raises an error since the mark does not - exist (for compatibility with the 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 - tell() -- return the current position - close() -- close the instance (make it unusable) -The position returned by tell() and the position given to setpos() -are 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 audio files: - f = sunau.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: - 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 - tell() -- return current position in output file - 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. -The close() method is called automatically when the class instance -is destroyed. -""" - -from collections import namedtuple -import warnings - -warnings._deprecated(__name__, remove=(3, 13)) - - -_sunau_params = namedtuple('_sunau_params', - 'nchannels sampwidth framerate nframes comptype compname') - -# from <multimedia/audio_filehdr.h> -AUDIO_FILE_MAGIC = 0x2e736e64 -AUDIO_FILE_ENCODING_MULAW_8 = 1 -AUDIO_FILE_ENCODING_LINEAR_8 = 2 -AUDIO_FILE_ENCODING_LINEAR_16 = 3 -AUDIO_FILE_ENCODING_LINEAR_24 = 4 -AUDIO_FILE_ENCODING_LINEAR_32 = 5 -AUDIO_FILE_ENCODING_FLOAT = 6 -AUDIO_FILE_ENCODING_DOUBLE = 7 -AUDIO_FILE_ENCODING_ADPCM_G721 = 23 -AUDIO_FILE_ENCODING_ADPCM_G722 = 24 -AUDIO_FILE_ENCODING_ADPCM_G723_3 = 25 -AUDIO_FILE_ENCODING_ADPCM_G723_5 = 26 -AUDIO_FILE_ENCODING_ALAW_8 = 27 - -# from <multimedia/audio_hdr.h> -AUDIO_UNKNOWN_SIZE = 0xFFFFFFFF # ((unsigned)(~0)) - -_simple_encodings = [AUDIO_FILE_ENCODING_MULAW_8, - AUDIO_FILE_ENCODING_LINEAR_8, - AUDIO_FILE_ENCODING_LINEAR_16, - AUDIO_FILE_ENCODING_LINEAR_24, - AUDIO_FILE_ENCODING_LINEAR_32, - AUDIO_FILE_ENCODING_ALAW_8] - -class Error(Exception): - pass - -def _read_u32(file): - x = 0 - for i in range(4): - byte = file.read(1) - if not byte: - raise EOFError - x = x*256 + ord(byte) - return x - -def _write_u32(file, x): - data = [] - for i in range(4): - d, m = divmod(x, 256) - data.insert(0, int(m)) - x = d - file.write(bytes(data)) - -class Au_read: - - def __init__(self, f): - if isinstance(f, str): - import builtins - f = builtins.open(f, 'rb') - self._opened = True - else: - self._opened = False - self.initfp(f) - - def __del__(self): - if self._file: - self.close() - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - def initfp(self, file): - self._file = file - self._soundpos = 0 - magic = int(_read_u32(file)) - if magic != AUDIO_FILE_MAGIC: - raise Error('bad magic number') - self._hdr_size = int(_read_u32(file)) - if self._hdr_size < 24: - raise Error('header size too small') - if self._hdr_size > 100: - raise Error('header size ridiculously large') - self._data_size = _read_u32(file) - if self._data_size != AUDIO_UNKNOWN_SIZE: - self._data_size = int(self._data_size) - self._encoding = int(_read_u32(file)) - if self._encoding not in _simple_encodings: - raise Error('encoding not (yet) supported') - if self._encoding in (AUDIO_FILE_ENCODING_MULAW_8, - AUDIO_FILE_ENCODING_ALAW_8): - self._sampwidth = 2 - self._framesize = 1 - elif self._encoding == AUDIO_FILE_ENCODING_LINEAR_8: - self._framesize = self._sampwidth = 1 - elif self._encoding == AUDIO_FILE_ENCODING_LINEAR_16: - self._framesize = self._sampwidth = 2 - elif self._encoding == AUDIO_FILE_ENCODING_LINEAR_24: - self._framesize = self._sampwidth = 3 - elif self._encoding == AUDIO_FILE_ENCODING_LINEAR_32: - self._framesize = self._sampwidth = 4 - else: - raise Error('unknown encoding') - self._framerate = int(_read_u32(file)) - self._nchannels = int(_read_u32(file)) - if not self._nchannels: - raise Error('bad # of channels') - self._framesize = self._framesize * self._nchannels - if self._hdr_size > 24: - self._info = file.read(self._hdr_size - 24) - self._info, _, _ = self._info.partition(b'\0') - else: - self._info = b'' - try: - self._data_pos = file.tell() - except (AttributeError, OSError): - self._data_pos = None - - def getfp(self): - return self._file - - def getnchannels(self): - return self._nchannels - - def getsampwidth(self): - return self._sampwidth - - def getframerate(self): - return self._framerate - - def getnframes(self): - if self._data_size == AUDIO_UNKNOWN_SIZE: - return AUDIO_UNKNOWN_SIZE - if self._encoding in _simple_encodings: - return self._data_size // self._framesize - return 0 # XXX--must do some arithmetic here - - def getcomptype(self): - if self._encoding == AUDIO_FILE_ENCODING_MULAW_8: - return 'ULAW' - elif self._encoding == AUDIO_FILE_ENCODING_ALAW_8: - return 'ALAW' - else: - return 'NONE' - - def getcompname(self): - if self._encoding == AUDIO_FILE_ENCODING_MULAW_8: - return 'CCITT G.711 u-law' - elif self._encoding == AUDIO_FILE_ENCODING_ALAW_8: - return 'CCITT G.711 A-law' - else: - return 'not compressed' - - def getparams(self): - return _sunau_params(self.getnchannels(), self.getsampwidth(), - self.getframerate(), self.getnframes(), - self.getcomptype(), self.getcompname()) - - def getmarkers(self): - return None - - def getmark(self, id): - raise Error('no marks') - - def readframes(self, nframes): - if self._encoding in _simple_encodings: - if nframes == AUDIO_UNKNOWN_SIZE: - data = self._file.read() - else: - data = self._file.read(nframes * self._framesize) - self._soundpos += len(data) // self._framesize - if self._encoding == AUDIO_FILE_ENCODING_MULAW_8: - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - data = audioop.ulaw2lin(data, self._sampwidth) - return data - return None # XXX--not implemented yet - - def rewind(self): - if self._data_pos is None: - raise OSError('cannot seek') - self._file.seek(self._data_pos) - self._soundpos = 0 - - def tell(self): - return self._soundpos - - def setpos(self, pos): - if pos < 0 or pos > self.getnframes(): - raise Error('position not in range') - if self._data_pos is None: - raise OSError('cannot seek') - self._file.seek(self._data_pos + pos * self._framesize) - self._soundpos = pos - - def close(self): - file = self._file - if file: - self._file = None - if self._opened: - file.close() - -class Au_write: - - def __init__(self, f): - if isinstance(f, str): - import builtins - f = builtins.open(f, 'wb') - self._opened = True - else: - self._opened = False - self.initfp(f) - - def __del__(self): - if self._file: - self.close() - self._file = None - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - def initfp(self, file): - self._file = file - self._framerate = 0 - self._nchannels = 0 - self._sampwidth = 0 - self._framesize = 0 - self._nframes = AUDIO_UNKNOWN_SIZE - self._nframeswritten = 0 - self._datawritten = 0 - self._datalength = 0 - self._info = b'' - self._comptype = 'ULAW' # default is U-law - - def setnchannels(self, nchannels): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - if nchannels not in (1, 2, 4): - raise Error('only 1, 2, or 4 channels supported') - 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 not in (1, 2, 3, 4): - raise Error('bad sample width') - self._sampwidth = sampwidth - - def getsampwidth(self): - if not self._framerate: - raise Error('sample width not specified') - return self._sampwidth - - def setframerate(self, framerate): - if self._nframeswritten: - raise Error('cannot change parameters after starting to write') - 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') - if nframes < 0: - raise Error('# of frames cannot be negative') - self._nframes = nframes - - def getnframes(self): - return self._nframeswritten - - def setcomptype(self, type, name): - if type in ('NONE', 'ULAW'): - self._comptype = type - else: - raise Error('unknown compression type') - - def getcomptype(self): - return self._comptype - - def getcompname(self): - if self._comptype == 'ULAW': - return 'CCITT G.711 u-law' - elif self._comptype == 'ALAW': - return 'CCITT G.711 A-law' - else: - return 'not compressed' - - def setparams(self, params): - nchannels, sampwidth, framerate, nframes, comptype, compname = params - self.setnchannels(nchannels) - self.setsampwidth(sampwidth) - self.setframerate(framerate) - self.setnframes(nframes) - self.setcomptype(comptype, compname) - - def getparams(self): - return _sunau_params(self.getnchannels(), self.getsampwidth(), - self.getframerate(), self.getnframes(), - self.getcomptype(), self.getcompname()) - - 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() - if self._comptype == 'ULAW': - with warnings.catch_warnings(): - warnings.simplefilter('ignore', category=DeprecationWarning) - import audioop - data = audioop.lin2ulaw(data, self._sampwidth) - nframes = len(data) // self._framesize - 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: - try: - self._ensure_header_written() - if self._nframeswritten != self._nframes or \ - self._datalength != self._datawritten: - self._patchheader() - self._file.flush() - finally: - file = self._file - self._file = None - if self._opened: - file.close() - - # - # private methods - # - - def _ensure_header_written(self): - if not self._nframeswritten: - if not self._nchannels: - raise Error('# of channels not specified') - if not self._sampwidth: - raise Error('sample width not specified') - if not self._framerate: - raise Error('frame rate not specified') - self._write_header() - - def _write_header(self): - if self._comptype == 'NONE': - if self._sampwidth == 1: - encoding = AUDIO_FILE_ENCODING_LINEAR_8 - self._framesize = 1 - elif self._sampwidth == 2: - encoding = AUDIO_FILE_ENCODING_LINEAR_16 - self._framesize = 2 - elif self._sampwidth == 3: - encoding = AUDIO_FILE_ENCODING_LINEAR_24 - self._framesize = 3 - elif self._sampwidth == 4: - encoding = AUDIO_FILE_ENCODING_LINEAR_32 - self._framesize = 4 - else: - raise Error('internal error') - elif self._comptype == 'ULAW': - encoding = AUDIO_FILE_ENCODING_MULAW_8 - self._framesize = 1 - else: - raise Error('internal error') - self._framesize = self._framesize * self._nchannels - _write_u32(self._file, AUDIO_FILE_MAGIC) - header_size = 25 + len(self._info) - header_size = (header_size + 7) & ~7 - _write_u32(self._file, header_size) - if self._nframes == AUDIO_UNKNOWN_SIZE: - length = AUDIO_UNKNOWN_SIZE - else: - length = self._nframes * self._framesize - try: - self._form_length_pos = self._file.tell() - except (AttributeError, OSError): - self._form_length_pos = None - _write_u32(self._file, length) - self._datalength = length - _write_u32(self._file, encoding) - _write_u32(self._file, self._framerate) - _write_u32(self._file, self._nchannels) - self._file.write(self._info) - self._file.write(b'\0'*(header_size - len(self._info) - 24)) - - def _patchheader(self): - if self._form_length_pos is None: - raise OSError('cannot seek') - self._file.seek(self._form_length_pos) - _write_u32(self._file, self._datawritten) - self._datalength = self._datawritten - self._file.seek(0, 2) - -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 Au_read(f) - elif mode in ('w', 'wb'): - return Au_write(f) - else: - raise Error("mode must be 'r', 'rb', 'w', or 'wb'") diff --git a/Lib/test/audiodata/pluck-pcm16.au b/Lib/test/audiodata/pluck-pcm16.au Binary files differdeleted file mode 100644 index 398f07f..0000000 --- a/Lib/test/audiodata/pluck-pcm16.au +++ /dev/null diff --git a/Lib/test/audiodata/pluck-pcm24.au b/Lib/test/audiodata/pluck-pcm24.au Binary files differdeleted file mode 100644 index 0bb2304..0000000 --- a/Lib/test/audiodata/pluck-pcm24.au +++ /dev/null diff --git a/Lib/test/audiodata/pluck-pcm32.au b/Lib/test/audiodata/pluck-pcm32.au Binary files differdeleted file mode 100644 index 92ee596..0000000 --- a/Lib/test/audiodata/pluck-pcm32.au +++ /dev/null diff --git a/Lib/test/audiodata/pluck-pcm8.au b/Lib/test/audiodata/pluck-pcm8.au Binary files differdeleted file mode 100644 index b7172c8..0000000 --- a/Lib/test/audiodata/pluck-pcm8.au +++ /dev/null diff --git a/Lib/test/audiodata/pluck-ulaw.au b/Lib/test/audiodata/pluck-ulaw.au Binary files differdeleted file mode 100644 index 1110353..0000000 --- a/Lib/test/audiodata/pluck-ulaw.au +++ /dev/null diff --git a/Lib/test/audiotest.au b/Lib/test/audiotest.au Binary files differdeleted file mode 100644 index f76b050..0000000 --- a/Lib/test/audiotest.au +++ /dev/null diff --git a/Lib/test/test_sunau.py b/Lib/test/test_sunau.py deleted file mode 100644 index 40408b0..0000000 --- a/Lib/test/test_sunau.py +++ /dev/null @@ -1,160 +0,0 @@ -import unittest -from test import audiotests -import io -import struct -import sys -from test.support import warnings_helper - -sunau = warnings_helper.import_deprecated("sunau") -audioop = warnings_helper.import_deprecated("audioop") - - -class SunauTest(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile): - module = sunau - - -class SunauPCM8Test(SunauTest, unittest.TestCase): - sndfilename = 'pluck-pcm8.au' - sndfilenframes = 3307 - nchannels = 2 - sampwidth = 1 - framerate = 11025 - nframes = 48 - comptype = 'NONE' - compname = 'not compressed' - frames = bytes.fromhex("""\ - 02FF 4B00 3104 8008 CB06 4803 BF01 03FE B8FA B4F3 29EB 1AE6 \ - EDE4 C6E2 0EE0 EFE0 57E2 FBE8 13EF D8F7 97FB F5FC 08FB DFFB \ - 11FA 3EFB BCFC 66FF CF04 4309 C10E 5112 EE17 8216 7F14 8012 \ - 490E 520D EF0F CE0F E40C 630A 080A 2B0B 510E 8B11 B60E 440A \ - """) - - -class SunauPCM16Test(SunauTest, unittest.TestCase): - sndfilename = 'pluck-pcm16.au' - sndfilenframes = 3307 - nchannels = 2 - sampwidth = 2 - framerate = 11025 - nframes = 48 - comptype = 'NONE' - compname = 'not compressed' - frames = bytes.fromhex("""\ - 022EFFEA 4B5C00F9 311404EF 80DB0844 CBE006B0 48AB03F3 BFE601B5 0367FE80 \ - B853FA42 B4AFF351 2997EBCD 1A5AE6DC EDF9E492 C627E277 0E06E0B7 EF29E029 \ - 5759E271 FB34E83F 1377EF85 D82CF727 978EFB79 F5F7FC12 0864FB9E DF30FB40 \ - 1183FA30 3EEAFB59 BC78FCB4 66D5FF60 CF130415 431A097D C1BA0EC7 512312A0 \ - EEE11754 82071666 7FFE1448 80001298 49990EB7 52B40DC1 EFAD0F65 CE3A0FBE \ - E4B70CE6 63490A57 08CC0A1D 2BBC0B09 51480E46 8BCB113C B6F60EE9 44150A5A \ - """) - - -class SunauPCM24Test(SunauTest, unittest.TestCase): - sndfilename = 'pluck-pcm24.au' - sndfilenframes = 3307 - nchannels = 2 - sampwidth = 3 - framerate = 11025 - nframes = 48 - comptype = 'NONE' - compname = 'not compressed' - frames = bytes.fromhex("""\ - 022D65FFEB9D 4B5A0F00FA54 3113C304EE2B 80DCD6084303 \ - CBDEC006B261 48A99803F2F8 BFE82401B07D 036BFBFE7B5D \ - B85756FA3EC9 B4B055F3502B 299830EBCB62 1A5CA7E6D99A \ - EDFA3EE491BD C625EBE27884 0E05A9E0B6CF EF2929E02922 \ - 5758D8E27067 FB3557E83E16 1377BFEF8402 D82C5BF7272A \ - 978F16FB7745 F5F865FC1013 086635FB9C4E DF30FCFB40EE \ - 117FE0FA3438 3EE6B8FB5AC3 BC77A3FCB2F4 66D6DAFF5F32 \ - CF13B9041275 431D69097A8C C1BB600EC74E 5120B912A2BA \ - EEDF641754C0 8207001664B7 7FFFFF14453F 8000001294E6 \ - 499C1B0EB3B2 52B73E0DBCA0 EFB2B20F5FD8 CE3CDB0FBE12 \ - E4B49C0CEA2D 6344A80A5A7C 08C8FE0A1FFE 2BB9860B0A0E \ - 51486F0E44E1 8BCC64113B05 B6F4EC0EEB36 4413170A5B48 \ - """) - - -class SunauPCM32Test(SunauTest, unittest.TestCase): - sndfilename = 'pluck-pcm32.au' - sndfilenframes = 3307 - nchannels = 2 - sampwidth = 4 - framerate = 11025 - nframes = 48 - comptype = 'NONE' - compname = 'not compressed' - frames = bytes.fromhex("""\ - 022D65BCFFEB9D92 4B5A0F8000FA549C 3113C34004EE2BC0 80DCD680084303E0 \ - CBDEC0C006B26140 48A9980003F2F8FC BFE8248001B07D92 036BFB60FE7B5D34 \ - B8575600FA3EC920 B4B05500F3502BC0 29983000EBCB6240 1A5CA7A0E6D99A60 \ - EDFA3E80E491BD40 C625EB80E27884A0 0E05A9A0E0B6CFE0 EF292940E0292280 \ - 5758D800E2706700 FB3557D8E83E1640 1377BF00EF840280 D82C5B80F7272A80 \ - 978F1600FB774560 F5F86510FC101364 086635A0FB9C4E20 DF30FC40FB40EE28 \ - 117FE0A0FA3438B0 3EE6B840FB5AC3F0 BC77A380FCB2F454 66D6DA80FF5F32B4 \ - CF13B980041275B0 431D6980097A8C00 C1BB60000EC74E00 5120B98012A2BAA0 \ - EEDF64C01754C060 820700001664B780 7FFFFFFF14453F40 800000001294E6E0 \ - 499C1B000EB3B270 52B73E000DBCA020 EFB2B2E00F5FD880 CE3CDB400FBE1270 \ - E4B49CC00CEA2D90 6344A8800A5A7CA0 08C8FE800A1FFEE0 2BB986C00B0A0E00 \ - 51486F800E44E190 8BCC6480113B0580 B6F4EC000EEB3630 441317800A5B48A0 \ - """) - - -class SunauULAWTest(SunauTest, unittest.TestCase): - sndfilename = 'pluck-ulaw.au' - sndfilenframes = 3307 - nchannels = 2 - sampwidth = 2 - framerate = 11025 - nframes = 48 - comptype = 'ULAW' - compname = 'CCITT G.711 u-law' - frames = bytes.fromhex("""\ - 022CFFE8 497C00F4 307C04DC 8284083C CB84069C 497C03DC BE8401AC 036CFE74 \ - B684FA24 B684F344 2A7CEC04 19FCE704 EE04E504 C584E204 0E3CE104 EF04DF84 \ - 557CE204 FB24E804 12FCEF04 D784F744 9684FB64 F5C4FC24 083CFBA4 DF84FB24 \ - 11FCFA24 3E7CFB64 BA84FCB4 657CFF5C CF84041C 417C09BC C1840EBC 517C12FC \ - EF0416FC 828415FC 7D7C13FC 828412FC 497C0EBC 517C0DBC F0040F3C CD840FFC \ - E5040CBC 617C0A3C 08BC0A3C 2C7C0B3C 517C0E3C 8A8410FC B6840EBC 457C0A3C \ - """) - if sys.byteorder != 'big': - frames = audioop.byteswap(frames, 2) - - -class SunauLowLevelTest(unittest.TestCase): - - def test_read_bad_magic_number(self): - b = b'SPA' - with self.assertRaises(EOFError): - sunau.open(io.BytesIO(b)) - b = b'SPAM' - with self.assertRaisesRegex(sunau.Error, 'bad magic number'): - sunau.open(io.BytesIO(b)) - - def test_read_too_small_header(self): - b = struct.pack('>LLLLL', sunau.AUDIO_FILE_MAGIC, 20, 0, - sunau.AUDIO_FILE_ENCODING_LINEAR_8, 11025) - with self.assertRaisesRegex(sunau.Error, 'header size too small'): - sunau.open(io.BytesIO(b)) - - def test_read_too_large_header(self): - b = struct.pack('>LLLLLL', sunau.AUDIO_FILE_MAGIC, 124, 0, - sunau.AUDIO_FILE_ENCODING_LINEAR_8, 11025, 1) - b += b'\0' * 100 - with self.assertRaisesRegex(sunau.Error, 'header size ridiculously large'): - sunau.open(io.BytesIO(b)) - - def test_read_wrong_encoding(self): - b = struct.pack('>LLLLLL', sunau.AUDIO_FILE_MAGIC, 24, 0, 0, 11025, 1) - with self.assertRaisesRegex(sunau.Error, r'encoding not \(yet\) supported'): - sunau.open(io.BytesIO(b)) - - def test_read_wrong_number_of_channels(self): - b = struct.pack('>LLLLLL', sunau.AUDIO_FILE_MAGIC, 24, 0, - sunau.AUDIO_FILE_ENCODING_LINEAR_8, 11025, 0) - with self.assertRaisesRegex(sunau.Error, 'bad # of channels'): - sunau.open(io.BytesIO(b)) - - -if __name__ == "__main__": - unittest.main() diff --git a/Misc/NEWS.d/3.7.0b3.rst b/Misc/NEWS.d/3.7.0b3.rst index 547fb50..9801106 100644 --- a/Misc/NEWS.d/3.7.0b3.rst +++ b/Misc/NEWS.d/3.7.0b3.rst @@ -326,7 +326,7 @@ documentation. Improved exceptions raised for invalid number of channels and sample width when read an audio file in modules :mod:`aifc`, :mod:`wave` and -:mod:`sunau`. +:mod:`!sunau`. .. diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index 2564167..75902b4 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -5577,7 +5577,7 @@ documentation. Improved exceptions raised for invalid number of channels and sample width when read an audio file in modules :mod:`aifc`, :mod:`wave` and -:mod:`sunau`. +:mod:`!sunau`. .. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst b/Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst new file mode 100644 index 0000000..fc103cd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst @@ -0,0 +1,2 @@ +:pep:`594`: Remove the :mod:`!sunau` 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 fe396a8..37d5c05 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -248,7 +248,6 @@ static const char* _Py_stdlib_module_names[] = { "stringprep", "struct", "subprocess", -"sunau", "symtable", "sys", "sysconfig", diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index a2ec54e..47bc238 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -84,7 +84,7 @@ OMIT_NETWORKING_FILES = ( OMIT_MODULE_FILES = { "_asyncio": ["asyncio/"], - "audioop": ["aifc.py", "sunau.py", "wave.py"], + "audioop": ["aifc.py", "wave.py"], "_crypt": ["crypt.py"], "_curses": ["curses/"], "_ctypes": ["ctypes/"], |