Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,6 @@ def test_exist_ok_existing_directory(self):
# Issue #25583: A drive root could raise PermissionError on Windows
os.makedirs(os.path.abspath('/'), exist_ok=True)

@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; os.umask not implemented yet for all platforms')
@unittest.skipIf(
support.is_emscripten or support.is_wasi,
"Emscripten's/WASI's umask is a stub."
Expand Down Expand Up @@ -4653,7 +4652,6 @@ def test_get_set_inheritable_o_path(self):
os.set_inheritable(fd, False)
self.assertEqual(os.get_inheritable(fd), False)

@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; os.get_inheritable not implemented yet for all platforms')
def test_get_set_inheritable_badf(self):
fd = os_helper.make_bad_fd()

Expand Down
39 changes: 30 additions & 9 deletions crates/vm/src/function/fspath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,26 @@ pub enum FsPath {
}

impl FsPath {
pub fn try_from_path_like(
obj: PyObjectRef,
check_for_nul: bool,
vm: &VirtualMachine,
) -> PyResult<Self> {
Self::try_from(
obj,
check_for_nul,
"expected str, bytes or os.PathLike object",
vm,
)
}

// PyOS_FSPath in CPython
pub fn try_from(obj: PyObjectRef, check_for_nul: bool, vm: &VirtualMachine) -> PyResult<Self> {
pub fn try_from(
obj: PyObjectRef,
check_for_nul: bool,
msg: &'static str,
vm: &VirtualMachine,
) -> PyResult<Self> {
let check_nul = |b: &[u8]| {
if !check_for_nul || memchr::memchr(b'\0', b).is_none() {
Ok(())
Expand All @@ -41,13 +59,16 @@ impl FsPath {
Ok(pathlike) => return Ok(pathlike),
Err(obj) => obj,
};
let method =
vm.get_method_or_type_error(obj.clone(), identifier!(vm, __fspath__), || {
format!(
"should be string, bytes, os.PathLike or integer, not {}",
obj.class().name()
)
})?;
let not_pathlike_error = || format!("{msg}, not {}", obj.class().name());
let method = vm.get_method_or_type_error(
obj.clone(),
identifier!(vm, __fspath__),
not_pathlike_error,
)?;
// If __fspath__ is explicitly set to None, treat it as if it doesn't have __fspath__
if vm.is_none(&method) {
return Err(vm.new_type_error(not_pathlike_error()));
}
let result = method.call((), vm)?;
match1(result)?.map_err(|result| {
vm.new_type_error(format!(
Expand Down Expand Up @@ -125,6 +146,6 @@ impl TryFromObject for FsPath {
}
Err(_) => obj,
};
Self::try_from(obj, true, vm)
Self::try_from_path_like(obj, true, vm)
}
}
15 changes: 14 additions & 1 deletion crates/vm/src/ospath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ impl OsPath {
Ok(Self { path, mode })
}

/// Convert an object to OsPath using the os.fspath-style error message.
/// This is used by open() which should report "expected str, bytes or os.PathLike object, not"
/// instead of "should be string, bytes or os.PathLike, not".
pub(crate) fn try_from_fspath(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
let fspath = FsPath::try_from_path_like(obj, true, vm)?;
Self::from_fspath(fspath, vm)
}

pub fn as_path(&self) -> &Path {
Path::new(&self.path)
}
Expand Down Expand Up @@ -90,7 +98,12 @@ impl AsRef<Path> for OsPath {
impl TryFromObject for OsPath {
// TODO: path_converter with allow_fd=0 in CPython
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let fspath = FsPath::try_from(obj, true, vm)?;
let fspath = FsPath::try_from(
obj,
true,
"should be string, bytes, os.PathLike or integer",
vm,
)?;
Self::from_fspath(fspath, vm)
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/stdlib/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4340,7 +4340,7 @@ mod fileio {
}
(fd, None)
} else {
let path = OsPath::try_from_object(vm, name.clone())?;
let path = OsPath::try_from_fspath(name.clone(), vm)?;
#[cfg(any(unix, target_os = "wasi"))]
let fd = crt_fd::open(&path.clone().into_cstring(vm)?, flags, 0o666);
#[cfg(windows)]
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/stdlib/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,7 @@ pub(super) mod _os {

#[pyfunction]
fn fspath(path: PyObjectRef, vm: &VirtualMachine) -> PyResult<FsPath> {
FsPath::try_from(path, false, vm)
FsPath::try_from_path_like(path, false, vm)
}

#[pyfunction]
Expand Down
Loading