@@ -63,20 +63,92 @@ impl From<rustpython_vm::PyRef<rustpython_vm::builtins::PyBaseException>> for Er
63
63
#[ cfg( feature = "pyo3" ) ]
64
64
impl From < PyErr > for Error {
65
65
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 > > {
67
67
let traceback_module = py. import ( "traceback" ) ?;
68
68
let traceback_object = error
69
69
. traceback ( py)
70
70
. 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)
75
149
} ) {
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
80
152
} ;
81
153
82
154
Error :: String ( error_msg)
0 commit comments