Skip to content

Commit 9fd2be4

Browse files
author
dengemann
committed
ENH: context manager + decorator
1 parent a0f0a3d commit 9fd2be4

File tree

1 file changed

+82
-3
lines changed

1 file changed

+82
-3
lines changed

sklearn/utils/testing.py

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import inspect
1212
import pkgutil
1313
import warnings
14+
import sys
1415

1516
import scipy as sp
1617
from functools import wraps
@@ -127,7 +128,6 @@ def assert_warns_message(warning_class, func, message, *args, **kw):
127128
return result
128129

129130

130-
131131
# To remove when we support numpy 1.7
132132
def assert_no_warnings(func, *args, **kw):
133133
# XXX: once we may depend on python >= 2.6, this can be replaced by the
@@ -145,20 +145,99 @@ def assert_no_warnings(func, *args, **kw):
145145
return result
146146

147147

148-
def ignore_warnings(fn):
148+
def ignore_warnings(obj=None):
149+
""" Context manager and decorator to ignore warnings
150+
151+
Examples
152+
--------
153+
>>> with ignore_warnings():
154+
... warnings.warn('buhuhuhu')
155+
>>>
156+
157+
>>>def nasty_warn():
158+
... warnings.warn('buhuhuhu')
159+
... print 42
160+
>>>
161+
162+
>>> ignore_warnings(nasty_warn)()
163+
42
164+
"""
165+
if callable(obj):
166+
return _ignore_warnings(obj)
167+
else:
168+
return _IgnoreWarnings()
169+
170+
171+
def _ignore_warnings(fn):
149172
"""Decorator to catch and hide warnings without visual nesting"""
150173
@wraps(fn)
151174
def wrapper(*args, **kwargs):
152175
# very important to avoid uncontrolled state propagation
153-
clean_warning_registry()
154176
with warnings.catch_warnings(record=True) as w:
155177
warnings.simplefilter('always')
178+
clean_warning_registry()
156179
return fn(*args, **kwargs)
157180
w[:] = []
158181

159182
return wrapper
160183

161184

185+
class _IgnoreWarnings(object):
186+
187+
"""Improved and simplified Python warnings context manager
188+
189+
Copied from Python 2.7.5 and modified as required.
190+
"""
191+
192+
def __init__(self):
193+
"""
194+
Parameters
195+
==========
196+
category : warning class
197+
The category to filter. Defaults to Warning. If None,
198+
all categories will be muted.
199+
"""
200+
self._record = True
201+
self._module = sys.modules['warnings']
202+
self._entered = False
203+
self.log = []
204+
205+
def __repr__(self):
206+
args = []
207+
if self._record:
208+
args.append("record=True")
209+
if self._module is not sys.modules['warnings']:
210+
args.append("module=%r" % self._module)
211+
name = type(self).__name__
212+
return "%s(%s)" % (name, ", ".join(args))
213+
214+
def __enter__(self):
215+
clean_warning_registry() # be safe and not propagate state + chaos
216+
warnings.simplefilter('always')
217+
if self._entered:
218+
raise RuntimeError("Cannot enter %r twice" % self)
219+
self._entered = True
220+
self._filters = self._module.filters
221+
self._module.filters = self._filters[:]
222+
self._showwarning = self._module.showwarning
223+
if self._record:
224+
self.log = []
225+
def showwarning(*args, **kwargs):
226+
self.log.append(warnings.WarningMessage(*args, **kwargs))
227+
self._module.showwarning = showwarning
228+
return self.log
229+
else:
230+
return None
231+
232+
def __exit__(self, *exc_info):
233+
if not self._entered:
234+
raise RuntimeError("Cannot exit %r without entering first" % self)
235+
self._module.filters = self._filters
236+
self._module.showwarning = self._showwarning
237+
self.log[:] = []
238+
clean_warning_registry() # be safe and not propagate state + chaos
239+
240+
162241
try:
163242
from nose.tools import assert_less
164243
except ImportError:

0 commit comments

Comments
 (0)