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 ,
58 AsObject , Context , Py , PyObjectRef , PyResult , VirtualMachine ,
@@ -48,19 +51,26 @@ fn check_matched(obj: &PyObjectRef, arg: &PyObjectRef, vm: &VirtualMachine) -> P
4851 Ok ( 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 (
5555 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 ) ,
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(
192202 Ok ( true )
193203}
194204
195- fn normalize_module ( filename : PyStrRef , vm : & VirtualMachine ) -> Option < PyObjectRef > {
205+ fn normalize_module ( filename : & Py < PyStr > , vm : & VirtualMachine ) -> Option < PyObjectRef > {
196206 let obj = match filename. char_len ( ) {
197207 0 => vm. new_pyobj ( "<unknown>" ) ,
198208 len if len >= 3 && filename. as_str ( ) . ends_with ( ".py" ) => {
@@ -211,16 +221,16 @@ fn warn_explicit(
211221 lineno : usize ,
212222 module : Option < PyObjectRef > ,
213223 registry : PyObjectRef ,
214- _source_line : Option < PyObjectRef > ,
215- _source : Option < PyObjectRef > ,
224+ source_line : Option < PyObjectRef > ,
225+ source : Option < PyObjectRef > ,
216226 vm : & VirtualMachine ,
217227) -> PyResult < ( ) > {
218228 let 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) ) {
224234 Some ( module) => module,
225235 None => return Ok ( ( ) ) ,
226236 } ;
@@ -280,8 +290,68 @@ fn warn_explicit(
280290 return 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 < ( ) > {
283353 let stderr = crate :: stdlib:: sys:: PyStderr ( vm) ;
284- writeln ! ( stderr, "{}: {}" , category. name( ) , text, ) ;
354+ writeln ! ( stderr, "{}: {}" , category. name( ) , text. as_str ( ) , ) ;
285355 Ok ( ( ) )
286356}
287357
0 commit comments