11use 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+ } ,
36 convert:: { IntoObject , TryFromObject } ,
47 types:: PyComparisonOp ,
58AsObject , Context , Py , PyObjectRef , PyResult , VirtualMachine ,
@@ -48,19 +51,26 @@ fn check_matched(obj: &PyObjectRef, arg: &PyObjectRef, vm: &VirtualMachine) -> P
4851Ok ( result. is_ok ( ) )
4952}
5053
51- pub fn py_warn (
52- category : & Py < PyType > ,
53- message : String ,
54- stack_level : usize ,
54+ fn get_warnings_attr (
5555vm : & 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 ) ,
6168}
62- }
63- Ok ( ( ) )
69+ } else {
70+ // TODO: finalizing support
71+ return Ok ( None ) ;
72+ } ;
73+ Ok ( Some ( module. get_attr ( attr_name, vm) ?) )
6474}
6575
6676pub fn warn (
@@ -192,7 +202,7 @@ fn already_warned(
192202Ok ( true )
193203}
194204
195- fn normalize_module ( filename : PyStrRef , vm : & VirtualMachine ) ->Option < PyObjectRef > {
205+ fn normalize_module ( filename : & Py < PyStr > , vm : & VirtualMachine ) ->Option < PyObjectRef > {
196206let obj =match filename. char_len ( ) {
1972070 => vm. new_pyobj ( "<unknown>" ) ,
198208 lenif len >=3 && filename. as_str ( ) . ends_with ( ".py" ) =>{
@@ -211,16 +221,16 @@ fn warn_explicit(
211221lineno : usize ,
212222module : Option < PyObjectRef > ,
213223registry : PyObjectRef ,
214- _source_line : Option < PyObjectRef > ,
215- _source : Option < PyObjectRef > ,
224+ source_line : Option < PyObjectRef > ,
225+ source : Option < PyObjectRef > ,
216226vm : & VirtualMachine ,
217227) ->PyResult < ( ) > {
218228let registry: PyObjectRef = registry
219229. try_into_value ( vm)
220230. map_err ( |_| vm. new_type_error ( "'registry' must be a dict or None" . to_owned ( ) ) ) ?;
221231
222232// Normalize module.
223- let module =match module. or_else ( ||normalize_module ( filename, vm) ) {
233+ let module =match module. or_else ( ||normalize_module ( & filename, vm) ) {
224234Some ( module) => module,
225235None =>return Ok ( ( ) ) ,
226236} ;
@@ -280,8 +290,68 @@ fn warn_explicit(
280290return Ok ( ( ) ) ;
281291}
282292
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 < ( ) > {
283353let stderr =crate :: stdlib:: sys:: PyStderr ( vm) ;
284- writeln ! ( stderr, "{}: {}" , category. name( ) , text, ) ;
354+ writeln ! ( stderr, "{}: {}" , category. name( ) , text. as_str ( ) , ) ;
285355Ok ( ( ) )
286356}
287357