Add all_warnings context manager

The context manager searches for __warningregistry__ entries that
Python leaves all over the place, clearing them, thereby ensuring
that warnings will always be raised.  This is necessary for the test
suite to detect warnings even if they were raised before under
the "once" filter.
This commit is contained in:
Stefan van der Walt
2014-04-27 02:08:33 +02:00
parent 717f5feb51
commit 132aa8bbd3
2 changed files with 62 additions and 0 deletions
+2
View File
@@ -7,6 +7,8 @@ from .arraypad import pad
from ._regular_grid import regular_grid
from .unique import unique_rows
from ._warnings import all_warnings
__all__ = ['img_as_float',
'img_as_int',
+60
View File
@@ -0,0 +1,60 @@
__all__ = ['all_warnings']
from contextlib import contextmanager
import sys
import warnings
import inspect
@contextmanager
def all_warnings():
"""
Context for use in testing to ensure that all warnings are raised.
Examples
--------
>>> import warnings
>>> def foo():
... warnings.warn(RuntimeWarning("bar"))
We raise the warning once, while the warning filter is set to "once".
Hereafter, the warning is invisible, even with custom filters:
>>> with warnings.catch_warnings():
... warnings.simplefilter('once')
... foo()
We can now run ``foo()`` without a warning being raised:
>>> from numpy.testing import assert_warns
>>> foo()
To catch the warning, we call in the help of ``all_warnings``:
>>> with all_warnings():
... assert_warns(RuntimeWarning, foo)
"""
# Whenever a warning is triggered, Python adds a __warningregistry__
# member to the *calling* module. The exercize here is to find
# and eradicate all those breadcrumbs that were left lying around.
#
# We proceed by first searching all parent calling frames and explicitly
# clearing their warning registries (necessary for the doctests above to
# pass). Then, we search for all submodules of skimage and clear theirs
# as well (necessary for the skimage test suite to pass).
frame = inspect.currentframe()
if frame:
for f in inspect.getouterframes(frame):
f[0].f_locals['__warningregistry__'] = {}
del frame
for mod in sys.modules.values():
try:
mod.__warningregistry__.clear()
except AttributeError:
pass
with warnings.catch_warnings():
warnings.simplefilter("always")
yield