You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					365 lines
				
				14 KiB
			
		
		
			
		
	
	
					365 lines
				
				14 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# These classes implement a doctest runner plugin for nose, a "known failure"
							 | 
						||
| 
								 | 
							
								# error class, and a customized TestProgram for NumPy.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Because this module imports nose directly, it should not
							 | 
						||
| 
								 | 
							
								# be used except by nosetester.py to avoid a general NumPy
							 | 
						||
| 
								 | 
							
								# dependency on nose.
							 | 
						||
| 
								 | 
							
								import os
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import doctest
							 | 
						||
| 
								 | 
							
								import inspect
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import numpy
							 | 
						||
| 
								 | 
							
								import nose
							 | 
						||
| 
								 | 
							
								from nose.plugins import doctests as npd
							 | 
						||
| 
								 | 
							
								from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
							 | 
						||
| 
								 | 
							
								from nose.plugins.base import Plugin
							 | 
						||
| 
								 | 
							
								from nose.util import src
							 | 
						||
| 
								 | 
							
								from .nosetester import get_package_name
							 | 
						||
| 
								 | 
							
								from .utils import KnownFailureException, KnownFailureTest
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Some of the classes in this module begin with 'Numpy' to clearly distinguish
							 | 
						||
| 
								 | 
							
								# them from the plethora of very similar names from nose/unittest/doctest
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#-----------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								# Modified version of the one in the stdlib, that fixes a python bug (doctests
							 | 
						||
| 
								 | 
							
								# not found in extension modules, https://bugs.python.org/issue3158)
							 | 
						||
| 
								 | 
							
								class NumpyDocTestFinder(doctest.DocTestFinder):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _from_module(self, module, object):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return true if the given object is defined in the given
							 | 
						||
| 
								 | 
							
								        module.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if module is None:
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								        elif inspect.isfunction(object):
							 | 
						||
| 
								 | 
							
								            return module.__dict__ is object.__globals__
							 | 
						||
| 
								 | 
							
								        elif inspect.isbuiltin(object):
							 | 
						||
| 
								 | 
							
								            return module.__name__ == object.__module__
							 | 
						||
| 
								 | 
							
								        elif inspect.isclass(object):
							 | 
						||
| 
								 | 
							
								            return module.__name__ == object.__module__
							 | 
						||
| 
								 | 
							
								        elif inspect.ismethod(object):
							 | 
						||
| 
								 | 
							
								            # This one may be a bug in cython that fails to correctly set the
							 | 
						||
| 
								 | 
							
								            # __module__ attribute of methods, but since the same error is easy
							 | 
						||
| 
								 | 
							
								            # to make by extension code writers, having this safety in place
							 | 
						||
| 
								 | 
							
								            # isn't such a bad idea
							 | 
						||
| 
								 | 
							
								            return module.__name__ == object.__self__.__class__.__module__
							 | 
						||
| 
								 | 
							
								        elif inspect.getmodule(object) is not None:
							 | 
						||
| 
								 | 
							
								            return module is inspect.getmodule(object)
							 | 
						||
| 
								 | 
							
								        elif hasattr(object, '__module__'):
							 | 
						||
| 
								 | 
							
								            return module.__name__ == object.__module__
							 | 
						||
| 
								 | 
							
								        elif isinstance(object, property):
							 | 
						||
| 
								 | 
							
								            return True  # [XX] no way not be sure.
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            raise ValueError("object must be a class or function")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _find(self, tests, obj, name, module, source_lines, globs, seen):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Find tests for the given object and any contained objects, and
							 | 
						||
| 
								 | 
							
								        add them to `tests`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        doctest.DocTestFinder._find(self, tests, obj, name, module,
							 | 
						||
| 
								 | 
							
								                                    source_lines, globs, seen)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Below we re-run pieces of the above method with manual modifications,
							 | 
						||
| 
								 | 
							
								        # because the original code is buggy and fails to correctly identify
							 | 
						||
| 
								 | 
							
								        # doctests in extension modules.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Local shorthands
							 | 
						||
| 
								 | 
							
								        from inspect import (
							 | 
						||
| 
								 | 
							
								            isroutine, isclass, ismodule, isfunction, ismethod
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Look for tests in a module's contained objects.
							 | 
						||
| 
								 | 
							
								        if ismodule(obj) and self._recurse:
							 | 
						||
| 
								 | 
							
								            for valname, val in obj.__dict__.items():
							 | 
						||
| 
								 | 
							
								                valname1 = f'{name}.{valname}'
							 | 
						||
| 
								 | 
							
								                if ( (isroutine(val) or isclass(val))
							 | 
						||
| 
								 | 
							
								                     and self._from_module(module, val)):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    self._find(tests, val, valname1, module, source_lines,
							 | 
						||
| 
								 | 
							
								                               globs, seen)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Look for tests in a class's contained objects.
							 | 
						||
| 
								 | 
							
								        if isclass(obj) and self._recurse:
							 | 
						||
| 
								 | 
							
								            for valname, val in obj.__dict__.items():
							 | 
						||
| 
								 | 
							
								                # Special handling for staticmethod/classmethod.
							 | 
						||
| 
								 | 
							
								                if isinstance(val, staticmethod):
							 | 
						||
| 
								 | 
							
								                    val = getattr(obj, valname)
							 | 
						||
| 
								 | 
							
								                if isinstance(val, classmethod):
							 | 
						||
| 
								 | 
							
								                    val = getattr(obj, valname).__func__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                # Recurse to methods, properties, and nested classes.
							 | 
						||
| 
								 | 
							
								                if ((isfunction(val) or isclass(val) or
							 | 
						||
| 
								 | 
							
								                     ismethod(val) or isinstance(val, property)) and
							 | 
						||
| 
								 | 
							
								                      self._from_module(module, val)):
							 | 
						||
| 
								 | 
							
								                    valname = f'{name}.{valname}'
							 | 
						||
| 
								 | 
							
								                    self._find(tests, val, valname, module, source_lines,
							 | 
						||
| 
								 | 
							
								                               globs, seen)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# second-chance checker; if the default comparison doesn't
							 | 
						||
| 
								 | 
							
								# pass, then see if the expected output string contains flags that
							 | 
						||
| 
								 | 
							
								# tell us to ignore the output
							 | 
						||
| 
								 | 
							
								class NumpyOutputChecker(doctest.OutputChecker):
							 | 
						||
| 
								 | 
							
								    def check_output(self, want, got, optionflags):
							 | 
						||
| 
								 | 
							
								        ret = doctest.OutputChecker.check_output(self, want, got,
							 | 
						||
| 
								 | 
							
								                                                 optionflags)
							 | 
						||
| 
								 | 
							
								        if not ret:
							 | 
						||
| 
								 | 
							
								            if "#random" in want:
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            # it would be useful to normalize endianness so that
							 | 
						||
| 
								 | 
							
								            # bigendian machines don't fail all the tests (and there are
							 | 
						||
| 
								 | 
							
								            # actually some bigendian examples in the doctests). Let's try
							 | 
						||
| 
								 | 
							
								            # making them all little endian
							 | 
						||
| 
								 | 
							
								            got = got.replace("'>", "'<")
							 | 
						||
| 
								 | 
							
								            want = want.replace("'>", "'<")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            # try to normalize out 32 and 64 bit default int sizes
							 | 
						||
| 
								 | 
							
								            for sz in [4, 8]:
							 | 
						||
| 
								 | 
							
								                got = got.replace("'<i%d'" % sz, "int")
							 | 
						||
| 
								 | 
							
								                want = want.replace("'<i%d'" % sz, "int")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            ret = doctest.OutputChecker.check_output(self, want,
							 | 
						||
| 
								 | 
							
								                    got, optionflags)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return ret
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Subclass nose.plugins.doctests.DocTestCase to work around a bug in
							 | 
						||
| 
								 | 
							
								# its constructor that blocks non-default arguments from being passed
							 | 
						||
| 
								 | 
							
								# down into doctest.DocTestCase
							 | 
						||
| 
								 | 
							
								class NumpyDocTestCase(npd.DocTestCase):
							 | 
						||
| 
								 | 
							
								    def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
							 | 
						||
| 
								 | 
							
								                 checker=None, obj=None, result_var='_'):
							 | 
						||
| 
								 | 
							
								        self._result_var = result_var
							 | 
						||
| 
								 | 
							
								        self._nose_obj = obj
							 | 
						||
| 
								 | 
							
								        doctest.DocTestCase.__init__(self, test,
							 | 
						||
| 
								 | 
							
								                                     optionflags=optionflags,
							 | 
						||
| 
								 | 
							
								                                     setUp=setUp, tearDown=tearDown,
							 | 
						||
| 
								 | 
							
								                                     checker=checker)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								print_state = numpy.get_printoptions()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class NumpyDoctest(npd.Doctest):
							 | 
						||
| 
								 | 
							
								    name = 'numpydoctest'   # call nosetests with --with-numpydoctest
							 | 
						||
| 
								 | 
							
								    score = 1000  # load late, after doctest builtin
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # always use whitespace and ellipsis options for doctests
							 | 
						||
| 
								 | 
							
								    doctest_optflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # files that should be ignored for doctests
							 | 
						||
| 
								 | 
							
								    doctest_ignore = ['generate_numpy_api.py',
							 | 
						||
| 
								 | 
							
								                      'setup.py']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Custom classes; class variables to allow subclassing
							 | 
						||
| 
								 | 
							
								    doctest_case_class = NumpyDocTestCase
							 | 
						||
| 
								 | 
							
								    out_check_class = NumpyOutputChecker
							 | 
						||
| 
								 | 
							
								    test_finder_class = NumpyDocTestFinder
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Don't use the standard doctest option handler; hard-code the option values
							 | 
						||
| 
								 | 
							
								    def options(self, parser, env=os.environ):
							 | 
						||
| 
								 | 
							
								        Plugin.options(self, parser, env)
							 | 
						||
| 
								 | 
							
								        # Test doctests in 'test' files / directories. Standard plugin default
							 | 
						||
| 
								 | 
							
								        # is False
							 | 
						||
| 
								 | 
							
								        self.doctest_tests = True
							 | 
						||
| 
								 | 
							
								        # Variable name; if defined, doctest results stored in this variable in
							 | 
						||
| 
								 | 
							
								        # the top-level namespace.  None is the standard default
							 | 
						||
| 
								 | 
							
								        self.doctest_result_var = None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def configure(self, options, config):
							 | 
						||
| 
								 | 
							
								        # parent method sets enabled flag from command line --with-numpydoctest
							 | 
						||
| 
								 | 
							
								        Plugin.configure(self, options, config)
							 | 
						||
| 
								 | 
							
								        self.finder = self.test_finder_class()
							 | 
						||
| 
								 | 
							
								        self.parser = doctest.DocTestParser()
							 | 
						||
| 
								 | 
							
								        if self.enabled:
							 | 
						||
| 
								 | 
							
								            # Pull standard doctest out of plugin list; there's no reason to run
							 | 
						||
| 
								 | 
							
								            # both.  In practice the Unplugger plugin above would cover us when
							 | 
						||
| 
								 | 
							
								            # run from a standard numpy.test() call; this is just in case
							 | 
						||
| 
								 | 
							
								            # someone wants to run our plugin outside the numpy.test() machinery
							 | 
						||
| 
								 | 
							
								            config.plugins.plugins = [p for p in config.plugins.plugins
							 | 
						||
| 
								 | 
							
								                                      if p.name != 'doctest']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def set_test_context(self, test):
							 | 
						||
| 
								 | 
							
								        """ Configure `test` object to set test context
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        We set the numpy / scipy standard doctest namespace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        test : test object
							 | 
						||
| 
								 | 
							
								            with ``globs`` dictionary defining namespace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns
							 | 
						||
| 
								 | 
							
								        -------
							 | 
						||
| 
								 | 
							
								        None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        `test` object modified in place
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        # set the namespace for tests
							 | 
						||
| 
								 | 
							
								        pkg_name = get_package_name(os.path.dirname(test.filename))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Each doctest should execute in an environment equivalent to
							 | 
						||
| 
								 | 
							
								        # starting Python and executing "import numpy as np", and,
							 | 
						||
| 
								 | 
							
								        # for SciPy packages, an additional import of the local
							 | 
						||
| 
								 | 
							
								        # package (so that scipy.linalg.basic.py's doctests have an
							 | 
						||
| 
								 | 
							
								        # implicit "from scipy import linalg" as well).
							 | 
						||
| 
								 | 
							
								        #
							 | 
						||
| 
								 | 
							
								        # Note: __file__ allows the doctest in NoseTester to run
							 | 
						||
| 
								 | 
							
								        # without producing an error
							 | 
						||
| 
								 | 
							
								        test.globs = {'__builtins__':__builtins__,
							 | 
						||
| 
								 | 
							
								                      '__file__':'__main__',
							 | 
						||
| 
								 | 
							
								                      '__name__':'__main__',
							 | 
						||
| 
								 | 
							
								                      'np':numpy}
							 | 
						||
| 
								 | 
							
								        # add appropriate scipy import for SciPy tests
							 | 
						||
| 
								 | 
							
								        if 'scipy' in pkg_name:
							 | 
						||
| 
								 | 
							
								            p = pkg_name.split('.')
							 | 
						||
| 
								 | 
							
								            p2 = p[-1]
							 | 
						||
| 
								 | 
							
								            test.globs[p2] = __import__(pkg_name, test.globs, {}, [p2])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Override test loading to customize test context (with set_test_context
							 | 
						||
| 
								 | 
							
								    # method), set standard docstring options, and install our own test output
							 | 
						||
| 
								 | 
							
								    # checker
							 | 
						||
| 
								 | 
							
								    def loadTestsFromModule(self, module):
							 | 
						||
| 
								 | 
							
								        if not self.matches(module.__name__):
							 | 
						||
| 
								 | 
							
								            npd.log.debug("Doctest doesn't want module %s", module)
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            tests = self.finder.find(module)
							 | 
						||
| 
								 | 
							
								        except AttributeError:
							 | 
						||
| 
								 | 
							
								            # nose allows module.__test__ = False; doctest does not and
							 | 
						||
| 
								 | 
							
								            # throws AttributeError
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        if not tests:
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        tests.sort()
							 | 
						||
| 
								 | 
							
								        module_file = src(module.__file__)
							 | 
						||
| 
								 | 
							
								        for test in tests:
							 | 
						||
| 
								 | 
							
								            if not test.examples:
							 | 
						||
| 
								 | 
							
								                continue
							 | 
						||
| 
								 | 
							
								            if not test.filename:
							 | 
						||
| 
								 | 
							
								                test.filename = module_file
							 | 
						||
| 
								 | 
							
								            # Set test namespace; test altered in place
							 | 
						||
| 
								 | 
							
								            self.set_test_context(test)
							 | 
						||
| 
								 | 
							
								            yield self.doctest_case_class(test,
							 | 
						||
| 
								 | 
							
								                                          optionflags=self.doctest_optflags,
							 | 
						||
| 
								 | 
							
								                                          checker=self.out_check_class(),
							 | 
						||
| 
								 | 
							
								                                          result_var=self.doctest_result_var)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Add an afterContext method to nose.plugins.doctests.Doctest in order
							 | 
						||
| 
								 | 
							
								    # to restore print options to the original state after each doctest
							 | 
						||
| 
								 | 
							
								    def afterContext(self):
							 | 
						||
| 
								 | 
							
								        numpy.set_printoptions(**print_state)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Ignore NumPy-specific build files that shouldn't be searched for tests
							 | 
						||
| 
								 | 
							
								    def wantFile(self, file):
							 | 
						||
| 
								 | 
							
								        bn = os.path.basename(file)
							 | 
						||
| 
								 | 
							
								        if bn in self.doctest_ignore:
							 | 
						||
| 
								 | 
							
								            return False
							 | 
						||
| 
								 | 
							
								        return npd.Doctest.wantFile(self, file)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Unplugger:
							 | 
						||
| 
								 | 
							
								    """ Nose plugin to remove named plugin late in loading
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    By default it removes the "doctest" plugin.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    name = 'unplugger'
							 | 
						||
| 
								 | 
							
								    enabled = True  # always enabled
							 | 
						||
| 
								 | 
							
								    score = 4000  # load late in order to be after builtins
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, to_unplug='doctest'):
							 | 
						||
| 
								 | 
							
								        self.to_unplug = to_unplug
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def options(self, parser, env):
							 | 
						||
| 
								 | 
							
								        pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def configure(self, options, config):
							 | 
						||
| 
								 | 
							
								        # Pull named plugin out of plugins list
							 | 
						||
| 
								 | 
							
								        config.plugins.plugins = [p for p in config.plugins.plugins
							 | 
						||
| 
								 | 
							
								                                  if p.name != self.to_unplug]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class KnownFailurePlugin(ErrorClassPlugin):
							 | 
						||
| 
								 | 
							
								    '''Plugin that installs a KNOWNFAIL error class for the
							 | 
						||
| 
								 | 
							
								    KnownFailureClass exception.  When KnownFailure is raised,
							 | 
						||
| 
								 | 
							
								    the exception will be logged in the knownfail attribute of the
							 | 
						||
| 
								 | 
							
								    result, 'K' or 'KNOWNFAIL' (verbose) will be output, and the
							 | 
						||
| 
								 | 
							
								    exception will not be counted as an error or failure.'''
							 | 
						||
| 
								 | 
							
								    enabled = True
							 | 
						||
| 
								 | 
							
								    knownfail = ErrorClass(KnownFailureException,
							 | 
						||
| 
								 | 
							
								                           label='KNOWNFAIL',
							 | 
						||
| 
								 | 
							
								                           isfailure=False)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def options(self, parser, env=os.environ):
							 | 
						||
| 
								 | 
							
								        env_opt = 'NOSE_WITHOUT_KNOWNFAIL'
							 | 
						||
| 
								 | 
							
								        parser.add_option('--no-knownfail', action='store_true',
							 | 
						||
| 
								 | 
							
								                          dest='noKnownFail', default=env.get(env_opt, False),
							 | 
						||
| 
								 | 
							
								                          help='Disable special handling of KnownFailure '
							 | 
						||
| 
								 | 
							
								                               'exceptions')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def configure(self, options, conf):
							 | 
						||
| 
								 | 
							
								        if not self.can_configure:
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        self.conf = conf
							 | 
						||
| 
								 | 
							
								        disable = getattr(options, 'noKnownFail', False)
							 | 
						||
| 
								 | 
							
								        if disable:
							 | 
						||
| 
								 | 
							
								            self.enabled = False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								KnownFailure = KnownFailurePlugin   # backwards compat
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class FPUModeCheckPlugin(Plugin):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Plugin that checks the FPU mode before and after each test,
							 | 
						||
| 
								 | 
							
								    raising failures if the test changed the mode.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def prepareTestCase(self, test):
							 | 
						||
| 
								 | 
							
								        from numpy.core._multiarray_tests import get_fpu_mode
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        def run(result):
							 | 
						||
| 
								 | 
							
								            old_mode = get_fpu_mode()
							 | 
						||
| 
								 | 
							
								            test.test(result)
							 | 
						||
| 
								 | 
							
								            new_mode = get_fpu_mode()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if old_mode != new_mode:
							 | 
						||
| 
								 | 
							
								                try:
							 | 
						||
| 
								 | 
							
								                    raise AssertionError(
							 | 
						||
| 
								 | 
							
								                        "FPU mode changed from {0:#x} to {1:#x} during the "
							 | 
						||
| 
								 | 
							
								                        "test".format(old_mode, new_mode))
							 | 
						||
| 
								 | 
							
								                except AssertionError:
							 | 
						||
| 
								 | 
							
								                    result.addFailure(test, sys.exc_info())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return run
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Class allows us to save the results of the tests in runTests - see runTests
							 | 
						||
| 
								 | 
							
								# method docstring for details
							 | 
						||
| 
								 | 
							
								class NumpyTestProgram(nose.core.TestProgram):
							 | 
						||
| 
								 | 
							
								    def runTests(self):
							 | 
						||
| 
								 | 
							
								        """Run Tests. Returns true on success, false on failure, and
							 | 
						||
| 
								 | 
							
								        sets self.success to the same value.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Because nose currently discards the test result object, but we need
							 | 
						||
| 
								 | 
							
								        to return it to the user, override TestProgram.runTests to retain
							 | 
						||
| 
								 | 
							
								        the result
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if self.testRunner is None:
							 | 
						||
| 
								 | 
							
								            self.testRunner = nose.core.TextTestRunner(stream=self.config.stream,
							 | 
						||
| 
								 | 
							
								                                                       verbosity=self.config.verbosity,
							 | 
						||
| 
								 | 
							
								                                                       config=self.config)
							 | 
						||
| 
								 | 
							
								        plug_runner = self.config.plugins.prepareTestRunner(self.testRunner)
							 | 
						||
| 
								 | 
							
								        if plug_runner is not None:
							 | 
						||
| 
								 | 
							
								            self.testRunner = plug_runner
							 | 
						||
| 
								 | 
							
								        self.result = self.testRunner.run(self.test)
							 | 
						||
| 
								 | 
							
								        self.success = self.result.wasSuccessful()
							 | 
						||
| 
								 | 
							
								        return self.success
							 |