From d46f5ba7abefa792a8b7436b397f2e546e280f51 Mon Sep 17 00:00:00 2001 From: Dean Li Date: Sat, 30 Oct 2021 18:44:40 +0800 Subject: [PATCH] Implement __str__ for OSError In CPython, __str__ and __repr__ for OSError show different results. This PR try to match this behavior but without the part after the message (in following example is "'123' -> '456'"). ``` In : exc.__repr__() Out: "FileNotFoundError(2, 'No such file or directory')" In : exc.__str__() Out: "[Errno 2] No such file or directory: '123' -> '456'" In : exc.args Out: (2, 'No such file or directory') ``` --- vm/src/exceptions.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 3307eb63b..65d322b41 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -745,6 +745,7 @@ impl ExceptionZoo { "filename" => ctx.none(), // second exception filename "filename2" => ctx.none(), + "__str__" => ctx.new_method("__str__", excs.os_error.clone(), os_error_str), }); // TODO: this isn't really accurate #[cfg(windows)] @@ -859,6 +860,21 @@ fn key_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyStrRef { } } +fn os_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyResult { + let args = exc.args(); + if args.as_slice().len() == 2 { + // SAFETY: len() == 2 is checked so get_arg 1 or 2 won't panic + let s = format!( + "[Errno {}] {}", + exc.get_arg(0).unwrap().str(vm)?, + exc.get_arg(1).unwrap().str(vm)? + ); + Ok(vm.ctx.new_str(s)) + } else { + Ok(exc.str(vm)) + } +} + fn system_exit_code(exc: PyBaseExceptionRef) -> Option { exc.args.read().as_slice().first().map(|code| { match_class!(match code {