1
1
use crate :: { convert:: ToPyObject , PyObject , PyResult , VirtualMachine } ;
2
2
3
- pub ( crate ) use sys:: { MAXSIZE , MULTIARCH } ;
3
+ pub ( crate ) use sys:: { UnraisableHookArgs , MAXSIZE , MULTIARCH } ;
4
4
5
5
#[ pymodule]
6
6
mod sys {
@@ -16,7 +16,7 @@ mod sys {
16
16
types:: PyStructSequence ,
17
17
version,
18
18
vm:: { Settings , VirtualMachine } ,
19
- PyObjectRef , PyRef , PyRefExact , PyResult ,
19
+ AsObject , PyObjectRef , PyRef , PyRefExact , PyResult ,
20
20
} ;
21
21
use num_traits:: ToPrimitive ;
22
22
use std:: { env, mem, path} ;
@@ -448,6 +448,66 @@ mod sys {
448
448
. into_struct_sequence ( vm) )
449
449
}
450
450
451
+ fn _unraisablehook ( unraisable : UnraisableHookArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
452
+ use super :: PyStderr ;
453
+
454
+ let stderr = PyStderr ( vm) ;
455
+ if !vm. is_none ( & unraisable. object ) {
456
+ if !vm. is_none ( & unraisable. err_msg ) {
457
+ write ! ( stderr, "{}: " , unraisable. err_msg. str ( vm) ?) ;
458
+ } else {
459
+ write ! ( stderr, "Exception ignored in: " ) ;
460
+ }
461
+ // exception in del will be ignored but printed
462
+ let repr = & unraisable. object . repr ( vm) ;
463
+ let str = match repr {
464
+ Ok ( v) => v. to_string ( ) ,
465
+ Err ( _) => format ! (
466
+ "<object {} repr() failed>" ,
467
+ unraisable. object. class( ) . name( )
468
+ ) ,
469
+ } ;
470
+ writeln ! ( stderr, "{str}" ) ;
471
+ } else if !vm. is_none ( & unraisable. err_msg ) {
472
+ writeln ! ( stderr, "{}:" , unraisable. err_msg. str ( vm) ?) ;
473
+ }
474
+
475
+ // TODO: print received unraisable.exc_traceback
476
+ let tb_module = vm. import ( "traceback" , None , 0 ) ?;
477
+ let print_stack = tb_module. get_attr ( "print_stack" , vm) ?;
478
+ vm. invoke ( & print_stack, ( ) ) ?;
479
+
480
+ if vm. is_none ( unraisable. exc_type . as_object ( ) ) {
481
+ // TODO: early return, but with what error?
482
+ }
483
+ assert ! ( unraisable
484
+ . exc_type
485
+ . fast_issubclass( & vm. ctx. exceptions. exception_type) ) ;
486
+
487
+ // TODO: print module name and qualname
488
+
489
+ if !vm. is_none ( & unraisable. exc_value ) {
490
+ write ! ( stderr, ": " ) ;
491
+ if let Ok ( str) = unraisable. exc_value . str ( vm) {
492
+ write ! ( stderr, "{}" , str . as_str( ) ) ;
493
+ } else {
494
+ write ! ( stderr, "<exception str() failed>" ) ;
495
+ }
496
+ }
497
+ writeln ! ( stderr) ;
498
+ // TODO: call file.flush()
499
+
500
+ Ok ( ( ) )
501
+ }
502
+
503
+ #[ pyfunction( name = "__unraisablehook__" ) ]
504
+ #[ pyfunction]
505
+ fn unraisablehook ( unraisable : UnraisableHookArgs , vm : & VirtualMachine ) {
506
+ if let Err ( e) = _unraisablehook ( unraisable, vm) {
507
+ println ! ( "{}" , e. as_object( ) . repr( vm) . unwrap( ) . as_str( ) ) ;
508
+ }
509
+ }
510
+
451
511
#[ pyattr]
452
512
fn hash_info ( vm : & VirtualMachine ) -> PyTupleRef {
453
513
PyHashInfo :: INFO . into_struct_sequence ( vm)
@@ -672,6 +732,19 @@ mod sys {
672
732
#[ cfg( windows) ]
673
733
#[ pyimpl( with( PyStructSequence ) ) ]
674
734
impl WindowsVersion { }
735
+
736
+ #[ pyclass( noattr, module = "sys" , name = "UnraisableHookArgs" ) ]
737
+ #[ derive( Debug , PyStructSequence , TryIntoPyStructSequence ) ]
738
+ pub struct UnraisableHookArgs {
739
+ pub exc_type : PyTypeRef ,
740
+ pub exc_value : PyObjectRef ,
741
+ pub exc_traceback : PyObjectRef ,
742
+ pub err_msg : PyObjectRef ,
743
+ pub object : PyObjectRef ,
744
+ }
745
+
746
+ #[ pyimpl( with( PyStructSequence ) ) ]
747
+ impl UnraisableHookArgs { }
675
748
}
676
749
677
750
pub ( crate ) fn init_module ( vm : & VirtualMachine , module : & PyObject , builtins : & PyObject ) {
0 commit comments