gh-75593: Add support of bytes and path-like paths in wave.open() (GH-140951)

This commit is contained in:
Mark Byrne 2025-11-12 09:20:55 +01:00 committed by GitHub
parent f1b7961ccf
commit 35908265b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 33 additions and 4 deletions

View file

@ -25,8 +25,9 @@ The :mod:`wave` module defines the following function and exception:
.. function:: open(file, mode=None) .. function:: open(file, mode=None)
If *file* is a string, open the file by that name, otherwise treat it as a If *file* is a string, a :term:`path-like object` or a
file-like object. *mode* can be: :term:`bytes-like object` open the file by that name, otherwise treat it as
a file-like object. *mode* can be:
``'rb'`` ``'rb'``
Read only mode. Read only mode.
@ -52,6 +53,10 @@ The :mod:`wave` module defines the following function and exception:
.. versionchanged:: 3.4 .. versionchanged:: 3.4
Added support for unseekable files. Added support for unseekable files.
.. versionchanged:: 3.15
Added support for :term:`path-like objects <path-like object>`
and :term:`bytes-like objects <bytes-like object>`.
.. exception:: Error .. exception:: Error
An error raised when something is impossible because it violates the WAV An error raised when something is impossible because it violates the WAV

View file

@ -1,9 +1,11 @@
import unittest import unittest
from test import audiotests from test import audiotests
from test import support from test import support
from test.support.os_helper import FakePath
import io import io
import os import os
import struct import struct
import tempfile
import sys import sys
import wave import wave
@ -206,5 +208,25 @@ def test_open_in_write_raises(self):
self.assertIsNone(cm.unraisable) self.assertIsNone(cm.unraisable)
class WaveOpen(unittest.TestCase):
def test_open_pathlike(self):
"""It is possible to use `wave.read` and `wave.write` with a path-like object"""
with tempfile.NamedTemporaryFile(delete_on_close=False) as fp:
cases = (
FakePath(fp.name),
FakePath(os.fsencode(fp.name)),
os.fsencode(fp.name),
)
for fake_path in cases:
with self.subTest(fake_path):
with wave.open(fake_path, 'wb') as f:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(44100)
with wave.open(fake_path, 'rb') as f:
pass
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View file

@ -69,6 +69,7 @@
from collections import namedtuple from collections import namedtuple
import builtins import builtins
import os
import struct import struct
import sys import sys
@ -274,7 +275,7 @@ def initfp(self, file):
def __init__(self, f): def __init__(self, f):
self._i_opened_the_file = None self._i_opened_the_file = None
if isinstance(f, str): if isinstance(f, (bytes, str, os.PathLike)):
f = builtins.open(f, 'rb') f = builtins.open(f, 'rb')
self._i_opened_the_file = f self._i_opened_the_file = f
# else, assume it is an open file object already # else, assume it is an open file object already
@ -431,7 +432,7 @@ class Wave_write:
def __init__(self, f): def __init__(self, f):
self._i_opened_the_file = None self._i_opened_the_file = None
if isinstance(f, str): if isinstance(f, (bytes, str, os.PathLike)):
f = builtins.open(f, 'wb') f = builtins.open(f, 'wb')
self._i_opened_the_file = f self._i_opened_the_file = f
try: try:

View file

@ -0,0 +1 @@
Add support of :term:`path-like objects <path-like object>` and :term:`bytes-like objects <bytes-like object>` in :func:`wave.open`.