@@ -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