diff --git a/include/pybind11/stl/filesystem.h b/include/pybind11/stl/filesystem.h index 52d2962107..56665b5c16 100644 --- a/include/pybind11/stl/filesystem.h +++ b/include/pybind11/stl/filesystem.h @@ -58,7 +58,13 @@ struct path_caster { return nullptr; } - bool load(handle handle, bool) { + bool load(handle handle, bool convert) { + if (!convert + && PyObject_IsInstance(handle.ptr(), module_::import("pathlib").attr("Path").ptr()) + != 1) { + return false; + } + // PyUnicode_FSConverter and PyUnicode_FSDecoder normally take care of // calling PyOS_FSPath themselves, but that's broken on PyPy (PyPy // issue #3168) so we do it ourselves instead. diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index 6084d517df..55ec708522 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -456,6 +456,10 @@ TEST_SUBMODULE(stl, m) { // test_fs_path m.attr("has_filesystem") = true; m.def("parent_path", [](const std::filesystem::path &path) { return path.parent_path(); }); + m.def( + "parent_path_noconvert", + [](const std::filesystem::path &path) { return path.parent_path(); }, + py::arg("arg0").noconvert()); m.def("parent_paths", [](const std::vector &paths) { std::vector result; result.reserve(paths.size()); diff --git a/tests/test_stl.py b/tests/test_stl.py index 4a57635e27..b2d8c16232 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -279,6 +279,16 @@ def __fspath__(self): assert m.parent_path(b"foo/bar") == Path("foo") assert m.parent_path(PseudoStrPath()) == Path("foo") assert m.parent_path(PseudoBytesPath()) == Path("foo") + # Single argument noconvert + assert m.parent_path_noconvert(Path("foo/bar")) == Path("foo") + with pytest.raises(TypeError): + m.parent_path_noconvert("foo/bar") + with pytest.raises(TypeError): + m.parent_path_noconvert(b"foo/bar") + with pytest.raises(TypeError): + m.parent_path_noconvert(PseudoStrPath()) + with pytest.raises(TypeError): + m.parent_path_noconvert(PseudoBytesPath()) # std::vector assert m.parent_paths(["foo/bar", "foo/baz"]) == [Path("foo"), Path("foo")] # py::typing::List @@ -311,6 +321,11 @@ def test_path_typing(doc): doc(m.parent_path) == "parent_path(arg0: os.PathLike | str | bytes) -> pathlib.Path" ) + # Single argument noconvert + assert ( + doc(m.parent_path_noconvert) + == "parent_path_noconvert(arg0: pathlib.Path) -> pathlib.Path" + ) # std::vector assert ( doc(m.parent_paths)