Skip to content

GH-132445: Allowing to reset parameters of Wave_write #132448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions Doc/library/wave.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,20 @@ Wave_write Objects

Set the number of channels.

Raises an :exc:`wave.Error`, if the value is set after data was written.

.. versionchanged:: 3.14
:exc:`wave.Error` is not raised, if the value is the same.

.. method:: setsampwidth(n)

Set the sample width to *n* bytes.

Raises an :exc:`wave.Error`, if the value is set after data was written.

.. versionchanged:: 3.14
:exc:`wave.Error` is not raised, if the value is the same.


.. method:: setframerate(n)

Expand All @@ -212,26 +221,43 @@ Wave_write Objects
A non-integral input to this method is rounded to the nearest
integer.

Raises an :exc:`wave.Error`, if the value is set after data was written.

.. versionchanged:: 3.14
:exc:`wave.Error` is not raised, if the value is the same.


.. method:: setnframes(n)

Set the number of frames to *n*. This will be changed later if the number
of frames actually written is different (this update attempt will
raise an error if the output stream is not seekable).

Raises an :exc:`wave.Error`, if the value is set after data was written.

.. versionchanged:: 3.14
:exc:`wave.Error` is not raised, if the value is the same.

.. method:: setcomptype(type, name)

Set the compression type and description. At the moment, only compression type
``NONE`` is supported, meaning no compression.

Raises an Error, if the value is set after data was written.

.. versionchanged:: 3.14
:exc:`wave.Error` is not raised, if the value is the same.

.. method:: setparams(tuple)

The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype,
compname)``, with values valid for the ``set*()`` methods. Sets all
parameters.

Raises an :exc:`wave.Error`, if the value is set after data was written.

.. versionchanged:: 3.14
:exc:`wave.Error` is not raised, if the value is the same.

.. method:: tell()

Expand All @@ -257,6 +283,6 @@ Wave_write Objects
.. versionchanged:: 3.4
Any :term:`bytes-like object` is now accepted.

Note that it is invalid to set any parameters after calling :meth:`writeframes`
Note that it is invalid to change any parameters after calling :meth:`writeframes`
or :meth:`writeframesraw`, and any attempt to do so will raise
:exc:`wave.Error`.
:exc:`wave.Error`, if the value is different from the current value.
33 changes: 33 additions & 0 deletions Lib/test/test_wave.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,39 @@ def test_write_deprecations(self):
with self.assertWarns(DeprecationWarning):
self.assertIsNone(writer.getmarkers())

def test_setters(self):
with io.BytesIO(b'') as tmpfile:
with wave.open(tmpfile, 'wb') as writer:
writer.setnchannels(1)
writer.setsampwidth(1)
writer.setframerate(1)
writer.setcomptype('NONE', 'not compressed')

# no errors, when chaning and nothing was written
writer.setnchannels(2)
writer.setsampwidth(2)
writer.setframerate(2)
writer.setcomptype('NONE', 'uncompressed')

# write some frames
writer.writeframes(b'\0' * 16)

# changeing now should result in an error
with self.assertRaises(wave.Error):
writer.setnchannels(1)
with self.assertRaises(wave.Error):
writer.setsampwidth(1)
with self.assertRaises(wave.Error):
writer.setframerate(1)
with self.assertRaises(wave.Error):
writer.setcomptype('NONE', 'other')

# same value, so it should not raise Error
writer.setnchannels(2)
writer.setsampwidth(2)
writer.setframerate(2)
writer.setcomptype('NONE', 'uncompressed')


class WaveLowLevelTest(unittest.TestCase):

Expand Down
19 changes: 10 additions & 9 deletions Lib/wave.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ def __exit__(self, *args):
# User visible methods.
#
def setnchannels(self, nchannels):
if self._datawritten:
if self._datawritten and self._nchannels != nchannels:
raise Error('cannot change parameters after starting to write')
if nchannels < 1:
raise Error('bad # of channels')
Expand All @@ -490,7 +490,7 @@ def getnchannels(self):
return self._nchannels

def setsampwidth(self, sampwidth):
if self._datawritten:
if self._datawritten and self._sampwidth != sampwidth:
raise Error('cannot change parameters after starting to write')
if sampwidth < 1 or sampwidth > 4:
raise Error('bad sample width')
Expand All @@ -502,27 +502,28 @@ def getsampwidth(self):
return self._sampwidth

def setframerate(self, framerate):
if self._datawritten:
rounded_framerate = int(round(framerate))
if self._datawritten and self._framerate != rounded_framerate:
raise Error('cannot change parameters after starting to write')
if framerate <= 0:
if rounded_framerate <= 0:
raise Error('bad frame rate')
self._framerate = int(round(framerate))
self._framerate = rounded_framerate

def getframerate(self):
if not self._framerate:
raise Error('frame rate not set')
return self._framerate

def setnframes(self, nframes):
if self._datawritten:
if self._datawritten and self._nframes != nframes:
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._datawritten:
if self._datawritten and (self._comptype != comptype or self._compname != compname):
raise Error('cannot change parameters after starting to write')
if comptype not in ('NONE',):
raise Error('unsupported compression type')
Expand All @@ -537,8 +538,8 @@ def getcompname(self):

def setparams(self, params):
nchannels, sampwidth, framerate, nframes, comptype, compname = params
if self._datawritten:
raise Error('cannot change parameters after starting to write')
# no check for value change required: either the properties have the same
# value or they throw the exception them selfs
self.setnchannels(nchannels)
self.setsampwidth(sampwidth)
self.setframerate(framerate)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:class:`Wave_write` setters don't raise an error anymore, if the value did not change after frames were written.
Loading