##// END OF EJS Templates
Make IPython work if a recent numpy is not available....
Fernando Perez -
Show More
@@ -0,0 +1,120 b''
1 # IPython: modified copy of numpy.testing.utils, so numpy.testing.decorators
2 # works without numpy being installed.
3 """
4 Utility function to facilitate testing.
5 """
6
7 import os
8 import sys
9 import re
10 import operator
11 import types
12 import warnings
13
14 # The following two classes are copied from python 2.6 warnings module (context
15 # manager)
16 class WarningMessage(object):
17
18 """
19 Holds the result of a single showwarning() call.
20
21 Notes
22 -----
23 `WarningMessage` is copied from the Python 2.6 warnings module,
24 so it can be used in NumPy with older Python versions.
25
26 """
27
28 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
29 "line")
30
31 def __init__(self, message, category, filename, lineno, file=None,
32 line=None):
33 local_values = locals()
34 for attr in self._WARNING_DETAILS:
35 setattr(self, attr, local_values[attr])
36 if category:
37 self._category_name = category.__name__
38 else:
39 self._category_name = None
40
41 def __str__(self):
42 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
43 "line : %r}" % (self.message, self._category_name,
44 self.filename, self.lineno, self.line))
45
46 class WarningManager:
47 """
48 A context manager that copies and restores the warnings filter upon
49 exiting the context.
50
51 The 'record' argument specifies whether warnings should be captured by a
52 custom implementation of ``warnings.showwarning()`` and be appended to a
53 list returned by the context manager. Otherwise None is returned by the
54 context manager. The objects appended to the list are arguments whose
55 attributes mirror the arguments to ``showwarning()``.
56
57 The 'module' argument is to specify an alternative module to the module
58 named 'warnings' and imported under that name. This argument is only useful
59 when testing the warnings module itself.
60
61 Notes
62 -----
63 `WarningManager` is a copy of the ``catch_warnings`` context manager
64 from the Python 2.6 warnings module, with slight modifications.
65 It is copied so it can be used in NumPy with older Python versions.
66
67 """
68 def __init__(self, record=False, module=None):
69 self._record = record
70 if module is None:
71 self._module = sys.modules['warnings']
72 else:
73 self._module = module
74 self._entered = False
75
76 def __enter__(self):
77 if self._entered:
78 raise RuntimeError("Cannot enter %r twice" % self)
79 self._entered = True
80 self._filters = self._module.filters
81 self._module.filters = self._filters[:]
82 self._showwarning = self._module.showwarning
83 if self._record:
84 log = []
85 def showwarning(*args, **kwargs):
86 log.append(WarningMessage(*args, **kwargs))
87 self._module.showwarning = showwarning
88 return log
89 else:
90 return None
91
92 def __exit__(self):
93 if not self._entered:
94 raise RuntimeError("Cannot exit %r without entering first" % self)
95 self._module.filters = self._filters
96 self._module.showwarning = self._showwarning
97
98 def assert_warns(warning_class, func, *args, **kw):
99 """Fail unless a warning of class warning_class is thrown by callable when
100 invoked with arguments args and keyword arguments kwargs.
101
102 If a different type of warning is thrown, it will not be caught, and the
103 test case will be deemed to have suffered an error.
104 """
105
106 # XXX: once we may depend on python >= 2.6, this can be replaced by the
107 # warnings module context manager.
108 ctx = WarningManager(record=True)
109 l = ctx.__enter__()
110 warnings.simplefilter('always')
111 try:
112 func(*args, **kw)
113 if not len(l) > 0:
114 raise AssertionError("No warning raised when calling %s"
115 % func.__name__)
116 if not l[0].category is warning_class:
117 raise AssertionError("First warning for %s is not a " \
118 "%s( is %s)" % (func.__name__, warning_class, l[0]))
119 finally:
120 ctx.__exit__()
@@ -1,275 +1,284 b''
1 """
1 """
2 Decorators for labeling and modifying behavior of test objects.
2 Decorators for labeling and modifying behavior of test objects.
3
3
4 Decorators that merely return a modified version of the original
4 Decorators that merely return a modified version of the original
5 function object are straightforward. Decorators that return a new
5 function object are straightforward. Decorators that return a new
6 function object need to use
6 function object need to use
7 ::
7 ::
8
8
9 nose.tools.make_decorator(original_function)(decorator)
9 nose.tools.make_decorator(original_function)(decorator)
10
10
11 in returning the decorator, in order to preserve meta-data such as
11 in returning the decorator, in order to preserve meta-data such as
12 function name, setup and teardown functions and so on - see
12 function name, setup and teardown functions and so on - see
13 ``nose.tools`` for more information.
13 ``nose.tools`` for more information.
14
14
15 """
15 """
16 import warnings
16 import warnings
17 import sys
17 import sys
18
18
19 from numpy.testing.utils import \
19 # IPython changes: make this work if numpy not available
20 WarningManager, WarningMessage
20 # Original code:
21 #from numpy.testing.utils import \
22 # WarningManager, WarningMessage
23 # Our version:
24 try:
25 from numpy.testing.utils import WarningManager, WarningMessage
26 except ImportError:
27 from _numpy_testing_utils import WarningManager, WarningMessage
28
29 # End IPython changes
21
30
22 def slow(t):
31 def slow(t):
23 """
32 """
24 Label a test as 'slow'.
33 Label a test as 'slow'.
25
34
26 The exact definition of a slow test is obviously both subjective and
35 The exact definition of a slow test is obviously both subjective and
27 hardware-dependent, but in general any individual test that requires more
36 hardware-dependent, but in general any individual test that requires more
28 than a second or two should be labeled as slow (the whole suite consits of
37 than a second or two should be labeled as slow (the whole suite consits of
29 thousands of tests, so even a second is significant).
38 thousands of tests, so even a second is significant).
30
39
31 Parameters
40 Parameters
32 ----------
41 ----------
33 t : callable
42 t : callable
34 The test to label as slow.
43 The test to label as slow.
35
44
36 Returns
45 Returns
37 -------
46 -------
38 t : callable
47 t : callable
39 The decorated test `t`.
48 The decorated test `t`.
40
49
41 Examples
50 Examples
42 --------
51 --------
43 The `numpy.testing` module includes ``import decorators as dec``.
52 The `numpy.testing` module includes ``import decorators as dec``.
44 A test can be decorated as slow like this::
53 A test can be decorated as slow like this::
45
54
46 from numpy.testing import *
55 from numpy.testing import *
47
56
48 @dec.slow
57 @dec.slow
49 def test_big(self):
58 def test_big(self):
50 print 'Big, slow test'
59 print 'Big, slow test'
51
60
52 """
61 """
53
62
54 t.slow = True
63 t.slow = True
55 return t
64 return t
56
65
57 def setastest(tf=True):
66 def setastest(tf=True):
58 """
67 """
59 Signals to nose that this function is or is not a test.
68 Signals to nose that this function is or is not a test.
60
69
61 Parameters
70 Parameters
62 ----------
71 ----------
63 tf : bool
72 tf : bool
64 If True, specifies that the decorated callable is a test.
73 If True, specifies that the decorated callable is a test.
65 If False, specifies that the decorated callable is not a test.
74 If False, specifies that the decorated callable is not a test.
66 Default is True.
75 Default is True.
67
76
68 Notes
77 Notes
69 -----
78 -----
70 This decorator can't use the nose namespace, because it can be
79 This decorator can't use the nose namespace, because it can be
71 called from a non-test module. See also ``istest`` and ``nottest`` in
80 called from a non-test module. See also ``istest`` and ``nottest`` in
72 ``nose.tools``.
81 ``nose.tools``.
73
82
74 Examples
83 Examples
75 --------
84 --------
76 `setastest` can be used in the following way::
85 `setastest` can be used in the following way::
77
86
78 from numpy.testing.decorators import setastest
87 from numpy.testing.decorators import setastest
79
88
80 @setastest(False)
89 @setastest(False)
81 def func_with_test_in_name(arg1, arg2):
90 def func_with_test_in_name(arg1, arg2):
82 pass
91 pass
83
92
84 """
93 """
85 def set_test(t):
94 def set_test(t):
86 t.__test__ = tf
95 t.__test__ = tf
87 return t
96 return t
88 return set_test
97 return set_test
89
98
90 def skipif(skip_condition, msg=None):
99 def skipif(skip_condition, msg=None):
91 """
100 """
92 Make function raise SkipTest exception if a given condition is true.
101 Make function raise SkipTest exception if a given condition is true.
93
102
94 If the condition is a callable, it is used at runtime to dynamically
103 If the condition is a callable, it is used at runtime to dynamically
95 make the decision. This is useful for tests that may require costly
104 make the decision. This is useful for tests that may require costly
96 imports, to delay the cost until the test suite is actually executed.
105 imports, to delay the cost until the test suite is actually executed.
97
106
98 Parameters
107 Parameters
99 ----------
108 ----------
100 skip_condition : bool or callable
109 skip_condition : bool or callable
101 Flag to determine whether to skip the decorated test.
110 Flag to determine whether to skip the decorated test.
102 msg : str, optional
111 msg : str, optional
103 Message to give on raising a SkipTest exception. Default is None.
112 Message to give on raising a SkipTest exception. Default is None.
104
113
105 Returns
114 Returns
106 -------
115 -------
107 decorator : function
116 decorator : function
108 Decorator which, when applied to a function, causes SkipTest
117 Decorator which, when applied to a function, causes SkipTest
109 to be raised when `skip_condition` is True, and the function
118 to be raised when `skip_condition` is True, and the function
110 to be called normally otherwise.
119 to be called normally otherwise.
111
120
112 Notes
121 Notes
113 -----
122 -----
114 The decorator itself is decorated with the ``nose.tools.make_decorator``
123 The decorator itself is decorated with the ``nose.tools.make_decorator``
115 function in order to transmit function name, and various other metadata.
124 function in order to transmit function name, and various other metadata.
116
125
117 """
126 """
118
127
119 def skip_decorator(f):
128 def skip_decorator(f):
120 # Local import to avoid a hard nose dependency and only incur the
129 # Local import to avoid a hard nose dependency and only incur the
121 # import time overhead at actual test-time.
130 # import time overhead at actual test-time.
122 import nose
131 import nose
123
132
124 # Allow for both boolean or callable skip conditions.
133 # Allow for both boolean or callable skip conditions.
125 if callable(skip_condition):
134 if callable(skip_condition):
126 skip_val = lambda : skip_condition()
135 skip_val = lambda : skip_condition()
127 else:
136 else:
128 skip_val = lambda : skip_condition
137 skip_val = lambda : skip_condition
129
138
130 def get_msg(func,msg=None):
139 def get_msg(func,msg=None):
131 """Skip message with information about function being skipped."""
140 """Skip message with information about function being skipped."""
132 if msg is None:
141 if msg is None:
133 out = 'Test skipped due to test condition'
142 out = 'Test skipped due to test condition'
134 else:
143 else:
135 out = '\n'+msg
144 out = '\n'+msg
136
145
137 return "Skipping test: %s%s" % (func.__name__,out)
146 return "Skipping test: %s%s" % (func.__name__,out)
138
147
139 # We need to define *two* skippers because Python doesn't allow both
148 # We need to define *two* skippers because Python doesn't allow both
140 # return with value and yield inside the same function.
149 # return with value and yield inside the same function.
141 def skipper_func(*args, **kwargs):
150 def skipper_func(*args, **kwargs):
142 """Skipper for normal test functions."""
151 """Skipper for normal test functions."""
143 if skip_val():
152 if skip_val():
144 raise nose.SkipTest(get_msg(f,msg))
153 raise nose.SkipTest(get_msg(f,msg))
145 else:
154 else:
146 return f(*args, **kwargs)
155 return f(*args, **kwargs)
147
156
148 def skipper_gen(*args, **kwargs):
157 def skipper_gen(*args, **kwargs):
149 """Skipper for test generators."""
158 """Skipper for test generators."""
150 if skip_val():
159 if skip_val():
151 raise nose.SkipTest(get_msg(f,msg))
160 raise nose.SkipTest(get_msg(f,msg))
152 else:
161 else:
153 for x in f(*args, **kwargs):
162 for x in f(*args, **kwargs):
154 yield x
163 yield x
155
164
156 # Choose the right skipper to use when building the actual decorator.
165 # Choose the right skipper to use when building the actual decorator.
157 if nose.util.isgenerator(f):
166 if nose.util.isgenerator(f):
158 skipper = skipper_gen
167 skipper = skipper_gen
159 else:
168 else:
160 skipper = skipper_func
169 skipper = skipper_func
161
170
162 return nose.tools.make_decorator(f)(skipper)
171 return nose.tools.make_decorator(f)(skipper)
163
172
164 return skip_decorator
173 return skip_decorator
165
174
166
175
167 def knownfailureif(fail_condition, msg=None):
176 def knownfailureif(fail_condition, msg=None):
168 """
177 """
169 Make function raise KnownFailureTest exception if given condition is true.
178 Make function raise KnownFailureTest exception if given condition is true.
170
179
171 If the condition is a callable, it is used at runtime to dynamically
180 If the condition is a callable, it is used at runtime to dynamically
172 make the decision. This is useful for tests that may require costly
181 make the decision. This is useful for tests that may require costly
173 imports, to delay the cost until the test suite is actually executed.
182 imports, to delay the cost until the test suite is actually executed.
174
183
175 Parameters
184 Parameters
176 ----------
185 ----------
177 fail_condition : bool or callable
186 fail_condition : bool or callable
178 Flag to determine whether to mark the decorated test as a known
187 Flag to determine whether to mark the decorated test as a known
179 failure (if True) or not (if False).
188 failure (if True) or not (if False).
180 msg : str, optional
189 msg : str, optional
181 Message to give on raising a KnownFailureTest exception.
190 Message to give on raising a KnownFailureTest exception.
182 Default is None.
191 Default is None.
183
192
184 Returns
193 Returns
185 -------
194 -------
186 decorator : function
195 decorator : function
187 Decorator, which, when applied to a function, causes SkipTest
196 Decorator, which, when applied to a function, causes SkipTest
188 to be raised when `skip_condition` is True, and the function
197 to be raised when `skip_condition` is True, and the function
189 to be called normally otherwise.
198 to be called normally otherwise.
190
199
191 Notes
200 Notes
192 -----
201 -----
193 The decorator itself is decorated with the ``nose.tools.make_decorator``
202 The decorator itself is decorated with the ``nose.tools.make_decorator``
194 function in order to transmit function name, and various other metadata.
203 function in order to transmit function name, and various other metadata.
195
204
196 """
205 """
197 if msg is None:
206 if msg is None:
198 msg = 'Test skipped due to known failure'
207 msg = 'Test skipped due to known failure'
199
208
200 # Allow for both boolean or callable known failure conditions.
209 # Allow for both boolean or callable known failure conditions.
201 if callable(fail_condition):
210 if callable(fail_condition):
202 fail_val = lambda : fail_condition()
211 fail_val = lambda : fail_condition()
203 else:
212 else:
204 fail_val = lambda : fail_condition
213 fail_val = lambda : fail_condition
205
214
206 def knownfail_decorator(f):
215 def knownfail_decorator(f):
207 # Local import to avoid a hard nose dependency and only incur the
216 # Local import to avoid a hard nose dependency and only incur the
208 # import time overhead at actual test-time.
217 # import time overhead at actual test-time.
209 import nose
218 import nose
210 from noseclasses import KnownFailureTest
219 from noseclasses import KnownFailureTest
211 def knownfailer(*args, **kwargs):
220 def knownfailer(*args, **kwargs):
212 if fail_val():
221 if fail_val():
213 raise KnownFailureTest, msg
222 raise KnownFailureTest, msg
214 else:
223 else:
215 return f(*args, **kwargs)
224 return f(*args, **kwargs)
216 return nose.tools.make_decorator(f)(knownfailer)
225 return nose.tools.make_decorator(f)(knownfailer)
217
226
218 return knownfail_decorator
227 return knownfail_decorator
219
228
220 def deprecated(conditional=True):
229 def deprecated(conditional=True):
221 """
230 """
222 Filter deprecation warnings while running the test suite.
231 Filter deprecation warnings while running the test suite.
223
232
224 This decorator can be used to filter DeprecationWarning's, to avoid
233 This decorator can be used to filter DeprecationWarning's, to avoid
225 printing them during the test suite run, while checking that the test
234 printing them during the test suite run, while checking that the test
226 actually raises a DeprecationWarning.
235 actually raises a DeprecationWarning.
227
236
228 Parameters
237 Parameters
229 ----------
238 ----------
230 conditional : bool or callable, optional
239 conditional : bool or callable, optional
231 Flag to determine whether to mark test as deprecated or not. If the
240 Flag to determine whether to mark test as deprecated or not. If the
232 condition is a callable, it is used at runtime to dynamically make the
241 condition is a callable, it is used at runtime to dynamically make the
233 decision. Default is True.
242 decision. Default is True.
234
243
235 Returns
244 Returns
236 -------
245 -------
237 decorator : function
246 decorator : function
238 The `deprecated` decorator itself.
247 The `deprecated` decorator itself.
239
248
240 Notes
249 Notes
241 -----
250 -----
242 .. versionadded:: 1.4.0
251 .. versionadded:: 1.4.0
243
252
244 """
253 """
245 def deprecate_decorator(f):
254 def deprecate_decorator(f):
246 # Local import to avoid a hard nose dependency and only incur the
255 # Local import to avoid a hard nose dependency and only incur the
247 # import time overhead at actual test-time.
256 # import time overhead at actual test-time.
248 import nose
257 import nose
249 from noseclasses import KnownFailureTest
258 from noseclasses import KnownFailureTest
250
259
251 def _deprecated_imp(*args, **kwargs):
260 def _deprecated_imp(*args, **kwargs):
252 # Poor man's replacement for the with statement
261 # Poor man's replacement for the with statement
253 ctx = WarningManager(record=True)
262 ctx = WarningManager(record=True)
254 l = ctx.__enter__()
263 l = ctx.__enter__()
255 warnings.simplefilter('always')
264 warnings.simplefilter('always')
256 try:
265 try:
257 f(*args, **kwargs)
266 f(*args, **kwargs)
258 if not len(l) > 0:
267 if not len(l) > 0:
259 raise AssertionError("No warning raised when calling %s"
268 raise AssertionError("No warning raised when calling %s"
260 % f.__name__)
269 % f.__name__)
261 if not l[0].category is DeprecationWarning:
270 if not l[0].category is DeprecationWarning:
262 raise AssertionError("First warning for %s is not a " \
271 raise AssertionError("First warning for %s is not a " \
263 "DeprecationWarning( is %s)" % (f.__name__, l[0]))
272 "DeprecationWarning( is %s)" % (f.__name__, l[0]))
264 finally:
273 finally:
265 ctx.__exit__()
274 ctx.__exit__()
266
275
267 if callable(conditional):
276 if callable(conditional):
268 cond = conditional()
277 cond = conditional()
269 else:
278 else:
270 cond = conditional
279 cond = conditional
271 if cond:
280 if cond:
272 return nose.tools.make_decorator(f)(_deprecated_imp)
281 return nose.tools.make_decorator(f)(_deprecated_imp)
273 else:
282 else:
274 return f
283 return f
275 return deprecate_decorator
284 return deprecate_decorator
General Comments 0
You need to be logged in to leave comments. Login now