summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2019-02-18 10:46:34 (GMT)
committerGitHub <noreply@github.com>2019-02-18 10:46:34 (GMT)
commit09fbcd6085e18b534fd4161844ff39f77eb4a082 (patch)
tree18814d4cc2ac1949afac68a27474645973f835f5
parentac28147e78c45a6217d348ce90ca5281d91f676f (diff)
downloadcpython-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.py19
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2019-02-18-09-30-55.bpo-35942.oLhL2v.rst3
-rw-r--r--Modules/posixmodule.c23
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) {