diff options
author | Pablo Galindo <Pablogsal@gmail.com> | 2019-02-18 10:46:34 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-18 10:46:34 (GMT) |
commit | 09fbcd6085e18b534fd4161844ff39f77eb4a082 (patch) | |
tree | 18814d4cc2ac1949afac68a27474645973f835f5 | |
parent | ac28147e78c45a6217d348ce90ca5281d91f676f (diff) | |
download | cpython-09fbcd6085e18b534fd4161844ff39f77eb4a082.zip cpython-09fbcd6085e18b534fd4161844ff39f77eb4a082.tar.gz cpython-09fbcd6085e18b534fd4161844ff39f77eb4a082.tar.bz2 |
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.
-rw-r--r-- | Lib/test/test_os.py | 19 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2019-02-18-09-30-55.bpo-35942.oLhL2v.rst | 3 | ||||
-rw-r--r-- | Modules/posixmodule.c | 23 |
3 files changed, 36 insertions, 9 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index b7e1c45..d478c64 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3344,7 +3344,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: @@ -3357,6 +3357,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 0000000..6ad4c0d --- /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 5995958..05afe9e 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -954,28 +954,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) { |