1
1
use crate :: function:: PyFuncArgs ;
2
2
use crate :: obj:: objsequence;
3
+ use crate :: obj:: objtuple:: { PyTuple , PyTupleRef } ;
3
4
use crate :: obj:: objtype;
4
5
use crate :: obj:: objtype:: PyClassRef ;
5
6
use crate :: pyobject:: { create_type, IdProtocol , PyContext , PyObjectRef , PyResult , TypeProtocol } ;
@@ -8,16 +9,12 @@ use std::fs::File;
8
9
use std:: io:: { BufRead , BufReader } ;
9
10
10
11
fn exception_init ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
11
- let zelf = args. args [ 0 ] . clone ( ) ;
12
- let msg = if args. args . len ( ) > 1 {
13
- args. args [ 1 ] . clone ( )
14
- } else {
15
- let empty_string = String :: default ( ) ;
16
- vm. new_str ( empty_string)
17
- } ;
12
+ let exc_self = args. args [ 0 ] . clone ( ) ;
13
+ let exc_args = vm. ctx . new_tuple ( args. args [ 1 ..] . to_vec ( ) ) ;
14
+ vm. set_attr ( & exc_self, "args" , exc_args) ?;
15
+
18
16
let traceback = vm. ctx . new_list ( Vec :: new ( ) ) ;
19
- vm. set_attr ( & zelf, "msg" , msg) ?;
20
- vm. set_attr ( & zelf, "__traceback__" , traceback) ?;
17
+ vm. set_attr ( & exc_self, "__traceback__" , traceback) ?;
21
18
Ok ( vm. get_none ( ) )
22
19
}
23
20
@@ -113,9 +110,42 @@ pub fn print_exception_inner(vm: &VirtualMachine, exc: &PyObjectRef) {
113
110
println ! ( "No traceback set on exception" ) ;
114
111
}
115
112
116
- match vm. to_str ( exc) {
117
- Ok ( txt) => println ! ( "{}" , txt. value) ,
118
- Err ( err) => println ! ( "Error during error {:?}" , err) ,
113
+ let varargs = vm
114
+ . get_attribute ( exc. clone ( ) , "args" )
115
+ . unwrap ( )
116
+ . downcast :: < PyTuple > ( )
117
+ . expect ( "'args' must be a tuple" ) ;
118
+ let args_repr = exception_args_as_string ( vm, varargs) ;
119
+
120
+ let exc_name = exc. class ( ) . name . clone ( ) ;
121
+ match args_repr. len ( ) {
122
+ 0 => println ! ( "{}" , exc_name) ,
123
+ 1 => println ! ( "{}: {}" , exc_name, args_repr[ 0 ] ) ,
124
+ _ => println ! ( "{}: ({})" , exc_name, args_repr. join( ", " ) ) ,
125
+ }
126
+ }
127
+
128
+ fn exception_args_as_string ( vm : & VirtualMachine , varargs : PyTupleRef ) -> Vec < String > {
129
+ match varargs. elements . len ( ) {
130
+ 0 => vec ! [ ] ,
131
+ 1 => {
132
+ let args0_repr = match vm. to_repr ( & varargs. elements [ 0 ] ) {
133
+ Ok ( args0_repr) => args0_repr. value . clone ( ) ,
134
+ Err ( _) => "<element repr() failed>" . to_string ( ) ,
135
+ } ;
136
+ vec ! [ args0_repr]
137
+ }
138
+ _ => {
139
+ let mut args_vec = Vec :: with_capacity ( varargs. elements . len ( ) ) ;
140
+ for vararg in & varargs. elements {
141
+ let arg_repr = match vm. to_repr ( vararg) {
142
+ Ok ( arg_repr) => arg_repr. value . clone ( ) ,
143
+ Err ( _) => "<element repr() failed>" . to_string ( ) ,
144
+ } ;
145
+ args_vec. push ( arg_repr) ;
146
+ }
147
+ args_vec
148
+ }
119
149
}
120
150
}
121
151
@@ -125,19 +155,40 @@ fn exception_str(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
125
155
args,
126
156
required = [ ( exc, Some ( vm. ctx. exceptions. exception_type. clone( ) ) ) ]
127
157
) ;
128
- let msg = if let Ok ( m) = vm. get_attribute ( exc. clone ( ) , "msg" ) {
129
- match vm. to_pystr ( & m) {
130
- Ok ( msg) => msg,
131
- _ => "<exception str() failed>" . to_string ( ) ,
132
- }
133
- } else {
134
- panic ! ( "Error message must be set" ) ;
158
+ let args = vm
159
+ . get_attribute ( exc. clone ( ) , "args" )
160
+ . unwrap ( )
161
+ . downcast :: < PyTuple > ( )
162
+ . expect ( "'args' must be a tuple" ) ;
163
+ let args_str = exception_args_as_string ( vm, args) ;
164
+ let joined_str = match args_str. len ( ) {
165
+ 0 => "" . to_string ( ) ,
166
+ 1 => args_str[ 0 ] . to_string ( ) ,
167
+ _ => format ! ( "({})" , args_str. join( ", " ) ) ,
135
168
} ;
136
- let mut exc_repr = exc. class ( ) . name . clone ( ) ;
137
- if !msg. is_empty ( ) {
138
- & exc_repr. push_str ( & format ! ( ": {}" , msg) ) ;
139
- }
140
- Ok ( vm. new_str ( exc_repr) )
169
+ Ok ( vm. new_str ( joined_str) )
170
+ }
171
+
172
+ fn exception_repr ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
173
+ arg_check ! (
174
+ vm,
175
+ args,
176
+ required = [ ( exc, Some ( vm. ctx. exceptions. exception_type. clone( ) ) ) ]
177
+ ) ;
178
+ let args = vm
179
+ . get_attribute ( exc. clone ( ) , "args" )
180
+ . unwrap ( )
181
+ . downcast :: < PyTuple > ( )
182
+ . expect ( "'args' must be a tuple" ) ;
183
+ let args_repr = exception_args_as_string ( vm, args) ;
184
+
185
+ let exc_name = exc. class ( ) . name . clone ( ) ;
186
+ let joined_str = match args_repr. len ( ) {
187
+ 0 => format ! ( "{}()" , exc_name) ,
188
+ 1 => format ! ( "{}({},)" , exc_name, args_repr[ 0 ] ) ,
189
+ _ => format ! ( "{}({})" , exc_name, args_repr. join( ", " ) ) ,
190
+ } ;
191
+ Ok ( vm. new_str ( joined_str) )
141
192
}
142
193
143
194
#[ derive( Debug ) ]
@@ -266,6 +317,7 @@ pub fn init(context: &PyContext) {
266
317
267
318
let exception_type = & context. exceptions . exception_type ;
268
319
extend_class ! ( context, exception_type, {
269
- "__str__" => context. new_rustfunc( exception_str)
320
+ "__str__" => context. new_rustfunc( exception_str) ,
321
+ "__repr__" => context. new_rustfunc( exception_repr) ,
270
322
} ) ;
271
323
}
0 commit comments