Skip to content

Commit ee4d72e

Browse files
committed
Add attributes to OSError and BlockingIOError
1 parent a19e876 commit ee4d72e

1 file changed

Lines changed: 69 additions & 15 deletions

File tree

vm/src/exceptions.rs

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,7 @@ pub(super) mod types {
963963
use crate::{
964964
builtins::{traceback::PyTracebackRef, PyInt, PyTupleRef, PyTypeRef},
965965
function::{FuncArgs, IntoPyResult},
966+
pyobject::{PyValue, TypeProtocol},
966967
PyObjectRef, PyRef, PyResult, VirtualMachine,
967968
};
968969
use crossbeam_utils::atomic::AtomicCell;
@@ -1160,8 +1161,9 @@ pub(super) mod types {
11601161
os_error,
11611162
"Base class for I/O related errors.",
11621163
os_error_new,
1163-
base_exception_init,
1164+
os_error_init,
11641165
}
1166+
11651167
#[cfg(not(target_arch = "wasm32"))]
11661168
fn os_error_optional_new(
11671169
args: Vec<PyObjectRef>,
@@ -1217,29 +1219,80 @@ pub(super) mod types {
12171219
}
12181220
#[cfg(not(target_arch = "wasm32"))]
12191221
fn os_error_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
1220-
// We need this method, because of how `CPython` copies `init`
1221-
// from `BaseException` in `SimpleExtendsException` macro.
1222-
// See: `BaseException_new`
1223-
if cls.name().deref() == vm.ctx.exceptions.os_error.name().deref() {
1224-
match os_error_optional_new(args.args.to_vec(), vm) {
1225-
Some(error) => error.unwrap().into_pyresult(vm),
1226-
None => PyBaseException::slot_new(cls, args, vm),
1227-
}
1228-
} else {
1229-
PyBaseException::slot_new(cls, args, vm)
1230-
}
1222+
let exc_self: PyBaseExceptionRef =
1223+
if cls.name().deref() == vm.ctx.exceptions.os_error.name().deref() {
1224+
match os_error_optional_new(args.args.to_vec(), vm) {
1225+
Some(error) => error.unwrap(),
1226+
None => PyBaseException::new(args.args.to_vec(), vm)
1227+
.into_ref_with_type(vm, cls)
1228+
.unwrap(),
1229+
}
1230+
} else {
1231+
PyBaseException::new(args.args.to_vec(), vm)
1232+
.into_ref_with_type(vm, cls)
1233+
.unwrap()
1234+
};
1235+
1236+
os_error_parse_args(exc_self.clone(), &args, vm)?;
1237+
exc_self.into_pyresult(vm)
12311238
}
12321239
#[cfg(target_arch = "wasm32")]
12331240
fn os_error_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
1234-
PyBaseException::slot_new(cls, args, vm)
1241+
let exc_self = PyBaseException::new(args.args.to_vec(), vm)
1242+
.into_ref_with_type(vm, cls)
1243+
.unwrap();
1244+
os_error_parse_args(exc_self.clone(), &args, vm)?;
1245+
exc_self.into_pyresult(vm)
1246+
}
1247+
1248+
fn os_error_parse_args(
1249+
exc_self: PyBaseExceptionRef,
1250+
args: &FuncArgs,
1251+
vm: &VirtualMachine,
1252+
) -> PyResult<()> {
1253+
os_error_set_attr(&exc_self, args, vm, "filename", 2)?;
1254+
#[cfg(windows)]
1255+
os_error_set_attr(&exc_self, args, vm, "winerror", 3)?;
1256+
os_error_set_attr(&exc_self, args, vm, "filename2", 4)?;
1257+
Ok(())
12351258
}
12361259

1237-
fn base_exception_init(
1260+
fn os_error_set_attr(
1261+
exc_self: &PyBaseExceptionRef,
1262+
args: &FuncArgs,
1263+
vm: &VirtualMachine,
1264+
attr_name: &str,
1265+
arg_idx: usize,
1266+
) -> PyResult<()> {
1267+
let exc_self = exc_self.as_ref();
1268+
1269+
if let Some(arg) = args.args.as_slice().get(arg_idx).cloned() {
1270+
exc_self.set_attr(attr_name, arg, vm)?;
1271+
}
1272+
1273+
Ok(())
1274+
}
1275+
1276+
fn os_error_init(
12381277
zelf: PyRef<PyBaseException>,
12391278
args: FuncArgs,
12401279
vm: &VirtualMachine,
12411280
) -> PyResult<()> {
1242-
PyBaseException::init(zelf, args, vm)
1281+
PyBaseException::init(zelf.clone(), args.clone(), vm)?;
1282+
1283+
let exc_self = zelf.as_object();
1284+
1285+
if exc_self.class().name().deref() == "BlockingIOError" {
1286+
exc_self.set_attr(
1287+
"characters_written",
1288+
vm.unwrap_or_none(args.args.as_slice().get(2).cloned()),
1289+
vm,
1290+
)?;
1291+
} else {
1292+
os_error_parse_args(zelf, &args, vm)?;
1293+
}
1294+
1295+
Ok(())
12431296
}
12441297

12451298
define_exception! {
@@ -1248,6 +1301,7 @@ pub(super) mod types {
12481301
blocking_io_error,
12491302
"I/O operation would block."
12501303
}
1304+
12511305
define_exception! {
12521306
PyChildProcessError,
12531307
PyOSError,

0 commit comments

Comments
 (0)