@@ -4,7 +4,8 @@ use crate::object::{Traverse, TraverseFn};
44use crate :: {
55 AsObject , Context , Py , PyObjectRef , PyPayload , PyRef , PyResult , TryFromObject , VirtualMachine ,
66 builtins:: {
7- PyNone , PyStr , PyStrRef , PyTuple , PyTupleRef , PyType , PyTypeRef , traceback:: PyTracebackRef ,
7+ PyNone , PyStr , PyStrRef , PyTuple , PyTupleRef , PyType , PyTypeRef ,
8+ traceback:: { PyTraceback , PyTracebackRef } ,
89 } ,
910 class:: { PyClassImpl , StaticType } ,
1011 convert:: { ToPyException , ToPyObject } ,
@@ -324,7 +325,7 @@ impl VirtualMachine {
324325 let ctor = ExceptionCtor :: try_from_object ( self , exc_type) ?;
325326 let exc = ctor. instantiate_value ( exc_val, self ) ?;
326327 if let Some ( tb) = Option :: < PyTracebackRef > :: try_from_object ( self , exc_tb) ? {
327- exc. set_traceback ( Some ( tb) ) ;
328+ exc. set_traceback_typed ( Some ( tb) ) ;
328329 }
329330 Ok ( exc)
330331 }
@@ -584,7 +585,25 @@ impl PyBaseException {
584585 }
585586
586587 #[ pygetset( magic, setter) ]
587- pub fn set_traceback ( & self , traceback : Option < PyTracebackRef > ) {
588+ pub fn set_traceback ( & self , value : PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
589+ let traceback = if vm. is_none ( & value) {
590+ None
591+ } else {
592+ match value. downcast :: < PyTraceback > ( ) {
593+ Ok ( tb) => Some ( tb) ,
594+ Err ( _) => {
595+ return Err (
596+ vm. new_type_error ( "__traceback__ must be a traceback or None" . to_owned ( ) )
597+ ) ;
598+ }
599+ }
600+ } ;
601+ self . set_traceback_typed ( traceback) ;
602+ Ok ( ( ) )
603+ }
604+
605+ // Helper method for internal use that doesn't require PyObjectRef
606+ pub ( crate ) fn set_traceback_typed ( & self , traceback : Option < PyTracebackRef > ) {
588607 * self . traceback . write ( ) = traceback;
589608 }
590609
0 commit comments