mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
vm/ospath module
This commit is contained in:
1 parent
d57287b89b
commit
c9c07a6bbc
10 files changed
+263
-246
No files matched your search
Vendored
-4
@@ -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())
|
||||
|
||||
-6
@@ -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,
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<PathBuf>, 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<std::ffi::OsString>) -> Self {
|
||||
let path = path.into();
|
||||
Self {
|
||||
path,
|
||||
mode: OutputMode::String,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_fspath(fspath: FsPath, vm: &VirtualMachine) -> PyResult<OsPath> {
|
||||
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<u8> {
|
||||
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> {
|
||||
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> {
|
||||
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<Path> 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<Self> {
|
||||
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<Self> {
|
||||
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<OsPath> 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<OsPathOrFd>,
|
||||
filename2: Option<OsPathOrFd>,
|
||||
}
|
||||
|
||||
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<OsPathOrFd>) -> Self {
|
||||
let filename = filename.into();
|
||||
self.filename.replace(filename);
|
||||
self
|
||||
}
|
||||
pub(crate) fn filename2(mut self, filename: impl Into<OsPathOrFd>) -> Self {
|
||||
let filename = filename.into();
|
||||
self.filename2.replace(filename);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn with_filename(
|
||||
error: &'a std::io::Error,
|
||||
filename: impl Into<OsPathOrFd>,
|
||||
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
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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::<crate::builtins::PyInt>() {
|
||||
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())
|
||||
|
||||
+2
-3
@@ -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;
|
||||
|
||||
+40
-207
@@ -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<PathBuf>, 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<ffi::OsString>) -> Self {
|
||||
let path = path.into();
|
||||
Self {
|
||||
path,
|
||||
mode: OutputMode::String,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_fspath(fspath: FsPath, vm: &VirtualMachine) -> PyResult<OsPath> {
|
||||
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<u8> {
|
||||
self.path.into_encoded_bytes()
|
||||
}
|
||||
|
||||
pub fn into_cstring(self, vm: &VirtualMachine) -> PyResult<ffi::CString> {
|
||||
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> {
|
||||
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<P: AsRef<Path>>(
|
||||
path: P,
|
||||
@@ -104,104 +18,13 @@ pub(super) fn fs_metadata<P: AsRef<Path>>(
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> 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<Self> {
|
||||
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<Self> {
|
||||
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<OsPath> 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<OsPathOrFd>,
|
||||
filename2: Option<OsPathOrFd>,
|
||||
}
|
||||
|
||||
impl IOErrorBuilder {
|
||||
pub fn new(error: io::Error) -> Self {
|
||||
Self {
|
||||
error,
|
||||
filename: None,
|
||||
filename2: None,
|
||||
}
|
||||
}
|
||||
pub(crate) fn filename(mut self, filename: impl Into<OsPathOrFd>) -> Self {
|
||||
let filename = filename.into();
|
||||
self.filename.replace(filename);
|
||||
self
|
||||
}
|
||||
pub(crate) fn filename2(mut self, filename: impl Into<OsPathOrFd>) -> 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::<PyResult<_>>()?
|
||||
}
|
||||
@@ -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<OsPath>, 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(())
|
||||
}
|
||||
|
||||
+15
-22
@@ -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<nix::Error> 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<nix::Error> 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
|
||||
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;
|
||||
|
||||
Reference in new issue
Block a user