Skip to content

Commit 637870a

Browse files
committed
Add OSError.__reduce__
1 parent 47a3bda commit 637870a

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

vm/src/exceptions.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use self::types::{PyBaseException, PyBaseExceptionRef};
2+
use crate::builtins::tuple::IntoPyTuple;
23
use crate::common::lock::PyRwLock;
34
use crate::{
45
builtins::{
@@ -764,6 +765,7 @@ impl ExceptionZoo {
764765
// second exception filename
765766
"filename2" => ctx.none(),
766767
"__str__" => ctx.new_method("__str__", excs.os_error, os_error_str),
768+
"__reduce__" => ctx.new_method("__str__", excs.os_error, os_error_reduce),
767769
});
768770
// TODO: this isn't really accurate
769771
#[cfg(windows)]
@@ -898,6 +900,42 @@ fn os_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyResult<PyStrR
898900
}
899901
}
900902

903+
fn os_error_reduce(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyTupleRef {
904+
let args = exc.args();
905+
let obj = exc.as_object().to_owned();
906+
let mut result: Vec<PyObjectRef> = vec![obj.class().clone().into()];
907+
908+
if args.len() >= 2 {
909+
// SAFETY: len() == 2 is checked so get_arg 1 or 2 won't panic
910+
let errno = exc.get_arg(0).unwrap();
911+
let msg = exc.get_arg(1).unwrap();
912+
913+
if let Ok(filename) = obj.get_attr("filename", vm) {
914+
if !vm.is_none(&filename) {
915+
let mut args_reduced: Vec<PyObjectRef> = vec![errno, msg, filename];
916+
917+
if let Ok(filename2) = obj.get_attr("filename2", vm) {
918+
if !vm.is_none(&filename2) {
919+
args_reduced.push(filename2);
920+
}
921+
}
922+
result.push(args_reduced.into_pytuple(vm).into());
923+
} else {
924+
result.push(vm.new_tuple((errno, msg)).into());
925+
}
926+
} else {
927+
result.push(vm.new_tuple((errno, msg)).into());
928+
}
929+
} else {
930+
result.push(args.into());
931+
}
932+
933+
if let Some(dict) = obj.dict().filter(|x| !x.is_empty()) {
934+
result.push(dict.into());
935+
}
936+
result.into_pytuple(vm)
937+
}
938+
901939
fn system_exit_code(exc: PyBaseExceptionRef) -> Option<PyObjectRef> {
902940
exc.args.read().first().map(|code| {
903941
match_class!(match code {

0 commit comments

Comments
 (0)