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')
```
This commit is contained in:
Dean Li
2021-10-30 18:44:40 +08:00
parent a19e87640c
commit d46f5ba7ab

View File

@@ -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<PyStrRef> {
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<PyObjectRef> {
exc.args.read().as_slice().first().map(|code| {
match_class!(match code {