summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/sunau.rst274
-rw-r--r--Doc/library/superseded.rst1
-rw-r--r--Doc/tools/.nitignore1
-rw-r--r--Doc/whatsnew/3.11.rst2
-rw-r--r--Doc/whatsnew/3.12.rst2
-rw-r--r--Doc/whatsnew/3.13.rst3
-rw-r--r--Doc/whatsnew/3.4.rst8
-rw-r--r--Doc/whatsnew/3.7.rst4
-rw-r--r--Lib/sunau.py533
-rw-r--r--Lib/test/audiodata/pluck-pcm16.aubin13252 -> 0 bytes
-rw-r--r--Lib/test/audiodata/pluck-pcm24.aubin19866 -> 0 bytes
-rw-r--r--Lib/test/audiodata/pluck-pcm32.aubin26480 -> 0 bytes
-rw-r--r--Lib/test/audiodata/pluck-pcm8.aubin6638 -> 0 bytes
-rw-r--r--Lib/test/audiodata/pluck-ulaw.aubin6638 -> 0 bytes
-rw-r--r--Lib/test/audiotest.aubin28144 -> 0 bytes
-rw-r--r--Lib/test/test_sunau.py160
-rw-r--r--Misc/NEWS.d/3.7.0b3.rst2
-rw-r--r--Misc/NEWS.d/3.8.0a1.rst2
-rw-r--r--Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst2
-rw-r--r--Python/stdlib_module_names.h1
-rwxr-xr-xTools/wasm/wasm_assets.py2
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
deleted file mode 100644
index 398f07f..0000000
--- a/Lib/test/audiodata/pluck-pcm16.au
+++ /dev/null
Binary files differ
diff --git a/Lib/test/audiodata/pluck-pcm24.au b/Lib/test/audiodata/pluck-pcm24.au
deleted file mode 100644
index 0bb2304..0000000
--- a/Lib/test/audiodata/pluck-pcm24.au
+++ /dev/null
Binary files differ
diff --git a/Lib/test/audiodata/pluck-pcm32.au b/Lib/test/audiodata/pluck-pcm32.au
deleted file mode 100644
index 92ee596..0000000
--- a/Lib/test/audiodata/pluck-pcm32.au
+++ /dev/null
Binary files differ
diff --git a/Lib/test/audiodata/pluck-pcm8.au b/Lib/test/audiodata/pluck-pcm8.au
deleted file mode 100644
index b7172c8..0000000
--- a/Lib/test/audiodata/pluck-pcm8.au
+++ /dev/null
Binary files differ
diff --git a/Lib/test/audiodata/pluck-ulaw.au b/Lib/test/audiodata/pluck-ulaw.au
deleted file mode 100644
index 1110353..0000000
--- a/Lib/test/audiodata/pluck-ulaw.au
+++ /dev/null
Binary files differ
diff --git a/Lib/test/audiotest.au b/Lib/test/audiotest.au
deleted file mode 100644
index f76b050..0000000
--- a/Lib/test/audiotest.au
+++ /dev/null
Binary files differ
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/"],