diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 134235506..aba7340a1 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -318,8 +318,6 @@ class TestRmTree(BaseTest, unittest.TestCase): self.assertTrue(os.path.exists(dir3)) self.assertTrue(os.path.exists(file1)) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_rmtree_errors_onerror(self): # filename is guaranteed not to exist filename = tempfile.mktemp(dir=self.mkdtemp()) @@ -352,8 +350,6 @@ class TestRmTree(BaseTest, unittest.TestCase): self.assertIsInstance(errors[1][2][1], NotADirectoryError) self.assertEqual(errors[1][2][1].filename, filename) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_rmtree_errors_onexc(self): # filename is guaranteed not to exist filename = tempfile.mktemp(dir=self.mkdtemp()) diff --git a/Lib/test/test_unicode_file_functions.py b/Lib/test/test_unicode_file_functions.py index 409552878..47619c880 100644 --- a/Lib/test/test_unicode_file_functions.py +++ b/Lib/test/test_unicode_file_functions.py @@ -94,8 +94,6 @@ class UnicodeFileTests(unittest.TestCase): "with bad filename in the exception: %a" % (fn.__name__, filename, exc_filename)) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_failures(self): # Pass non-existing Unicode filenames all over the place. for name in self.files: @@ -113,8 +111,6 @@ class UnicodeFileTests(unittest.TestCase): else: _listdir_failure = NotADirectoryError - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_open(self): for name in self.files: f = open(name, 'wb') @@ -127,8 +123,6 @@ class UnicodeFileTests(unittest.TestCase): # NFD (a variant of Unicode NFD form). Normalize the filename to NFC, NFKC, # NFKD in Python is useless, because darwin will normalize it later and so # open(), os.stat(), etc. don't raise any exception. - # TODO: RUSTPYTHON - @unittest.expectedFailure @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') @unittest.skipIf( support.is_emscripten or support.is_wasi, diff --git a/stdlib/src/posixsubprocess.rs b/stdlib/src/posixsubprocess.rs index 5f8cb3f5b..cbc78d962 100644 --- a/stdlib/src/posixsubprocess.rs +++ b/stdlib/src/posixsubprocess.rs @@ -1,7 +1,8 @@ use crate::vm::{ builtins::PyListRef, function::ArgSequence, - stdlib::{os::OsPath, posix}, + ospath::OsPath, + stdlib::posix, {PyObjectRef, PyResult, TryFromObject, VirtualMachine}, }; use nix::{errno::Errno, unistd}; diff --git a/vm/src/lib.rs b/vm/src/lib.rs index aae29a9a2..3c99e382f 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -60,6 +60,8 @@ pub mod import; mod intern; pub mod iter; pub mod object; +#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))] +pub mod ospath; pub mod prelude; pub mod protocol; pub mod py_io; diff --git a/vm/src/ospath.rs b/vm/src/ospath.rs new file mode 100644 index 000000000..ac574339f --- /dev/null +++ b/vm/src/ospath.rs @@ -0,0 +1,198 @@ +use crate::{ + builtins::PyBaseExceptionRef, + convert::{ToPyException, TryFromObject}, + function::FsPath, + object::AsObject, + PyObjectRef, PyResult, VirtualMachine, +}; +use std::path::{Path, PathBuf}; + +// path_ without allow_fd in CPython +#[derive(Clone)] +pub struct OsPath { + pub path: std::ffi::OsString, + pub(super) mode: OutputMode, +} + +#[derive(Debug, Copy, Clone)] +pub(super) enum OutputMode { + String, + Bytes, +} + +impl OutputMode { + pub(super) fn process_path(self, path: impl Into, vm: &VirtualMachine) -> PyResult { + fn inner(mode: OutputMode, path: PathBuf, vm: &VirtualMachine) -> PyResult { + let path_as_string = |p: PathBuf| { + p.into_os_string().into_string().map_err(|_| { + vm.new_unicode_decode_error( + "Can't convert OS path to valid UTF-8 string".into(), + ) + }) + }; + match mode { + OutputMode::String => path_as_string(path).map(|s| vm.ctx.new_str(s).into()), + OutputMode::Bytes => { + #[cfg(any(unix, target_os = "wasi"))] + { + use rustpython_common::os::ffi::OsStringExt; + Ok(vm.ctx.new_bytes(path.into_os_string().into_vec()).into()) + } + #[cfg(windows)] + { + path_as_string(path).map(|s| vm.ctx.new_bytes(s.into_bytes()).into()) + } + } + } + } + inner(self, path.into(), vm) + } +} + +impl OsPath { + pub fn new_str(path: impl Into) -> Self { + let path = path.into(); + Self { + path, + mode: OutputMode::String, + } + } + + pub(crate) fn from_fspath(fspath: FsPath, vm: &VirtualMachine) -> PyResult { + let path = fspath.as_os_str(vm)?.to_owned(); + let mode = match fspath { + FsPath::Str(_) => OutputMode::String, + FsPath::Bytes(_) => OutputMode::Bytes, + }; + Ok(OsPath { path, mode }) + } + + pub fn as_path(&self) -> &Path { + Path::new(&self.path) + } + + pub fn into_bytes(self) -> Vec { + self.path.into_encoded_bytes() + } + + pub fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> { + self.path.to_string_lossy() + } + + pub fn into_cstring(self, vm: &VirtualMachine) -> PyResult { + std::ffi::CString::new(self.into_bytes()).map_err(|err| err.to_pyexception(vm)) + } + + #[cfg(windows)] + pub fn to_widecstring(&self, vm: &VirtualMachine) -> PyResult { + widestring::WideCString::from_os_str(&self.path).map_err(|err| err.to_pyexception(vm)) + } + + pub fn filename(&self, vm: &VirtualMachine) -> PyResult { + self.mode.process_path(self.path.clone(), vm) + } +} + +impl AsRef for OsPath { + fn as_ref(&self) -> &Path { + self.as_path() + } +} + +impl TryFromObject for OsPath { + // TODO: path_converter with allow_fd=0 in CPython + fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { + let fspath = FsPath::try_from(obj, true, vm)?; + Self::from_fspath(fspath, vm) + } +} + +// path_t with allow_fd in CPython +#[derive(Clone)] +pub(crate) enum OsPathOrFd { + Path(OsPath), + Fd(i32), +} + +impl TryFromObject for OsPathOrFd { + fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { + let r = match obj.try_index_opt(vm) { + Some(int) => Self::Fd(int?.try_to_primitive(vm)?), + None => Self::Path(obj.try_into_value(vm)?), + }; + Ok(r) + } +} + +impl From for OsPathOrFd { + fn from(path: OsPath) -> Self { + Self::Path(path) + } +} + +impl OsPathOrFd { + pub fn filename(&self, vm: &VirtualMachine) -> PyObjectRef { + match self { + OsPathOrFd::Path(path) => path.filename(vm).unwrap_or_else(|_| vm.ctx.none()), + OsPathOrFd::Fd(fd) => vm.ctx.new_int(*fd).into(), + } + } +} + +// TODO: preserve the input `PyObjectRef` of filename and filename2 (Failing check `self.assertIs(err.filename, name, str(func)`) +pub struct IOErrorBuilder<'a> { + error: &'a std::io::Error, + filename: Option, + filename2: Option, +} + +impl<'a> IOErrorBuilder<'a> { + pub fn new(error: &'a std::io::Error) -> Self { + Self { + error, + filename: None, + filename2: None, + } + } + pub(crate) fn filename(mut self, filename: impl Into) -> Self { + let filename = filename.into(); + self.filename.replace(filename); + self + } + pub(crate) fn filename2(mut self, filename: impl Into) -> Self { + let filename = filename.into(); + self.filename2.replace(filename); + self + } + + pub(crate) fn with_filename( + error: &'a std::io::Error, + filename: impl Into, + vm: &VirtualMachine, + ) -> PyBaseExceptionRef { + let zelf = Self { + error, + filename: Some(filename.into()), + filename2: None, + }; + zelf.to_pyexception(vm) + } +} + +impl<'a> ToPyException for IOErrorBuilder<'a> { + fn to_pyexception(&self, vm: &VirtualMachine) -> PyBaseExceptionRef { + let excp = self.error.to_pyexception(vm); + + if let Some(filename) = &self.filename { + excp.as_object() + .set_attr("filename", filename.filename(vm), vm) + .unwrap(); + } + if let Some(filename2) = &self.filename2 { + excp.as_object() + .set_attr("filename2", filename2.filename(vm), vm) + .unwrap(); + } + excp + } +} diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index deea3eafb..309125066 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -3570,7 +3570,7 @@ mod _io { // check file descriptor validity #[cfg(unix)] - if let Ok(crate::stdlib::os::OsPathOrFd::Fd(fd)) = file.clone().try_into_value(vm) { + if let Ok(crate::ospath::OsPathOrFd::Fd(fd)) = file.clone().try_into_value(vm) { nix::fcntl::fcntl(fd, nix::fcntl::F_GETFD) .map_err(|_| crate::stdlib::os::errno_err(vm))?; } @@ -3901,7 +3901,7 @@ mod fileio { } else if let Some(i) = name.payload::() { i.try_to_primitive(vm)? } else { - let path = os::OsPath::try_from_object(vm, name.clone())?; + let path = crate::ospath::OsPath::try_from_object(vm, name.clone())?; if !args.closefd { return Err( vm.new_value_error("Cannot use closefd=False with file name".to_owned()) diff --git a/vm/src/stdlib/nt.rs b/vm/src/stdlib/nt.rs index 2da8f5e0d..9fa69291f 100644 --- a/vm/src/stdlib/nt.rs +++ b/vm/src/stdlib/nt.rs @@ -18,9 +18,8 @@ pub(crate) mod module { convert::ToPyException, function::Either, function::OptionalArg, - stdlib::os::{ - errno_err, DirFd, FollowSymlinks, OsPath, SupportFunc, TargetIsDirectory, _os, - }, + ospath::OsPath, + stdlib::os::{errno_err, DirFd, FollowSymlinks, SupportFunc, TargetIsDirectory, _os}, PyResult, TryFromObject, VirtualMachine, }; use libc::intptr_t; diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 3121b7944..636f6cd33 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1,97 +1,11 @@ use crate::{ builtins::{PyBaseExceptionRef, PyModule, PySet}, common::crt_fd::Fd, - convert::{IntoPyException, ToPyException}, - function::{ArgumentError, FromArgs, FsPath, FuncArgs}, - AsObject, Py, PyObjectRef, PyPayload, PyResult, TryFromObject, VirtualMachine, + convert::ToPyException, + function::{ArgumentError, FromArgs, FuncArgs}, + AsObject, Py, PyPayload, PyResult, VirtualMachine, }; - -use std::{ - ffi, fs, io, - path::{Path, PathBuf}, -}; - -#[derive(Debug, Copy, Clone)] -pub(super) enum OutputMode { - String, - Bytes, -} - -impl OutputMode { - pub(super) fn process_path(self, path: impl Into, vm: &VirtualMachine) -> PyResult { - fn inner(mode: OutputMode, path: PathBuf, vm: &VirtualMachine) -> PyResult { - let path_as_string = |p: PathBuf| { - p.into_os_string().into_string().map_err(|_| { - vm.new_unicode_decode_error( - "Can't convert OS path to valid UTF-8 string".into(), - ) - }) - }; - match mode { - OutputMode::String => path_as_string(path).map(|s| vm.ctx.new_str(s).into()), - OutputMode::Bytes => { - #[cfg(any(unix, target_os = "wasi"))] - { - use rustpython_common::os::ffi::OsStringExt; - Ok(vm.ctx.new_bytes(path.into_os_string().into_vec()).into()) - } - #[cfg(windows)] - { - path_as_string(path).map(|s| vm.ctx.new_bytes(s.into_bytes()).into()) - } - } - } - } - inner(self, path.into(), vm) - } -} - -// path_ without allow_fd in CPython -#[derive(Clone)] -pub struct OsPath { - pub path: ffi::OsString, - pub(super) mode: OutputMode, -} - -impl OsPath { - pub fn new_str(path: impl Into) -> Self { - let path = path.into(); - Self { - path, - mode: OutputMode::String, - } - } - - pub(crate) fn from_fspath(fspath: FsPath, vm: &VirtualMachine) -> PyResult { - let path = fspath.as_os_str(vm)?.to_owned(); - let mode = match fspath { - FsPath::Str(_) => OutputMode::String, - FsPath::Bytes(_) => OutputMode::Bytes, - }; - Ok(OsPath { path, mode }) - } - - pub fn as_path(&self) -> &Path { - Path::new(&self.path) - } - - pub fn into_bytes(self) -> Vec { - self.path.into_encoded_bytes() - } - - pub fn into_cstring(self, vm: &VirtualMachine) -> PyResult { - ffi::CString::new(self.into_bytes()).map_err(|err| err.into_pyexception(vm)) - } - - #[cfg(windows)] - pub fn to_widecstring(&self, vm: &VirtualMachine) -> PyResult { - widestring::WideCString::from_os_str(&self.path).map_err(|err| err.into_pyexception(vm)) - } - - pub fn filename(&self, vm: &VirtualMachine) -> PyResult { - self.mode.process_path(self.path.clone(), vm) - } -} +use std::{ffi, fs, io, path::Path}; pub(super) fn fs_metadata>( path: P, @@ -104,104 +18,13 @@ pub(super) fn fs_metadata>( } } -impl AsRef for OsPath { - fn as_ref(&self) -> &Path { - self.as_path() - } -} - -impl TryFromObject for OsPath { - // TODO: path_converter with allow_fd=0 in CPython - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - let fspath = FsPath::try_from(obj, true, vm)?; - Self::from_fspath(fspath, vm) - } -} - -// path_t with allow_fd in CPython -#[derive(Clone)] -pub(crate) enum OsPathOrFd { - Path(OsPath), - Fd(i32), -} - -impl TryFromObject for OsPathOrFd { - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - let r = match obj.try_index_opt(vm) { - Some(int) => Self::Fd(int?.try_to_primitive(vm)?), - None => Self::Path(obj.try_into_value(vm)?), - }; - Ok(r) - } -} - -impl From for OsPathOrFd { - fn from(path: OsPath) -> Self { - Self::Path(path) - } -} - -impl OsPathOrFd { - pub fn filename(&self, vm: &VirtualMachine) -> PyObjectRef { - match self { - OsPathOrFd::Path(path) => path.filename(vm).unwrap_or_else(|_| vm.ctx.none()), - OsPathOrFd::Fd(fd) => vm.ctx.new_int(*fd).into(), - } - } -} - #[cfg(unix)] -impl IntoPyException for nix::Error { +impl crate::convert::IntoPyException for nix::Error { fn into_pyexception(self, vm: &VirtualMachine) -> PyBaseExceptionRef { io::Error::from(self).into_pyexception(vm) } } -// TODO: preserve the input `PyObjectRef` of filename and filename2 (Failing check `self.assertIs(err.filename, name, str(func)`) -pub struct IOErrorBuilder { - error: io::Error, - filename: Option, - filename2: Option, -} - -impl IOErrorBuilder { - pub fn new(error: io::Error) -> Self { - Self { - error, - filename: None, - filename2: None, - } - } - pub(crate) fn filename(mut self, filename: impl Into) -> Self { - let filename = filename.into(); - self.filename.replace(filename); - self - } - pub(crate) fn filename2(mut self, filename: impl Into) -> Self { - let filename = filename.into(); - self.filename2.replace(filename); - self - } -} - -impl IntoPyException for IOErrorBuilder { - fn into_pyexception(self, vm: &VirtualMachine) -> PyBaseExceptionRef { - let excp = self.error.into_pyexception(vm); - - if let Some(filename) = self.filename { - excp.as_object() - .set_attr("filename", filename.filename(vm), vm) - .unwrap(); - } - if let Some(filename2) = self.filename2 { - excp.as_object() - .set_attr("filename2", filename2.filename(vm), vm) - .unwrap(); - } - excp - } -} - /// Convert the error stored in the `errno` variable into an Exception #[inline] pub fn errno_err(vm: &VirtualMachine) -> PyBaseExceptionRef { @@ -295,10 +118,7 @@ fn bytes_as_osstr<'a>(b: &'a [u8], vm: &VirtualMachine) -> PyResult<&'a ffi::OsS #[pymodule(sub)] pub(super) mod _os { - use super::{ - errno_err, DirFd, FollowSymlinks, IOErrorBuilder, OsPath, OsPathOrFd, OutputMode, - SupportFunc, - }; + use super::{errno_err, DirFd, FollowSymlinks, SupportFunc}; use crate::{ builtins::{ PyBytesRef, PyGenericAlias, PyIntRef, PyStrRef, PyTuple, PyTupleRef, PyTypeRef, @@ -308,6 +128,7 @@ pub(super) mod _os { common::suppress_iph, convert::{IntoPyException, ToPyObject}, function::{ArgBytesLike, Either, FsPath, FuncArgs, OptionalArg}, + ospath::{IOErrorBuilder, OsPath, OsPathOrFd, OutputMode}, protocol::PyIterReturn, recursion::ReprGuard, types::{IterNext, Iterable, PyStructSequence, Representable, SelfIter}, @@ -407,7 +228,7 @@ pub(super) mod _os { } }; fd.map(|fd| fd.0) - .map_err(|e| IOErrorBuilder::new(e).filename(name).into_pyexception(vm)) + .map_err(|err| IOErrorBuilder::with_filename(&err, name, vm)) } #[pyfunction] @@ -449,7 +270,7 @@ pub(super) mod _os { } else { fs::remove_file(&path) }; - res.map_err(|e| IOErrorBuilder::new(e).filename(path).into_pyexception(vm)) + res.map_err(|err| IOErrorBuilder::with_filename(&err, path, vm)) } #[cfg(not(windows))] @@ -486,8 +307,7 @@ pub(super) mod _os { #[pyfunction] fn rmdir(path: OsPath, dir_fd: DirFd<0>, vm: &VirtualMachine) -> PyResult<()> { let [] = dir_fd.0; - fs::remove_dir(&path) - .map_err(|e| IOErrorBuilder::new(e).filename(path).into_pyexception(vm)) + fs::remove_dir(&path).map_err(|err| IOErrorBuilder::with_filename(&err, path, vm)) } const LISTDIR_FD: bool = cfg!(all(unix, not(target_os = "redox"))); @@ -497,13 +317,16 @@ pub(super) mod _os { let path = path.unwrap_or_else(|| OsPathOrFd::Path(OsPath::new_str("."))); let list = match path { OsPathOrFd::Path(path) => { - let dir_iter = fs::read_dir(&path).map_err(|err| err.into_pyexception(vm))?; + let dir_iter = match fs::read_dir(&path) { + Ok(iter) => iter, + Err(err) => { + return Err(IOErrorBuilder::with_filename(&err, path, vm)); + } + }; dir_iter .map(|entry| match entry { Ok(entry_path) => path.mode.process_path(entry_path.file_name(), vm), - Err(e) => Err(IOErrorBuilder::new(e) - .filename(path.clone()) - .into_pyexception(vm)), + Err(err) => Err(IOErrorBuilder::with_filename(&err, path.clone(), vm)), }) .collect::>()? } @@ -593,8 +416,8 @@ pub(super) mod _os { fn readlink(path: OsPath, dir_fd: DirFd<0>, vm: &VirtualMachine) -> PyResult { let mode = path.mode; let [] = dir_fd.0; - let path = fs::read_link(&path) - .map_err(|err| IOErrorBuilder::new(err).filename(path).into_pyexception(vm))?; + let path = + fs::read_link(&path).map_err(|err| IOErrorBuilder::with_filename(&err, path, vm))?; mode.process_path(path, vm) } @@ -861,7 +684,8 @@ pub(super) mod _os { #[pyfunction] fn scandir(path: OptionalArg, vm: &VirtualMachine) -> PyResult { let path = path.unwrap_or_else(|| OsPath::new_str(".")); - let entries = fs::read_dir(path.path).map_err(|err| err.into_pyexception(vm))?; + let entries = fs::read_dir(&path.path) + .map_err(|err| IOErrorBuilder::with_filename(&err, path.clone(), vm))?; Ok(ScandirIterator { entries: PyRwLock::new(Some(entries)), mode: path.mode, @@ -1113,7 +937,7 @@ pub(super) mod _os { vm: &VirtualMachine, ) -> PyResult { let stat = stat_inner(file.clone(), dir_fd, follow_symlinks) - .map_err(|e| IOErrorBuilder::new(e).filename(file).into_pyexception(vm))? + .map_err(|err| IOErrorBuilder::with_filename(&err, file, vm))? .ok_or_else(|| crate::exceptions::cstring_error(vm))?; Ok(StatResult::from_stat(&stat, vm).to_pyobject(vm)) } @@ -1144,7 +968,7 @@ pub(super) mod _os { #[pyfunction] fn chdir(path: OsPath, vm: &VirtualMachine) -> PyResult<()> { env::set_current_dir(&path.path) - .map_err(|err| IOErrorBuilder::new(err).filename(path).into_pyexception(vm)) + .map_err(|err| IOErrorBuilder::with_filename(&err, path, vm)) } #[pyfunction] @@ -1156,7 +980,7 @@ pub(super) mod _os { #[pyfunction(name = "replace")] fn rename(src: OsPath, dst: OsPath, vm: &VirtualMachine) -> PyResult<()> { fs::rename(&src.path, &dst.path).map_err(|err| { - IOErrorBuilder::new(err) + IOErrorBuilder::new(&err) .filename(src) .filename2(dst) .into_pyexception(vm) @@ -1238,7 +1062,7 @@ pub(super) mod _os { #[pyfunction] fn link(src: OsPath, dst: OsPath, vm: &VirtualMachine) -> PyResult<()> { fs::hard_link(&src.path, &dst.path).map_err(|err| { - IOErrorBuilder::new(err) + IOErrorBuilder::new(&err) .filename(src) .filename2(dst) .into_pyexception(vm) @@ -1552,14 +1376,23 @@ pub(super) mod _os { if let Ok(fd) = path.try_to_value(vm) { return ftruncate(fd, length, vm); } + + #[cold] + fn error( + vm: &VirtualMachine, + error: std::io::Error, + path: OsPath, + ) -> crate::builtins::PyBaseExceptionRef { + IOErrorBuilder::with_filename(&error, path, vm) + } + let path = OsPath::try_from_object(vm, path)?; // TODO: just call libc::truncate() on POSIX - let f = OpenOptions::new() - .write(true) - .open(path) - .map_err(|e| e.into_pyexception(vm))?; - f.set_len(length as u64) - .map_err(|e| e.into_pyexception(vm))?; + let f = match OpenOptions::new().write(true).open(&path) { + Ok(f) => f, + Err(e) => return Err(error(vm, e, path)), + }; + f.set_len(length as u64).map_err(|e| error(vm, e, path))?; drop(f); Ok(()) } diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index 4351acf86..58b13c46d 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -24,9 +24,9 @@ pub mod module { builtins::{PyDictRef, PyInt, PyListRef, PyStrRef, PyTupleRef, PyTypeRef}, convert::{IntoPyException, ToPyObject, TryFromObject}, function::{Either, KwArgs, OptionalArg}, + ospath::{IOErrorBuilder, OsPath, OsPathOrFd}, stdlib::os::{ - errno_err, DirFd, FollowSymlinks, OsPath, OsPathOrFd, SupportFunc, TargetIsDirectory, - _os, fs_metadata, IOErrorBuilder, + errno_err, DirFd, FollowSymlinks, SupportFunc, TargetIsDirectory, _os, fs_metadata, }, types::{Constructor, Representable}, utils::ToCString, @@ -279,14 +279,15 @@ pub mod module { ) })?; - let metadata = fs::metadata(path.path); + let metadata = fs::metadata(path.path.clone()); // if it's only checking for F_OK if flags == AccessFlags::F_OK { return Ok(metadata.is_ok()); } - let metadata = metadata.map_err(|err| err.into_pyexception(vm))?; + let metadata = + metadata.map_err(|err| IOErrorBuilder::with_filename(&err, path.clone(), vm))?; let user_id = metadata.uid(); let group_id = metadata.gid(); @@ -356,13 +357,12 @@ pub mod module { #[cfg(not(target_os = "redox"))] #[pyfunction] fn chroot(path: OsPath, vm: &VirtualMachine) -> PyResult<()> { - use crate::stdlib::os::IOErrorBuilder; + use crate::ospath::IOErrorBuilder; nix::unistd::chroot(&*path.path).map_err(|err| { // Use `From for io::Error` when it is available - IOErrorBuilder::new(io::Error::from_raw_os_error(err as i32)) - .filename(path) - .into_pyexception(vm) + let err = io::Error::from_raw_os_error(err as i32); + IOErrorBuilder::with_filename(&err, path, vm) }) } @@ -408,9 +408,8 @@ pub mod module { } .map_err(|err| { // Use `From for io::Error` when it is available - IOErrorBuilder::new(io::Error::from_raw_os_error(err as i32)) - .filename(path) - .into_pyexception(vm) + let err = io::Error::from_raw_os_error(err as i32); + IOErrorBuilder::with_filename(&err, path, vm) }) } @@ -919,11 +918,7 @@ pub mod module { permissions.set_mode(mode); fs::set_permissions(&path, permissions) }; - body().map_err(|err| { - IOErrorBuilder::new(err) - .filename(err_path) - .into_pyexception(vm) - }) + body().map_err(|err| IOErrorBuilder::with_filename(&err, err_path, vm)) } #[cfg(not(target_os = "redox"))] @@ -1474,9 +1469,8 @@ pub mod module { } }; if ret != 0 { - return Err(IOErrorBuilder::new(std::io::Error::from_raw_os_error(ret)) - .filename(self.path) - .into_pyexception(vm)); + let err = std::io::Error::from_raw_os_error(ret); + return Err(IOErrorBuilder::with_filename(&err, self.path, vm)); } } } @@ -1548,9 +1542,8 @@ pub mod module { if ret == 0 { Ok(pid) } else { - Err(IOErrorBuilder::new(std::io::Error::from_raw_os_error(ret)) - .filename(self.path) - .into_pyexception(vm)) + let err = std::io::Error::from_raw_os_error(ret); + Err(IOErrorBuilder::with_filename(&err, self.path, vm)) } } } diff --git a/vm/src/stdlib/posix_compat.rs b/vm/src/stdlib/posix_compat.rs index 3f939dce1..95ed932fe 100644 --- a/vm/src/stdlib/posix_compat.rs +++ b/vm/src/stdlib/posix_compat.rs @@ -11,7 +11,8 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { pub(crate) mod module { use crate::{ builtins::PyStrRef, - stdlib::os::{DirFd, OsPath, SupportFunc, TargetIsDirectory, _os}, + ospath::OsPath, + stdlib::os::{DirFd, SupportFunc, TargetIsDirectory, _os}, PyObjectRef, PyResult, VirtualMachine, }; use std::env;