@@ -368,50 +368,67 @@ def open_urlresource(url, *args, **kw):
368368
369369
370370class WarningMessage (object ):
371- "Holds the result of the latest showwarning() call"
371+ "Holds the result of a single showwarning() call"
372+ _WARNING_DETAILS = "message category filename lineno line" .split ()
373+ def __init__ (self , message , category , filename , lineno , line = None ):
374+ for attr in self ._WARNING_DETAILS :
375+ setattr (self , attr , locals ()[attr ])
376+ self ._category_name = category .__name__ if category else None
377+
378+ def __str__ (self ):
379+ return ("{message : %r, category : %r, filename : %r, lineno : %s, "
380+ "line : %r}" % (self .message , self ._category_name ,
381+ self .filename , self .lineno , self .line ))
382+
383+ class WarningRecorder (object ):
384+ "Records the result of any showwarning calls"
372385 def __init__ (self ):
373- self .message = None
374- self .category = None
375- self .filename = None
376- self .lineno = None
377-
378- def _showwarning (self , message , category , filename , lineno , file = None ,
379- line = None ):
380- self .message = message
381- self .category = category
382- self .filename = filename
383- self .lineno = lineno
384- self .line = line
386+ self .warnings = []
387+ self ._set_last (None )
388+
389+ def _showwarning (self , message , category , filename , lineno ,
390+ file = None , line = None ):
391+ wm = WarningMessage (message , category , filename , lineno , line )
392+ self .warnings .append (wm )
393+ self ._set_last (wm )
394+
395+ def _set_last (self , last_warning ):
396+ if last_warning is None :
397+ for attr in WarningMessage ._WARNING_DETAILS :
398+ setattr (self , attr , None )
399+ else :
400+ for attr in WarningMessage ._WARNING_DETAILS :
401+ setattr (self , attr , getattr (last_warning , attr ))
385402
386403 def reset (self ):
387- self ._showwarning (* ((None ,)* 6 ))
404+ self .warnings = []
405+ self ._set_last (None )
388406
389407 def __str__ (self ):
390- return ("{message : %r, category : %r, filename : %r, lineno : %s, "
391- "line : %r}" % (self .message ,
392- self .category .__name__ if self .category else None ,
393- self .filename , self .lineno , self .line ))
394-
408+ return '[%s]' % (', ' .join (map (str , self .warnings )))
395409
396410@contextlib .contextmanager
397411def catch_warning (module = warnings , record = True ):
398- """
399- Guard the warnings filter from being permanently changed and record the
400- data of the last warning that has been issued.
412+ """Guard the warnings filter from being permanently changed and
413+ optionally record the details of any warnings that are issued.
401414
402415 Use like this:
403416
404417 with catch_warning() as w:
405418 warnings.warn("foo")
406419 assert str(w.message) == "foo"
407420 """
408- original_filters = module .filters [:]
421+ original_filters = module .filters
409422 original_showwarning = module .showwarning
410423 if record :
411- warning_obj = WarningMessage ()
412- module .showwarning = warning_obj ._showwarning
424+ recorder = WarningRecorder ()
425+ module .showwarning = recorder ._showwarning
426+ else :
427+ recorder = None
413428 try :
414- yield warning_obj if record else None
429+ # Replace the filters with a copy of the original
430+ module .filters = module .filters [:]
431+ yield recorder
415432 finally :
416433 module .showwarning = original_showwarning
417434 module .filters = original_filters
@@ -421,7 +438,7 @@ class CleanImport(object):
421438 """Context manager to force import to return a new module reference.
422439
423440 This is useful for testing module-level behaviours, such as
424- the emission of a DepreciationWarning on import.
441+ the emission of a DeprecationWarning on import.
425442
426443 Use like this:
427444
0 commit comments