From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Mon, 18 Feb 2019 11:05:52 +0000 (-0800) Subject: bpo-35942: Improve the error message if __fspath__ returns invalid types in path_conv... X-Git-Tag: v3.7.3rc1~72 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a01065a3588d3f0d0c57ea35107aa97e722fe2b2;p=thirdparty%2FPython%2Fcpython.git bpo-35942: Improve the error message if __fspath__ returns invalid types in path_converter (GH-11831) The error message emitted when returning invalid types from __fspath__ in interfaces that allow passing PathLike objects has been improved and now it does explain the origin of the error. (cherry picked from commit 09fbcd6085e18b534fd4161844ff39f77eb4a082) Co-authored-by: Pablo Galindo --- diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index ff22fbeee7b1..06144713633b 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3297,7 +3297,7 @@ class PathTConverterTests(unittest.TestCase): cleanup_fn(result) with self.assertRaisesRegex( - TypeError, 'should be string, bytes'): + TypeError, 'to return str or bytes'): fn(int_fspath, *extra_args) if allow_fd: @@ -3310,6 +3310,23 @@ class PathTConverterTests(unittest.TestCase): 'os.PathLike'): fn(fd, *extra_args) + def test_path_t_converter_and_custom_class(self): + with self.assertRaisesRegex( + TypeError, + '__fspath__\(\) to return str or bytes, not int' + ): + os.stat(FakePath(2)) + with self.assertRaisesRegex( + TypeError, + '__fspath__\(\) to return str or bytes, not float' + ): + os.stat(FakePath(2.34)) + with self.assertRaisesRegex( + TypeError, + '__fspath__\(\) to return str or bytes, not object' + ): + os.stat(FakePath(object())) + @unittest.skipUnless(hasattr(os, 'get_blocking'), 'needs os.get_blocking() and os.set_blocking()') diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-02-18-09-30-55.bpo-35942.oLhL2v.rst b/Misc/NEWS.d/next/Core and Builtins/2019-02-18-09-30-55.bpo-35942.oLhL2v.rst new file mode 100644 index 000000000000..6ad4c0df2a81 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-02-18-09-30-55.bpo-35942.oLhL2v.rst @@ -0,0 +1,3 @@ +The error message emmited when returning invalid types from ``__fspath__`` +in interfaces that allow passing :class:`~os.PathLike` objects has been +improved and now it does explain the origin of the error. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e587ed23c29f..e7a1f987def9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -979,28 +979,35 @@ path_converter(PyObject *o, void *p) if (!is_index && !is_buffer && !is_unicode && !is_bytes) { /* Inline PyOS_FSPath() for better error messages. */ _Py_IDENTIFIER(__fspath__); - PyObject *func = NULL; + PyObject *func, *res; func = _PyObject_LookupSpecial(o, &PyId___fspath__); if (NULL == func) { goto error_format; } - /* still owns a reference to the original object */ - Py_DECREF(o); - o = _PyObject_CallNoArg(func); + res = _PyObject_CallNoArg(func); Py_DECREF(func); - if (NULL == o) { + if (NULL == res) { goto error_exit; } - else if (PyUnicode_Check(o)) { + else if (PyUnicode_Check(res)) { is_unicode = 1; } - else if (PyBytes_Check(o)) { + else if (PyBytes_Check(res)) { is_bytes = 1; } else { - goto error_format; + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", Py_TYPE(o)->tp_name, + Py_TYPE(res)->tp_name); + Py_DECREF(res); + goto error_exit; } + + /* still owns a reference to the original object */ + Py_DECREF(o); + o = res; } if (is_unicode) {