diff options
author | David Cournapeau <cournape@gmail.com> | 2009-07-21 05:15:46 +0000 |
---|---|---|
committer | David Cournapeau <cournape@gmail.com> | 2009-07-21 05:15:46 +0000 |
commit | 5bda487a73b05826f7bc1aaa565075aa70a8c824 (patch) | |
tree | f86f1d0118a1521c218b8c32946a8f070176194a /numpy | |
parent | 6c8e325c7210cc03caf5c8f9f34e6ce0dd06dc79 (diff) | |
download | numpy-5bda487a73b05826f7bc1aaa565075aa70a8c824.tar.gz |
Add a deprecated decorator to avoid cluttering test run output while checking for raised deprecation.
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/tests/test_numeric.py | 9 | ||||
-rw-r--r-- | numpy/testing/decorators.py | 102 |
2 files changed, 111 insertions, 0 deletions
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index 9353bc960..206c06e66 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -917,6 +917,7 @@ class TestCorrelate(_TestCorrelate): _TestCorrelate._setup(self, dt) self.z2 = self.z1 + @dec.deprecated() def test_complex(self): x = np.array([1, 2, 3, 4+1j], dtype=np.complex) y = np.array([-1, -2j, 3+1j], dtype=np.complex) @@ -924,6 +925,14 @@ class TestCorrelate(_TestCorrelate): z = np.correlate(x, y, 'full') assert_array_almost_equal(z, r_z) + @dec.deprecated() + def test_float(self): + _TestCorrelate.test_float(self) + + @dec.deprecated() + def test_object(self): + _TestCorrelate.test_object(self) + class TestCorrelateNew(_TestCorrelate): old_behavior = False def test_complex(self): diff --git a/numpy/testing/decorators.py b/numpy/testing/decorators.py index 15788141c..174b68771 100644 --- a/numpy/testing/decorators.py +++ b/numpy/testing/decorators.py @@ -9,6 +9,8 @@ setup and teardown functions and so on - see nose.tools for more information. """ +import warnings +import sys def slow(t): """Labels a test as 'slow'. @@ -170,3 +172,103 @@ def knownfailureif(fail_condition, msg=None): return nose.tools.make_decorator(f)(knownfailer) return knownfail_decorator + +# The following two classes are copied from python 2.6 warnings module (context +# manager) +class WarningMessage(object): + + """Holds the result of a single showwarning() call.""" + + _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", + "line") + + def __init__(self, message, category, filename, lineno, file=None, + line=None): + local_values = locals() + for attr in self._WARNING_DETAILS: + setattr(self, attr, local_values[attr]) + self._category_name = category.__name__ if category else None + + def __str__(self): + return ("{message : %r, category : %r, filename : %r, lineno : %s, " + "line : %r}" % (self.message, self._category_name, + self.filename, self.lineno, self.line)) + +class WarningManager: + def __init__(self, record=False, module=None): + self._record = record + self._module = sys.modules['warnings'] if module is None else module + self._entered = False + + def __enter__(self): + if self._entered: + raise RuntimeError("Cannot enter %r twice" % self) + self._entered = True + self._filters = self._module.filters + self._module.filters = self._filters[:] + self._showwarning = self._module.showwarning + if self._record: + log = [] + def showwarning(*args, **kwargs): + log.append(WarningMessage(*args, **kwargs)) + self._module.showwarning = showwarning + return log + else: + return None + + def __exit__(self): + if not self._entered: + raise RuntimeError("Cannot exit %r without entering first" % self) + self._module.filters = self._filters + self._module.showwarning = self._showwarning + +def deprecated(conditional=True): + """This decorator can be used to filter Deprecation Warning, to avoid + printing them during the test suite run, while checking that the test + actually raises a DeprecationWarning. + + Parameters + ---------- + conditional : bool or callable. + Flag to determine whether to mark test as deprecated or not. If the + condition is a callable, it is used at runtime to dynamically make the + decision. + + Returns + ------- + decorator : function + Decorator, which, when applied to a function, causes SkipTest + to be raised when the skip_condition was True, and the function + to be called normally otherwise. + """ + def deprecate_decorator(f): + # Local import to avoid a hard nose dependency and only incur the + # import time overhead at actual test-time. + import nose + from noseclasses import KnownFailureTest + + def _deprecated_imp(*args, **kwargs): + # Poor man's replacement for the with statement + ctx = WarningManager(record=True) + l = ctx.__enter__() + warnings.simplefilter('always') + try: + f(*args, **kwargs) + if not len(l) > 0: + raise AssertionError("No warning raised when calling %s" + % f.__name__) + if not l[0].category is DeprecationWarning: + raise AssertionError("First warning for %s is not a " \ + "DeprecationWarning( is %s)" % (f.__name__, l[0])) + finally: + ctx.__exit__() + + if callable(conditional): + cond = conditional() + else: + cond = conditional + if cond: + return nose.tools.make_decorator(f)(_deprecated_imp) + else: + return f + return deprecate_decorator |