1
1
use crate :: {
2
- builtins:: { PyDict , PyDictRef , PyListRef , PyStrRef , PyTuple , PyTupleRef , PyType , PyTypeRef } ,
2
+ builtins:: {
3
+ PyDict , PyDictRef , PyListRef , PyStr , PyStrInterned , PyStrRef , PyTuple , PyTupleRef ,
4
+ PyTypeRef ,
5
+ } ,
3
6
convert:: { IntoObject , TryFromObject } ,
4
7
types:: PyComparisonOp ,
5
8
AsObject , Context , Py , PyObjectRef , PyResult , VirtualMachine ,
@@ -48,19 +51,26 @@ fn check_matched(obj: &PyObjectRef, arg: &PyObjectRef, vm: &VirtualMachine) -> P
48
51
Ok ( result. is_ok ( ) )
49
52
}
50
53
51
- pub fn py_warn (
52
- category : & Py < PyType > ,
53
- message : String ,
54
- stack_level : usize ,
54
+ fn get_warnings_attr (
55
55
vm : & VirtualMachine ,
56
- ) -> PyResult < ( ) > {
57
- // TODO: use rust warnings module
58
- if let Ok ( module) = vm. import ( "warnings" , None , 0 ) {
59
- if let Ok ( func) = module. get_attr ( "warn" , vm) {
60
- let _ = func. call ( ( message, category. to_owned ( ) , stack_level) , vm) ;
56
+ attr_name : & ' static PyStrInterned ,
57
+ try_import : bool ,
58
+ ) -> PyResult < Option < PyObjectRef > > {
59
+ let module = if try_import
60
+ && !vm
61
+ . state
62
+ . finalizing
63
+ . load ( std:: sync:: atomic:: Ordering :: SeqCst )
64
+ {
65
+ match vm. import ( "warnings" , None , 0 ) {
66
+ Ok ( module) => module,
67
+ Err ( _) => return Ok ( None ) ,
61
68
}
62
- }
63
- Ok ( ( ) )
69
+ } else {
70
+ // TODO: finalizing support
71
+ return Ok ( None ) ;
72
+ } ;
73
+ Ok ( Some ( module. get_attr ( attr_name, vm) ?) )
64
74
}
65
75
66
76
pub fn warn (
@@ -192,7 +202,7 @@ fn already_warned(
192
202
Ok ( true )
193
203
}
194
204
195
- fn normalize_module ( filename : PyStrRef , vm : & VirtualMachine ) -> Option < PyObjectRef > {
205
+ fn normalize_module ( filename : & Py < PyStr > , vm : & VirtualMachine ) -> Option < PyObjectRef > {
196
206
let obj = match filename. char_len ( ) {
197
207
0 => vm. new_pyobj ( "<unknown>" ) ,
198
208
len if len >= 3 && filename. as_str ( ) . ends_with ( ".py" ) => {
@@ -211,16 +221,16 @@ fn warn_explicit(
211
221
lineno : usize ,
212
222
module : Option < PyObjectRef > ,
213
223
registry : PyObjectRef ,
214
- _source_line : Option < PyObjectRef > ,
215
- _source : Option < PyObjectRef > ,
224
+ source_line : Option < PyObjectRef > ,
225
+ source : Option < PyObjectRef > ,
216
226
vm : & VirtualMachine ,
217
227
) -> PyResult < ( ) > {
218
228
let registry: PyObjectRef = registry
219
229
. try_into_value ( vm)
220
230
. map_err ( |_| vm. new_type_error ( "'registry' must be a dict or None" . to_owned ( ) ) ) ?;
221
231
222
232
// Normalize module.
223
- let module = match module. or_else ( || normalize_module ( filename, vm) ) {
233
+ let module = match module. or_else ( || normalize_module ( & filename, vm) ) {
224
234
Some ( module) => module,
225
235
None => return Ok ( ( ) ) ,
226
236
} ;
@@ -280,8 +290,68 @@ fn warn_explicit(
280
290
return Ok ( ( ) ) ;
281
291
}
282
292
293
+ call_show_warning (
294
+ // t_state,
295
+ category,
296
+ message,
297
+ filename,
298
+ lineno, // lineno_obj,
299
+ source_line,
300
+ source,
301
+ vm,
302
+ )
303
+ }
304
+
305
+ fn call_show_warning (
306
+ category : PyTypeRef ,
307
+ message : PyStrRef ,
308
+ filename : PyStrRef ,
309
+ lineno : usize ,
310
+ source_line : Option < PyObjectRef > ,
311
+ source : Option < PyObjectRef > ,
312
+ vm : & VirtualMachine ,
313
+ ) -> PyResult < ( ) > {
314
+ let Some ( show_fn) =
315
+ get_warnings_attr ( vm, identifier ! ( & vm. ctx, _showwarnmsg) , source. is_some ( ) ) ?
316
+ else {
317
+ return show_warning ( filename, lineno, message, category, source_line, vm) ;
318
+ } ;
319
+ if !show_fn. is_callable ( ) {
320
+ return Err (
321
+ vm. new_type_error ( "warnings._showwarnmsg() must be set to a callable" . to_owned ( ) )
322
+ ) ;
323
+ }
324
+ let Some ( warnmsg_cls) = get_warnings_attr ( vm, identifier ! ( & vm. ctx, WarningMessage ) , false ) ?
325
+ else {
326
+ return Err ( vm. new_type_error ( "unable to get warnings.WarningMessage" . to_owned ( ) ) ) ;
327
+ } ;
328
+
329
+ let msg = warnmsg_cls. call (
330
+ vec ! [
331
+ message. into( ) ,
332
+ category. into( ) ,
333
+ filename. into( ) ,
334
+ vm. new_pyobj( lineno) ,
335
+ vm. ctx. none( ) ,
336
+ vm. ctx. none( ) ,
337
+ vm. unwrap_or_none( source) ,
338
+ ] ,
339
+ vm,
340
+ ) ?;
341
+ show_fn. call ( ( msg, ) , vm) ?;
342
+ Ok ( ( ) )
343
+ }
344
+
345
+ fn show_warning (
346
+ _filename : PyStrRef ,
347
+ _lineno : usize ,
348
+ text : PyStrRef ,
349
+ category : PyTypeRef ,
350
+ _source_line : Option < PyObjectRef > ,
351
+ vm : & VirtualMachine ,
352
+ ) -> PyResult < ( ) > {
283
353
let stderr = crate :: stdlib:: sys:: PyStderr ( vm) ;
284
- writeln ! ( stderr, "{}: {}" , category. name( ) , text, ) ;
354
+ writeln ! ( stderr, "{}: {}" , category. name( ) , text. as_str ( ) , ) ;
285
355
Ok ( ( ) )
286
356
}
287
357
0 commit comments