Skip to content

Commit 9aa1f18

Browse files
authored
Unraiseable traceback (#6449)
1 parent 246fab6 commit 9aa1f18

File tree

1 file changed

+41
-9
lines changed

1 file changed

+41
-9
lines changed

crates/vm/src/stdlib/sys.rs

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mod sys {
1515
},
1616
convert::ToPyObject,
1717
frame::FrameRef,
18-
function::{FuncArgs, OptionalArg, PosArgs},
18+
function::{FuncArgs, KwArgs, OptionalArg, PosArgs},
1919
stdlib::{builtins, warnings::warn},
2020
types::PyStructSequence,
2121
version,
@@ -688,32 +688,64 @@ mod sys {
688688
writeln!(stderr, "{}:", unraisable.err_msg.str(vm)?);
689689
}
690690

691-
// TODO: print received unraisable.exc_traceback
692-
let tb_module = vm.import("traceback", 0)?;
693-
let print_stack = tb_module.get_attr("print_stack", vm)?;
694-
print_stack.call((), vm)?;
691+
// Print traceback (using actual exc_traceback, not current stack)
692+
if !vm.is_none(&unraisable.exc_traceback) {
693+
let tb_module = vm.import("traceback", 0)?;
694+
let print_tb = tb_module.get_attr("print_tb", vm)?;
695+
let stderr_obj = super::get_stderr(vm)?;
696+
let kwargs: KwArgs = [("file".to_string(), stderr_obj)].into_iter().collect();
697+
let _ = print_tb.call(
698+
FuncArgs::new(vec![unraisable.exc_traceback.clone()], kwargs),
699+
vm,
700+
);
701+
}
695702

703+
// Check exc_type
696704
if vm.is_none(unraisable.exc_type.as_object()) {
697-
// TODO: early return, but with what error?
705+
return Ok(());
698706
}
699707
assert!(
700708
unraisable
701709
.exc_type
702710
.fast_issubclass(vm.ctx.exceptions.base_exception_type)
703711
);
704712

705-
// TODO: print module name and qualname
713+
// Print module name (if not builtins or __main__)
714+
let module_name = unraisable.exc_type.__module__(vm);
715+
if let Ok(module_str) = module_name.downcast::<PyStr>() {
716+
let module = module_str.as_str();
717+
if module != "builtins" && module != "__main__" {
718+
write!(stderr, "{}.", module);
719+
}
720+
} else {
721+
write!(stderr, "<unknown>.");
722+
}
706723

724+
// Print qualname
725+
let qualname = unraisable.exc_type.__qualname__(vm);
726+
if let Ok(qualname_str) = qualname.downcast::<PyStr>() {
727+
write!(stderr, "{}", qualname_str.as_str());
728+
} else {
729+
write!(stderr, "{}", unraisable.exc_type.name());
730+
}
731+
732+
// Print exception value
707733
if !vm.is_none(&unraisable.exc_value) {
708-
write!(stderr, "{}: ", unraisable.exc_type);
734+
write!(stderr, ": ");
709735
if let Ok(str) = unraisable.exc_value.str(vm) {
710736
write!(stderr, "{}", str.to_str().unwrap_or("<str with surrogate>"));
711737
} else {
712738
write!(stderr, "<exception str() failed>");
713739
}
714740
}
715741
writeln!(stderr);
716-
// TODO: call file.flush()
742+
743+
// Flush stderr
744+
if let Ok(stderr_obj) = super::get_stderr(vm)
745+
&& let Ok(flush) = stderr_obj.get_attr("flush", vm)
746+
{
747+
let _ = flush.call((), vm);
748+
}
717749

718750
Ok(())
719751
}

0 commit comments

Comments
 (0)