diff --git a/examples/pyo3-pytests/src/lib.rs b/examples/pyo3-pytests/src/lib.rs index 0dea9c03679..ed0b818038d 100644 --- a/examples/pyo3-pytests/src/lib.rs +++ b/examples/pyo3-pytests/src/lib.rs @@ -8,6 +8,7 @@ pub mod dict_iter; pub mod misc; pub mod objstore; pub mod othermod; +pub mod path; pub mod pyclass_iter; pub mod subclassing; @@ -17,6 +18,7 @@ use dict_iter::*; use misc::*; use objstore::*; use othermod::*; +use path::*; use pyclass_iter::*; use subclassing::*; @@ -28,6 +30,7 @@ fn pyo3_pytests(py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(misc))?; m.add_wrapped(wrap_pymodule!(objstore))?; m.add_wrapped(wrap_pymodule!(othermod))?; + m.add_wrapped(wrap_pymodule!(path))?; m.add_wrapped(wrap_pymodule!(pyclass_iter))?; m.add_wrapped(wrap_pymodule!(subclassing))?; @@ -42,6 +45,7 @@ fn pyo3_pytests(py: Python, m: &PyModule) -> PyResult<()> { sys_modules.set_item("pyo3_pytests.misc", m.getattr("misc")?)?; sys_modules.set_item("pyo3_pytests.objstore", m.getattr("objstore")?)?; sys_modules.set_item("pyo3_pytests.othermod", m.getattr("othermod")?)?; + sys_modules.set_item("pyo3_pytests.path", m.getattr("path")?)?; sys_modules.set_item("pyo3_pytests.pyclass_iter", m.getattr("pyclass_iter")?)?; sys_modules.set_item("pyo3_pytests.subclassing", m.getattr("subclassing")?)?; diff --git a/examples/pyo3-pytests/src/path.rs b/examples/pyo3-pytests/src/path.rs new file mode 100644 index 00000000000..d3214aa0c91 --- /dev/null +++ b/examples/pyo3-pytests/src/path.rs @@ -0,0 +1,21 @@ +use pyo3::prelude::*; +use pyo3::wrap_pyfunction; +use std::path::{Path, PathBuf}; + +#[pyfunction] +fn make_path() -> PathBuf { + Path::new("/root").to_owned() +} + +#[pyfunction] +fn take_pathbuf(path: PathBuf) -> PathBuf { + path +} + +#[pymodule] +fn path(_py: Python<'_>, m: &PyModule) -> PyResult<()> { + m.add_function(wrap_pyfunction!(make_path, m)?)?; + m.add_function(wrap_pyfunction!(take_pathbuf, m)?)?; + + Ok(()) +} diff --git a/examples/pyo3-pytests/tests/test_path.py b/examples/pyo3-pytests/tests/test_path.py new file mode 100644 index 00000000000..84a0981612c --- /dev/null +++ b/examples/pyo3-pytests/tests/test_path.py @@ -0,0 +1,18 @@ +import pathlib + +import pyo3_pytests.path as rpath + + +def test_make_path(): + p = rpath.make_path() + assert p == "/root" + + +def test_take_pathbuf(): + p = "/root" + assert rpath.take_pathbuf(p) == p + + +def test_take_pathlib(): + p = pathlib.Path("/root") + assert rpath.take_pathbuf(p) == str(p) \ No newline at end of file diff --git a/src/conversions/osstr.rs b/src/conversions/osstr.rs index 466a4417b86..fefe8daf3f2 100644 --- a/src/conversions/osstr.rs +++ b/src/conversions/osstr.rs @@ -58,7 +58,22 @@ impl ToPyObject for OsStr { impl FromPyObject<'_> for OsString { fn extract(ob: &PyAny) -> PyResult { - let pystring = ::try_from(ob)?; // Cast PyAny to PyString + let pystring = match ::try_from(ob) { + // Cast PyAny to PyString + Ok(s) => s, + Err(err) => { + let py = ob.py(); + let pathlib = py.import("pathlib")?; + let pathlib_path = pathlib.getattr("Path")?; + // FIXME: right way to get the type object of pathlib.Path? + let path_instance = pathlib_path.call0()?; + if path_instance.get_type().is_instance(ob)? { + ob.call_method0("__str__")? + } else { + return Err(err.into()); + } + } + }; #[cfg(not(windows))] {