@@ -63,20 +63,92 @@ impl From<rustpython_vm::PyRef<rustpython_vm::builtins::PyBaseException>> for Er
6363#[ cfg( feature = "pyo3" ) ]
6464impl From < PyErr > for Error {
6565 fn from ( error : PyErr ) -> Self {
66- let error_msg = match pyo3:: Python :: with_gil ( |py| {
66+ let error_msg = match pyo3:: Python :: with_gil ( |py| -> Result < Vec < String > > {
6767 let traceback_module = py. import ( "traceback" ) ?;
6868 let traceback_object = error
6969 . traceback ( py)
7070 . ok_or ( pyo3:: exceptions:: PyWarning :: new_err ( "No traceback found." ) ) ?;
71- let format_traceback = traceback_module. getattr ( "format_tb" ) ?;
72- format_traceback
73- . call1 ( ( traceback_object, ) )
74- . and_then ( |r| r. extract :: < Vec < String > > ( ) )
71+ let extract_traceback = traceback_module. getattr ( "extract_tb" ) ?;
72+
73+ // Get the formatted traceback lines
74+ let result = extract_traceback. call1 ( ( traceback_object, ) ) . and_then ( |r| {
75+ match r. extract :: < Vec < PyObject > > ( ) {
76+ Ok ( v) => {
77+ let mut formatted_lines = Vec :: new ( ) ;
78+ for arg in v. iter ( ) {
79+ let frame = arg. bind ( py) ;
80+
81+ // Extract filename
82+ let filename = match frame. getattr ( "filename" ) {
83+ Ok ( f) => match f. extract :: < String > ( ) {
84+ Ok ( s) if s == "<string>" . to_string ( ) => {
85+ // Special handling for <string>
86+ frame. setattr ( "filename" , "main.py" ) ?;
87+ let lineno = frame. getattr ( "lineno" ) ?. extract :: < usize > ( ) ?;
88+ frame. setattr ( "lineno" , lineno - 2 ) ?;
89+ "main.py" . to_string ( )
90+ }
91+ Ok ( s) => s,
92+ Err ( _) => "<unknown>" . to_string ( ) ,
93+ } ,
94+ Err ( _) => "<unknown>" . to_string ( ) ,
95+ } ;
96+
97+ // Extract line number
98+ let lineno = match frame. getattr ( "lineno" ) {
99+ Ok ( l) => match l. extract :: < usize > ( ) {
100+ Ok ( n) => n,
101+ Err ( _) => 0 ,
102+ } ,
103+ Err ( _) => 0 ,
104+ } ;
105+
106+ // Extract function name
107+ let name = match frame. getattr ( "name" ) {
108+ Ok ( n) => match n. extract :: < String > ( ) {
109+ Ok ( s) => s,
110+ Err ( _) => "<unknown>" . to_string ( ) ,
111+ } ,
112+ Err ( _) => "<unknown>" . to_string ( ) ,
113+ } ;
114+
115+ // Extract line content (if available)
116+ let line = match frame. getattr ( "line" ) {
117+ Ok ( l) => match l. extract :: < Option < String > > ( ) {
118+ Ok ( Some ( s) ) => format ! ( "\t {}" , s) ,
119+ _ => "" . to_string ( ) ,
120+ } ,
121+ Err ( _) => "" . to_string ( ) ,
122+ } ;
123+
124+ // Format the line like requested
125+ let formatted_line = format ! (
126+ "File \" {}\" , line {}, in {}\n {}" ,
127+ filename, lineno, name, line
128+ ) ;
129+
130+ formatted_lines. push ( formatted_line) ;
131+ }
132+
133+ Ok ( formatted_lines)
134+ }
135+ Err ( _) => Err ( PyErr :: new :: < pyo3:: exceptions:: PyValueError , _ > (
136+ "Failed to extract traceback" ,
137+ ) ) ,
138+ }
139+ } ) ?;
140+
141+ // Add traceback header
142+ let mut full_traceback = vec ! [ "Traceback (most recent call last):" . to_string( ) ] ;
143+ full_traceback. extend ( result) ;
144+
145+ // Add error type and message
146+ full_traceback. push ( error. to_string ( ) ) ;
147+
148+ Ok ( full_traceback)
75149 } ) {
76- Ok ( formatted) => formatted. join ( "" ) ,
77- Err ( _) => {
78- error. to_string ( ) // Fall back to simple error message
79- }
150+ Ok ( formatted) => formatted. join ( "\n " ) ,
151+ Err ( _) => error. to_string ( ) , // Fall back to simple error message
80152 } ;
81153
82154 Error :: String ( error_msg)
0 commit comments