@@ -4,12 +4,13 @@ use crate::obj::objstr::{PyString, PyStringRef};
4
4
use crate :: obj:: objtraceback:: PyTracebackRef ;
5
5
use crate :: obj:: objtuple:: { PyTuple , PyTupleRef } ;
6
6
use crate :: obj:: objtype:: { self , PyClass , PyClassRef } ;
7
+ use crate :: py_serde;
7
8
use crate :: pyobject:: {
8
9
PyClassImpl , PyContext , PyIterable , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
9
10
TypeProtocol ,
10
11
} ;
11
12
use crate :: types:: create_type;
12
- use crate :: vm :: VirtualMachine ;
13
+ use crate :: VirtualMachine ;
13
14
use itertools:: Itertools ;
14
15
use std:: cell:: { Cell , RefCell } ;
15
16
use std:: fmt;
@@ -245,10 +246,8 @@ pub fn write_exception_inner<W: Write>(
245
246
) -> io:: Result < ( ) > {
246
247
if let Some ( tb) = exc. traceback . borrow ( ) . clone ( ) {
247
248
writeln ! ( output, "Traceback (most recent call last):" ) ?;
248
- let mut tb = Some ( & tb) ;
249
- while let Some ( traceback) = tb {
250
- write_traceback_entry ( output, traceback) ?;
251
- tb = traceback. next . as_ref ( ) ;
249
+ for tb in tb. iter ( ) {
250
+ write_traceback_entry ( output, & tb) ?;
252
251
}
253
252
}
254
253
@@ -660,3 +659,71 @@ pub fn init(ctx: &PyContext) {
660
659
"reason" => ctx. new_property( make_arg_getter( 3 ) ) ,
661
660
} ) ;
662
661
}
662
+
663
+ pub struct SerializeException < ' s > {
664
+ vm : & ' s VirtualMachine ,
665
+ exc : & ' s PyBaseExceptionRef ,
666
+ }
667
+
668
+ impl < ' s > SerializeException < ' s > {
669
+ pub fn new ( vm : & ' s VirtualMachine , exc : & ' s PyBaseExceptionRef ) -> Self {
670
+ SerializeException { vm, exc }
671
+ }
672
+ }
673
+
674
+ impl serde:: Serialize for SerializeException < ' _ > {
675
+ fn serialize < S : serde:: Serializer > ( & self , s : S ) -> Result < S :: Ok , S :: Error > {
676
+ use serde:: ser:: * ;
677
+
678
+ let mut struc = s. serialize_struct ( "PyBaseException" , 7 ) ?;
679
+ struc. serialize_field ( "exc_type" , & self . exc . class ( ) . name ) ?;
680
+ let tbs = {
681
+ struct Tracebacks ( PyTracebackRef ) ;
682
+ impl serde:: Serialize for Tracebacks {
683
+ fn serialize < S : serde:: Serializer > ( & self , s : S ) -> Result < S :: Ok , S :: Error > {
684
+ let mut s = s. serialize_seq ( None ) ?;
685
+ for tb in self . 0 . iter ( ) {
686
+ s. serialize_element ( & * tb) ?;
687
+ }
688
+ s. end ( )
689
+ }
690
+ }
691
+ self . exc . traceback ( ) . map ( Tracebacks )
692
+ } ;
693
+ struc. serialize_field ( "traceback" , & tbs) ?;
694
+ struc. serialize_field (
695
+ "cause" ,
696
+ & self . exc . cause ( ) . as_ref ( ) . map ( |e| Self :: new ( self . vm , e) ) ,
697
+ ) ?;
698
+ struc. serialize_field (
699
+ "context" ,
700
+ & self . exc . context ( ) . as_ref ( ) . map ( |e| Self :: new ( self . vm , e) ) ,
701
+ ) ?;
702
+ struc. serialize_field ( "suppress_context" , & self . exc . suppress_context . get ( ) ) ?;
703
+
704
+ let args = {
705
+ struct Args < ' vm > ( & ' vm VirtualMachine , PyTupleRef ) ;
706
+ impl serde:: Serialize for Args < ' _ > {
707
+ fn serialize < S : serde:: Serializer > ( & self , s : S ) -> Result < S :: Ok , S :: Error > {
708
+ s. collect_seq (
709
+ self . 1
710
+ . as_slice ( )
711
+ . iter ( )
712
+ . map ( |arg| py_serde:: PyObjectSerializer :: new ( self . 0 , arg) ) ,
713
+ )
714
+ }
715
+ }
716
+ Args ( self . vm , self . exc . args ( ) )
717
+ } ;
718
+ struc. serialize_field ( "args" , & args) ?;
719
+
720
+ let rendered = {
721
+ let mut rendered = Vec :: < u8 > :: new ( ) ;
722
+ write_exception ( & mut rendered, self . vm , & self . exc ) . map_err ( S :: Error :: custom) ?;
723
+ String :: from_utf8 ( rendered) . map_err ( S :: Error :: custom) ?
724
+ } ;
725
+ struc. serialize_field ( "rendered" , & rendered) ?;
726
+
727
+ struc. end ( )
728
+ }
729
+ }
0 commit comments