Merge pull request #3374 from Tpt/pathlike
Makes PathBuf FromPyObject implementation work on all os.PathLike
This commit is contained in:
commit
1df7270e15
|
@ -37,6 +37,7 @@ The table below contains the Python type and the corresponding function argument
|
|||
| `decimal.Decimal` | `rust_decimal::Decimal`[^5] | - |
|
||||
| `ipaddress.IPv4Address` | `std::net::IpAddr`, `std::net::IpV4Addr` | - |
|
||||
| `ipaddress.IPv6Address` | `std::net::IpAddr`, `std::net::IpV6Addr` | - |
|
||||
| `os.PathLike ` | `PathBuf`, `Path` | `&PyString`, `&PyUnicode` |
|
||||
| `pathlib.Path` | `PathBuf`, `Path` | `&PyString`, `&PyUnicode` |
|
||||
| `typing.Optional[T]` | `Option<T>` | - |
|
||||
| `typing.Sequence[T]` | `Vec<T>` | `&PySequence` |
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
`PathBuf` `FromPyObject` implementation now works on all `os.PathLike` values.
|
|
@ -0,0 +1 @@
|
|||
Linking of `PyOS_FSPath` on PyPy.
|
|
@ -1,5 +1,6 @@
|
|||
use crate::object::PyObject;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(PyPy, link_name = "PyPyOS_FSPath")]
|
||||
pub fn PyOS_FSPath(path: *mut PyObject) -> *mut PyObject;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import pathlib
|
||||
|
||||
import pytest
|
||||
|
||||
import pyo3_pytests.path as rpath
|
||||
|
||||
|
||||
|
@ -16,3 +18,25 @@ def test_take_pathbuf():
|
|||
def test_take_pathlib():
|
||||
p = pathlib.Path("/root")
|
||||
assert rpath.take_pathbuf(p) == str(p)
|
||||
|
||||
|
||||
def test_take_pathlike():
|
||||
assert rpath.take_pathbuf(PathLike("/root")) == "/root"
|
||||
|
||||
|
||||
def test_take_invalid_pathlike():
|
||||
with pytest.raises(TypeError):
|
||||
assert rpath.take_pathbuf(PathLike(1))
|
||||
|
||||
|
||||
def test_take_invalid():
|
||||
with pytest.raises(TypeError):
|
||||
assert rpath.take_pathbuf(3)
|
||||
|
||||
|
||||
class PathLike:
|
||||
def __init__(self, path):
|
||||
self._path = path
|
||||
|
||||
def __fspath__(self):
|
||||
return self._path
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::intern;
|
||||
use crate::{FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject};
|
||||
use crate::{
|
||||
ffi, AsPyPointer, FromPyObject, FromPyPointer, IntoPy, PyAny, PyObject, PyResult, Python,
|
||||
ToPyObject,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -14,21 +16,9 @@ impl ToPyObject for Path {
|
|||
|
||||
impl FromPyObject<'_> for PathBuf {
|
||||
fn extract(ob: &PyAny) -> PyResult<Self> {
|
||||
let os_str = match OsString::extract(ob) {
|
||||
Ok(s) => s,
|
||||
Err(err) => {
|
||||
let py = ob.py();
|
||||
let pathlib = py.import(intern!(py, "pathlib"))?;
|
||||
let pathlib_path = pathlib.getattr(intern!(py, "Path"))?;
|
||||
if ob.is_instance(pathlib_path)? {
|
||||
let path_str = ob.call_method0(intern!(py, "__str__"))?;
|
||||
OsString::extract(path_str)?
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(PathBuf::from(os_str))
|
||||
// We use os.fspath to get the underlying path as bytes or str
|
||||
let path = unsafe { PyAny::from_owned_ptr_or_err(ob.py(), ffi::PyOS_FSPath(ob.as_ptr())) }?;
|
||||
Ok(OsString::extract(path)?.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue