8000 better OSError.filename (#5239) · RustPython/RustPython@b366606 · GitHub
[go: up one dir, main page]

Skip to content

Commit b366606

Browse files
authored
better OSError.filename (#5239)
* Fix OSError message * IOError with filename * more filenames
1 parent c9c07a6 commit b366606

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

vm/src/exceptions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,14 +1307,14 @@ pub(super) mod types {
13071307

13081308
let s = match obj.get_attr("filename", vm) {
13091309
Ok(filename) => match obj.get_attr("filename2", vm) {
1310-
Ok(filename2) => format!(
1310+
Ok(filename2) if !vm.is_none(&filename2) => format!(
13111311
"[Errno {}] {}: '{}' -> '{}'",
13121312
errno,
13131313
msg,
13141314
filename.str(vm)?,
13151315
filename2.str(vm)?
13161316
),
1317-
Err(_) => format!("[Errno {}] {}: '{}'", errno, msg, filename.str(vm)?),
1317+
_ => format!("[Errno {}] {}: '{}'", errno, msg, filename.str(vm)?),
13181318
},
13191319
Err(_) => {
13201320
format!("[Errno {errno}] {msg}")

vm/src/stdlib/io.rs

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3730,7 +3730,7 @@ mod _io {
37303730
mod fileio {
37313731
use super::{Offset, _io::*};
37323732
use crate::{
3733-
builtins::{PyStr, PyStrRef},
3733+
builtins::{PyBaseExceptionRef, PyStr, PyStrRef},
37343734
common::crt_fd::Fd,
37353735
convert::ToPyException,
37363736
function::{ArgBytesLike, ArgMemoryBuffer, OptionalArg, OptionalOption},
@@ -3947,6 +3947,20 @@ mod fileio {
39473947
flags(BASETYPE, HAS_DICT)
39483948
)]
39493949
impl FileIO {
3950+
fn io_error(
3951+
zelf: &Py<Self>,
3952+
error: std::io::Error,
3953+
vm: &VirtualMachine,
3954+
) -> PyBaseExceptionRef {
3955+
let exc = error.to_pyexception(vm);
3956+
if let Ok(name) = zelf.as_object().get_attr("name", vm) {
3957+
exc.as_object()
3958+
.set_attr("filename", name, vm)
3959+
.expect("OSError.filename set must success");
3960+
}
3961+
exc
3962+
}
3963+
39503964
#[pygetset]
39513965
fn closed(&self) -> bool {
39523966
self.fd.load() < 0
@@ -4006,79 +4020,87 @@ mod fileio {
40064020
}
40074021

40084022
#[pymethod]
4009-
fn read(&self, read_byte: OptionalSize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
4010-
if !self.mode.load().contains(Mode::READABLE) {
4023+
fn read(
4024+
zelf: &Py<Self>,
4025+
read_byte: OptionalSize,
4026+
vm: &VirtualMachine,
4027+
) -> PyResult<Vec<u8>> {
4028+
if !zelf.mode.load().contains(Mode::READABLE) {
40114029
return Err(new_unsupported_operation(
40124030
vm,
40134031
"File or stream is not readable".to_owned(),
40144032
));
40154033
}
4016-
let mut handle = self.get_fd(vm)?;
4034+
let mut handle = zelf.get_fd(vm)?;
40174035
let bytes = if let Some(read_byte) = read_byte.to_usize() {
40184036
let mut bytes = vec![0; read_byte];
40194037
let n = handle
40204038
.read(&mut bytes)
4021-
.map_err(|err| err.to_pyexception(vm))?;
4039+
.map_err(|err| Self::io_error(zelf, err, vm))?;
40224040
bytes.truncate(n);
40234041
bytes
40244042
} else {
40254043
let mut bytes = vec![];
40264044
handle
40274045
.read_to_end(&mut bytes)
4028-
.map_err(|err| err.to_pyexception(vm))?;
4046+
.map_err(|err| Self::io_error(zelf, err, vm))?;
40294047
bytes
40304048
};
40314049

40324050
Ok(bytes)
40334051
}
40344052

40354053
#[pymethod]
4036-
fn readinto(&self, obj: ArgMemoryBuffer, vm: &VirtualMachine) -> PyResult<usize> {
4037-
if !self.mode.load().contains(Mode::READABLE) {
4054+
fn readinto(zelf: &Py<Self>, obj: ArgMemoryBuffer, vm: &VirtualMachine) -> PyResult<usize> {
4055+
if !zelf.mode.load().contains(Mode::READABLE) {
40384056
return Err(new_unsupported_operation(
40394057
vm,
40404058
"File or stream is not readable".to_owned(),
40414059
));
40424060
}
40434061

4044-
let handle = self.get_fd(vm)?;
4062+
let handle = zelf.get_fd(vm)?;
40454063

40464064
let mut buf = obj.borrow_buf_mut();
40474065
let mut f = handle.take(buf.len() as _);
4048-
let ret = f.read(&mut buf).map_err(|e| e.to_pyexception(vm))?;
4066+
let ret = f
4067+
.read(&mut buf)
4068+
.map_err(|err| Self::io_error(zelf, err, vm))?;
40494069

40504070
Ok(ret)
40514071
}
40524072

40534073
#[pymethod]
4054-
fn write(&self, obj: ArgBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
4055-
if !self.mode.load().contains(Mode::WRITABLE) {
4074+
fn write(zelf: &Py<Self>, obj: ArgBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
4075+
if !zelf.mode.load().contains(Mode::WRITABLE) {
40564076
return Err(new_unsupported_operation(
40574077
vm,
40584078
"File or stream is not writable".to_owned(),
40594079
));
40604080
}
40614081

4062-
let mut handle = self.get_fd(vm)?;
4082+
let mut handle = zelf.get_fd(vm)?;
40634083

40644084
let len = obj
40654085
.with_ref(|b| handle.write(b))
4066-
.map_err(|err| err.to_pyexception(vm))?;
4086+
.map_err(|err| Self::io_error(zelf, err, vm))?;
40674087

40684088
//return number of bytes written
40694089
Ok(len)
40704090
}
40714091

40724092
#[pymethod]
4073-
fn close(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<()> {
4093+
fn close(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<()> {
40744094
let res = iobase_close(zelf.as_object(), vm);
40754095
if !zelf.closefd.load() {
40764096
zelf.fd.store(-1);
40774097
return res;
40784098
}
40794099
let fd = zelf.fd.swap(-1);
40804100
if fd >= 0 {
4081-
Fd(fd).close().map_err(|e| e.to_pyexception(vm))?;
4101+
Fd(fd)
4102+
.close()
4103+
.map_err(|err| Self::io_error(zelf, err, vm))?;
40824104
}
40834105
res
40844106
}

vm/src/stdlib/posix.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ pub mod module {
279279
)
280280
})?;
281281

282-
let metadata = fs::metadata(path.path.clone());
282+
let metadata = fs::metadata(&path.path);
283283

284284
// if it's only checking for F_OK
285285
if flags == AccessFlags::F_OK {
@@ -1982,20 +1982,23 @@ pub mod module {
19821982

19831983
Errno::clear();
19841984
debug_assert_eq!(errno::errno(), 0);
1985-
let raw = match path {
1985+
let raw = match &path {
19861986
OsPathOrFd::Path(path) => {
1987-
let path = CString::new(path.into_bytes())
1988-
.map_err(|_| vm.new_value_error("embedded null character".to_owned()))?;
1987+
let path = path.clone().into_cstring(vm)?;
19891988
unsafe { libc::pathconf(path.as_ptr(), name) }
19901989
}
1991-
OsPathOrFd::Fd(fd) => unsafe { libc::fpathconf(fd, name) },
1990+
OsPathOrFd::Fd(fd) => unsafe { libc::fpathconf(*fd, name) },
19921991
};
19931992

19941993
if raw == -1 {
19951994
if errno::errno() == 0 {
19961995
Ok(None)
19971996
} else {
1998-
Err(io::Error::from(Errno::last()).into_pyexception(vm))
1997+
Err(IOErrorBuilder::with_filename(
1998+
&io::Error::from(Errno::last()),
1999+
path,
2000+
vm,
2001+
))
19992002
}
20002003
} else {
20012004
Ok(Some(raw))

0 commit comments

Comments
 (0)
0