[Python-checkins] gh-91061: also accept pathlib.Path for winsound.PlaySound (#91489)

JelleZijlstra webhook-mailer at python.org
Sun May 22 21:54:32 EDT 2022


https://github.com/python/cpython/commit/9bc616cb4cd0610c21611554b50791f4d4c850e8
commit: 9bc616cb4cd0610c21611554b50791f4d4c850e8
branch: main
author: Mori Bellamy <mori at invoked.net>
committer: JelleZijlstra <jelle.zijlstra at gmail.com>
date: 2022-05-22T18:54:24-07:00
summary:

gh-91061: also accept pathlib.Path for winsound.PlaySound (#91489)

Fixes #91061

Co-authored-by: Jelle Zijlstra <jelle.zijlstra at gmail.com>

files:
A Misc/NEWS.d/next/Windows/2022-04-12-18-35-20.gh-issue-91061.x40hSK.rst
M Lib/test/test_winsound.py
M PC/winsound.c

diff --git a/Lib/test/test_winsound.py b/Lib/test/test_winsound.py
index 3c3359b9004fd..a59d0d24f5db4 100644
--- a/Lib/test/test_winsound.py
+++ b/Lib/test/test_winsound.py
@@ -1,6 +1,7 @@
 # Ridiculously simple test of the winsound module for Windows.
 
 import functools
+import pathlib
 import time
 import unittest
 
@@ -84,6 +85,13 @@ def test_keyword_args(self):
         safe_MessageBeep(type=winsound.MB_OK)
 
 
+# A class for testing winsound when the given path resolves
+# to bytes rather than str.
+class BytesPath(pathlib.WindowsPath):
+    def __fspath__(self):
+        return bytes(super().__fspath__(), 'UTF-8')
+
+
 class PlaySoundTest(unittest.TestCase):
 
     def test_errors(self):
@@ -116,6 +124,20 @@ def test_snd_filename(self):
         fn = support.findfile('pluck-pcm8.wav', subdir='audiodata')
         safe_PlaySound(fn, winsound.SND_FILENAME | winsound.SND_NODEFAULT)
 
+    def test_snd_filepath(self):
+        fn = support.findfile('pluck-pcm8.wav', subdir='audiodata')
+        path = pathlib.Path(fn)
+        safe_PlaySound(path, winsound.SND_FILENAME | winsound.SND_NODEFAULT)
+
+    def test_snd_filepath_as_bytes(self):
+        fn = support.findfile('pluck-pcm8.wav', subdir='audiodata')
+        self.assertRaises(
+            TypeError,
+            winsound.PlaySound,
+            BytesPath(fn),
+            winsound.SND_FILENAME | winsound.SND_NODEFAULT
+        )
+
     def test_aliases(self):
         aliases = [
             "SystemAsterisk",
diff --git a/Misc/NEWS.d/next/Windows/2022-04-12-18-35-20.gh-issue-91061.x40hSK.rst b/Misc/NEWS.d/next/Windows/2022-04-12-18-35-20.gh-issue-91061.x40hSK.rst
new file mode 100644
index 0000000000000..aadc303442025
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2022-04-12-18-35-20.gh-issue-91061.x40hSK.rst
@@ -0,0 +1 @@
+Accept os.PathLike for the argument to winsound.PlaySound
diff --git a/PC/winsound.c b/PC/winsound.c
index fd04e1e55b5fc..65025ddc5e1f5 100644
--- a/PC/winsound.c
+++ b/PC/winsound.c
@@ -94,17 +94,25 @@ winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags)
             return NULL;
         }
         wsound = (wchar_t *)view.buf;
+    } else if (PyBytes_Check(sound)) {
+        PyErr_Format(PyExc_TypeError,
+                     "'sound' must be str, os.PathLike, or None, not '%s'",
+                     Py_TYPE(sound)->tp_name);
+        return NULL;
     } else {
-        if (!PyUnicode_Check(sound)) {
+        PyObject *obj = PyOS_FSPath(sound);
+        // Either <obj> is unicode/bytes/NULL, or a helpful message
+        // has been surfaced to the user about how they gave a non-path.
+        if (obj == NULL) return NULL;
+        if (PyBytes_Check(obj)) {
             PyErr_Format(PyExc_TypeError,
-                         "'sound' must be str or None, not '%s'",
-                         Py_TYPE(sound)->tp_name);
-            return NULL;
-        }
-        wsound = PyUnicode_AsWideCharString(sound, NULL);
-        if (wsound == NULL) {
+                         "'sound' must resolve to str, not bytes");
+            Py_DECREF(obj);
             return NULL;
         }
+        wsound = PyUnicode_AsWideCharString(obj, NULL);
+        Py_DECREF(obj);
+        if (wsound == NULL) return NULL;
     }
 
 



More information about the Python-checkins mailing list