Skip to content

Commit ff287a7

Browse files
authored
gh-144975: Fix wave.Wave_write.setframerate() validation order (GH-144976)
Validate the frame rate after rounding to an integer, not before. This prevents values like 0.5 from passing validation (0.5 > 0) but then rounding to 0, which would cause a confusing delayed error "sampling rate not specified" when writing frames. With this fix, setframerate(0.5) immediately raises "bad frame rate", providing clear feedback at the point of the error.
1 parent dc24b8a commit ff287a7

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

Lib/test/test_wave.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,43 @@ def test_open_in_write_raises(self):
207207
support.gc_collect()
208208
self.assertIsNone(cm.unraisable)
209209

210+
@support.subTests('arg', (
211+
# rounds to 0, should raise:
212+
0.5,
213+
0.4,
214+
# Negative values should still raise:
215+
-1,
216+
-0.5,
217+
-0.4,
218+
# 0 should raise:
219+
0,
220+
))
221+
def test_setframerate_validates_rounded_values(self, arg):
222+
"""Test that setframerate that round to 0 or negative are rejected"""
223+
with wave.open(io.BytesIO(), 'wb') as f:
224+
f.setnchannels(1)
225+
f.setsampwidth(2)
226+
with self.assertRaises(wave.Error):
227+
f.setframerate(arg)
228+
with self.assertRaises(wave.Error):
229+
f.close()
230+
231+
@support.subTests(('arg', 'expected'), (
232+
(1.4, 1),
233+
(1.5, 2),
234+
(1.6, 2),
235+
(44100.4, 44100),
236+
(44100.5, 44100),
237+
(44100.6, 44101),
238+
))
239+
def test_setframerate_rounds(self, arg, expected):
240+
"""Test that setframerate is rounded"""
241+
with wave.open(io.BytesIO(), 'wb') as f:
242+
f.setnchannels(1)
243+
f.setsampwidth(2)
244+
f.setframerate(arg)
245+
self.assertEqual(f.getframerate(), expected)
246+
210247

211248
class WaveOpen(unittest.TestCase):
212249
def test_open_pathlike(self):

Lib/wave.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,10 @@ def getsampwidth(self):
493493
def setframerate(self, framerate):
494494
if self._datawritten:
495495
raise Error('cannot change parameters after starting to write')
496+
framerate = int(round(framerate))
496497
if framerate <= 0:
497498
raise Error('bad frame rate')
498-
self._framerate = int(round(framerate))
499+
self._framerate = framerate
499500

500501
def getframerate(self):
501502
if not self._framerate:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:meth:`wave.Wave_write.setframerate` now validates the frame rate after
2+
rounding to an integer, preventing values like ``0.5`` from being accepted
3+
and causing confusing errors later. Patch by Michiel Beijen.

0 commit comments

Comments
 (0)