Created starter files for the project.
This commit is contained in:
commit
73f0c0db42
1992 changed files with 769897 additions and 0 deletions
364
venv/Lib/site-packages/numpy/testing/_private/noseclasses.py
Normal file
364
venv/Lib/site-packages/numpy/testing/_private/noseclasses.py
Normal file
|
@ -0,0 +1,364 @@
|
|||
# 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 = '%s.%s' % (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 = '%s.%s' % (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
|
Loading…
Add table
Add a link
Reference in a new issue