_numpy_testing_utils.py
120 lines
| 4.1 KiB
| text/x-python
|
PythonLexer
Fernando Perez
|
r2406 | # IPython: modified copy of numpy.testing.utils, so numpy.testing.decorators | ||
# works without numpy being installed. | ||||
""" | ||||
Utility function to facilitate testing. | ||||
""" | ||||
import os | ||||
import sys | ||||
import re | ||||
import operator | ||||
import types | ||||
import warnings | ||||
# 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. | ||||
Notes | ||||
----- | ||||
`WarningMessage` is copied from the Python 2.6 warnings module, | ||||
so it can be used in NumPy with older Python versions. | ||||
""" | ||||
_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]) | ||||
if category: | ||||
self._category_name = category.__name__ | ||||
else: | ||||
self._category_name = 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: | ||||
""" | ||||
A context manager that copies and restores the warnings filter upon | ||||
exiting the context. | ||||
The 'record' argument specifies whether warnings should be captured by a | ||||
custom implementation of ``warnings.showwarning()`` and be appended to a | ||||
list returned by the context manager. Otherwise None is returned by the | ||||
context manager. The objects appended to the list are arguments whose | ||||
attributes mirror the arguments to ``showwarning()``. | ||||
The 'module' argument is to specify an alternative module to the module | ||||
named 'warnings' and imported under that name. This argument is only useful | ||||
when testing the warnings module itself. | ||||
Notes | ||||
----- | ||||
`WarningManager` is a copy of the ``catch_warnings`` context manager | ||||
from the Python 2.6 warnings module, with slight modifications. | ||||
It is copied so it can be used in NumPy with older Python versions. | ||||
""" | ||||
def __init__(self, record=False, module=None): | ||||
self._record = record | ||||
if module is None: | ||||
self._module = sys.modules['warnings'] | ||||
else: | ||||
self._module = 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 assert_warns(warning_class, func, *args, **kw): | ||||
"""Fail unless a warning of class warning_class is thrown by callable when | ||||
invoked with arguments args and keyword arguments kwargs. | ||||
If a different type of warning is thrown, it will not be caught, and the | ||||
test case will be deemed to have suffered an error. | ||||
""" | ||||
# XXX: once we may depend on python >= 2.6, this can be replaced by the | ||||
# warnings module context manager. | ||||
ctx = WarningManager(record=True) | ||||
l = ctx.__enter__() | ||||
warnings.simplefilter('always') | ||||
try: | ||||
func(*args, **kw) | ||||
if not len(l) > 0: | ||||
raise AssertionError("No warning raised when calling %s" | ||||
% func.__name__) | ||||
if not l[0].category is warning_class: | ||||
raise AssertionError("First warning for %s is not a " \ | ||||
"%s( is %s)" % (func.__name__, warning_class, l[0])) | ||||
finally: | ||||
ctx.__exit__() | ||||