|
1 | 1 | use self::types::{PyBaseException, PyBaseExceptionRef}; |
| 2 | +use crate::builtins::tuple::IntoPyTuple; |
2 | 3 | use crate::common::lock::PyRwLock; |
3 | 4 | use crate::{ |
4 | 5 | builtins::{ |
@@ -773,6 +774,7 @@ impl ExceptionZoo { |
773 | 774 | // second exception filename |
774 | 775 | "filename2" => ctx.none(), |
775 | 776 | "__str__" => ctx.new_method("__str__", excs.os_error, os_error_str), |
| 777 | + "__reduce__" => ctx.new_method("__reduce__", excs.os_error, os_error_reduce), |
776 | 778 | }); |
777 | 779 | // TODO: this isn't really accurate |
778 | 780 | #[cfg(windows)] |
@@ -907,6 +909,42 @@ fn os_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyResult<PyStrR |
907 | 909 | } |
908 | 910 | } |
909 | 911 |
|
| 912 | +fn os_error_reduce(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyTupleRef { |
| 913 | + let args = exc.args(); |
| 914 | + let obj = exc.as_object().to_owned(); |
| 915 | + let mut result: Vec<PyObjectRef> = vec![obj.class().clone().into()]; |
| 916 | + |
| 917 | + if args.len() >= 2 && args.len() <= 5 { |
| 918 | + // SAFETY: len() == 2 is checked so get_arg 1 or 2 won't panic |
| 919 | + let errno = exc.get_arg(0).unwrap(); |
| 920 | + let msg = exc.get_arg(1).unwrap(); |
| 921 | + |
| 922 | + if let Ok(filename) = obj.get_attr("filename", vm) { |
| 923 | + if !vm.is_none(&filename) { |
| 924 | + let mut args_reduced: Vec<PyObjectRef> = vec![errno, msg, filename]; |
| 925 | + |
| 926 | + if let Ok(filename2) = obj.get_attr("filename2", vm) { |
| 927 | + if !vm.is_none(&filename2) { |
| 928 | + args_reduced.push(filename2); |
| 929 | + } |
| 930 | + } |
| 931 | + result.push(args_reduced.into_pytuple(vm).into()); |
| 932 | + } else { |
| 933 | + result.push(vm.new_tuple((errno, msg)).into()); |
| 934 | + } |
| 935 | + } else { |
| 936 | + result.push(vm.new_tuple((errno, msg)).into()); |
| 937 | + } |
| 938 | + } else { |
| 939 | + result.push(args.into()); |
| 940 | + } |
| 941 | + |
| 942 | + if let Some(dict) = obj.dict().filter(|x| !x.is_empty()) { |
| 943 | + result.push(dict.into()); |
| 944 | + } |
| 945 | + result.into_pytuple(vm) |
| 946 | +} |
| 947 | + |
910 | 948 | fn system_exit_code(exc: PyBaseExceptionRef) -> Option<PyObjectRef> { |
911 | 949 | exc.args.read().first().map(|code| { |
912 | 950 | match_class!(match code { |
|
0 commit comments