Skip to content

Commit 0273641

Browse files
committed
gh-144975: Fix wave.Wave_write.setframerate() validation order
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 16ccdbc commit 0273641

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

Lib/test/test_wave.py

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

210+
def test_setframerate_rounds_then_validates(self):
211+
"""Test that setframerate rounds before validation"""
212+
# Test that framerates that round to 0 or negative are rejected
213+
with wave.open(io.BytesIO(), 'wb') as f:
214+
f.setnchannels(1)
215+
f.setsampwidth(2)
216+
# 0.5 rounds to 0, should raise
217+
with self.assertRaises(wave.Error):
218+
f.setframerate(0.5)
219+
# 0.4 rounds to 0, should raise
220+
with self.assertRaises(wave.Error):
221+
f.setframerate(0.4)
222+
# Negative values should still raise
223+
with self.assertRaises(wave.Error):
224+
f.setframerate(-1)
225+
with self.assertRaises(wave.Error):
226+
f.setframerate(-0.5)
227+
# 0 should raise
228+
with self.assertRaises(wave.Error):
229+
f.setframerate(0)
230+
231+
# Valid values that round to positive integers should work
232+
f.setframerate(1.4) # rounds to 1
233+
self.assertEqual(f.getframerate(), 1)
234+
f.setframerate(1.5) # rounds to 2
235+
self.assertEqual(f.getframerate(), 2)
236+
f.setframerate(1.6) # rounds to 2
237+
self.assertEqual(f.getframerate(), 2)
238+
f.setframerate(44100.4) # rounds to 44100
239+
self.assertEqual(f.getframerate(), 44100)
240+
f.setframerate(44100.5) # rounds to 44100
241+
self.assertEqual(f.getframerate(), 44100)
242+
210243

211244
class WaveOpen(unittest.TestCase):
212245
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)