@@ -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,62 @@ 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+ }
721+
722+ // Print qualname
723+ let qualname = unraisable. exc_type . __qualname__ ( vm) ;
724+ if let Ok ( qualname_str) = qualname. downcast :: < PyStr > ( ) {
725+ write ! ( stderr, "{}" , qualname_str. as_str( ) ) ;
726+ } else {
727+ write ! ( stderr, "{}" , unraisable. exc_type. name( ) ) ;
728+ }
706729
730+ // Print exception value
707731 if !vm. is_none ( & unraisable. exc_value ) {
708- write ! ( stderr, "{} : " , unraisable . exc_type ) ;
732+ write ! ( stderr, ": " ) ;
709733 if let Ok ( str) = unraisable. exc_value . str ( vm) {
710734 write ! ( stderr, "{}" , str . to_str( ) . unwrap_or( "<str with surrogate>" ) ) ;
711735 } else {
712736 write ! ( stderr, "<exception str() failed>" ) ;
713737 }
714738 }
715739 writeln ! ( stderr) ;
716- // TODO: call file.flush()
740+
741+ // Flush stderr
742+ if let Ok ( stderr_obj) = super :: get_stderr ( vm)
743+ && let Ok ( flush) = stderr_obj. get_attr ( "flush" , vm)
744+ {
745+ let _ = flush. call ( ( ) , vm) ;
746+ }
717747
718748 Ok ( ( ) )
719749 }
0 commit comments