Created starter files for the project.
This commit is contained in:
commit
73f0c0db42
1992 changed files with 769897 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
284
venv/Lib/site-packages/numpy/testing/_private/decorators.py
Normal file
284
venv/Lib/site-packages/numpy/testing/_private/decorators.py
Normal file
|
@ -0,0 +1,284 @@
|
|||
"""
|
||||
Decorators for labeling and modifying behavior of test objects.
|
||||
|
||||
Decorators that merely return a modified version of the original
|
||||
function object are straightforward. Decorators that return a new
|
||||
function object need to use
|
||||
::
|
||||
|
||||
nose.tools.make_decorator(original_function)(decorator)
|
||||
|
||||
in returning the decorator, in order to preserve meta-data such as
|
||||
function name, setup and teardown functions and so on - see
|
||||
``nose.tools`` for more information.
|
||||
|
||||
"""
|
||||
import collections.abc
|
||||
|
||||
from .utils import SkipTest, assert_warns, HAS_REFCOUNT
|
||||
|
||||
__all__ = ['slow', 'setastest', 'skipif', 'knownfailureif', 'deprecated',
|
||||
'parametrize', '_needs_refcount',]
|
||||
|
||||
|
||||
def slow(t):
|
||||
"""
|
||||
Label a test as 'slow'.
|
||||
|
||||
The exact definition of a slow test is obviously both subjective and
|
||||
hardware-dependent, but in general any individual test that requires more
|
||||
than a second or two should be labeled as slow (the whole suite consists of
|
||||
thousands of tests, so even a second is significant).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
t : callable
|
||||
The test to label as slow.
|
||||
|
||||
Returns
|
||||
-------
|
||||
t : callable
|
||||
The decorated test `t`.
|
||||
|
||||
Examples
|
||||
--------
|
||||
The `numpy.testing` module includes ``import decorators as dec``.
|
||||
A test can be decorated as slow like this::
|
||||
|
||||
from numpy.testing import *
|
||||
|
||||
@dec.slow
|
||||
def test_big(self):
|
||||
print('Big, slow test')
|
||||
|
||||
"""
|
||||
|
||||
t.slow = True
|
||||
return t
|
||||
|
||||
def setastest(tf=True):
|
||||
"""
|
||||
Signals to nose that this function is or is not a test.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tf : bool
|
||||
If True, specifies that the decorated callable is a test.
|
||||
If False, specifies that the decorated callable is not a test.
|
||||
Default is True.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This decorator can't use the nose namespace, because it can be
|
||||
called from a non-test module. See also ``istest`` and ``nottest`` in
|
||||
``nose.tools``.
|
||||
|
||||
Examples
|
||||
--------
|
||||
`setastest` can be used in the following way::
|
||||
|
||||
from numpy.testing import dec
|
||||
|
||||
@dec.setastest(False)
|
||||
def func_with_test_in_name(arg1, arg2):
|
||||
pass
|
||||
|
||||
"""
|
||||
def set_test(t):
|
||||
t.__test__ = tf
|
||||
return t
|
||||
return set_test
|
||||
|
||||
def skipif(skip_condition, msg=None):
|
||||
"""
|
||||
Make function raise SkipTest exception if a given condition is true.
|
||||
|
||||
If the condition is a callable, it is used at runtime to dynamically
|
||||
make the decision. This is useful for tests that may require costly
|
||||
imports, to delay the cost until the test suite is actually executed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
skip_condition : bool or callable
|
||||
Flag to determine whether to skip the decorated test.
|
||||
msg : str, optional
|
||||
Message to give on raising a SkipTest exception. Default is None.
|
||||
|
||||
Returns
|
||||
-------
|
||||
decorator : function
|
||||
Decorator which, when applied to a function, causes SkipTest
|
||||
to be raised when `skip_condition` is True, and the function
|
||||
to be called normally otherwise.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The decorator itself is decorated with the ``nose.tools.make_decorator``
|
||||
function in order to transmit function name, and various other metadata.
|
||||
|
||||
"""
|
||||
|
||||
def skip_decorator(f):
|
||||
# Local import to avoid a hard nose dependency and only incur the
|
||||
# import time overhead at actual test-time.
|
||||
import nose
|
||||
|
||||
# Allow for both boolean or callable skip conditions.
|
||||
if isinstance(skip_condition, collections.abc.Callable):
|
||||
skip_val = lambda: skip_condition()
|
||||
else:
|
||||
skip_val = lambda: skip_condition
|
||||
|
||||
def get_msg(func,msg=None):
|
||||
"""Skip message with information about function being skipped."""
|
||||
if msg is None:
|
||||
out = 'Test skipped due to test condition'
|
||||
else:
|
||||
out = msg
|
||||
|
||||
return "Skipping test: %s: %s" % (func.__name__, out)
|
||||
|
||||
# We need to define *two* skippers because Python doesn't allow both
|
||||
# return with value and yield inside the same function.
|
||||
def skipper_func(*args, **kwargs):
|
||||
"""Skipper for normal test functions."""
|
||||
if skip_val():
|
||||
raise SkipTest(get_msg(f, msg))
|
||||
else:
|
||||
return f(*args, **kwargs)
|
||||
|
||||
def skipper_gen(*args, **kwargs):
|
||||
"""Skipper for test generators."""
|
||||
if skip_val():
|
||||
raise SkipTest(get_msg(f, msg))
|
||||
else:
|
||||
yield from f(*args, **kwargs)
|
||||
|
||||
# Choose the right skipper to use when building the actual decorator.
|
||||
if nose.util.isgenerator(f):
|
||||
skipper = skipper_gen
|
||||
else:
|
||||
skipper = skipper_func
|
||||
|
||||
return nose.tools.make_decorator(f)(skipper)
|
||||
|
||||
return skip_decorator
|
||||
|
||||
|
||||
def knownfailureif(fail_condition, msg=None):
|
||||
"""
|
||||
Make function raise KnownFailureException exception if given condition is true.
|
||||
|
||||
If the condition is a callable, it is used at runtime to dynamically
|
||||
make the decision. This is useful for tests that may require costly
|
||||
imports, to delay the cost until the test suite is actually executed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fail_condition : bool or callable
|
||||
Flag to determine whether to mark the decorated test as a known
|
||||
failure (if True) or not (if False).
|
||||
msg : str, optional
|
||||
Message to give on raising a KnownFailureException exception.
|
||||
Default is None.
|
||||
|
||||
Returns
|
||||
-------
|
||||
decorator : function
|
||||
Decorator, which, when applied to a function, causes
|
||||
KnownFailureException to be raised when `fail_condition` is True,
|
||||
and the function to be called normally otherwise.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The decorator itself is decorated with the ``nose.tools.make_decorator``
|
||||
function in order to transmit function name, and various other metadata.
|
||||
|
||||
"""
|
||||
if msg is None:
|
||||
msg = 'Test skipped due to known failure'
|
||||
|
||||
# Allow for both boolean or callable known failure conditions.
|
||||
if isinstance(fail_condition, collections.abc.Callable):
|
||||
fail_val = lambda: fail_condition()
|
||||
else:
|
||||
fail_val = lambda: fail_condition
|
||||
|
||||
def knownfail_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 KnownFailureException
|
||||
|
||||
def knownfailer(*args, **kwargs):
|
||||
if fail_val():
|
||||
raise KnownFailureException(msg)
|
||||
else:
|
||||
return f(*args, **kwargs)
|
||||
return nose.tools.make_decorator(f)(knownfailer)
|
||||
|
||||
return knownfail_decorator
|
||||
|
||||
def deprecated(conditional=True):
|
||||
"""
|
||||
Filter deprecation warnings while running the test suite.
|
||||
|
||||
This decorator can be used to filter DeprecationWarning's, to avoid
|
||||
printing them during the test suite run, while checking that the test
|
||||
actually raises a DeprecationWarning.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
conditional : bool or callable, optional
|
||||
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. Default is True.
|
||||
|
||||
Returns
|
||||
-------
|
||||
decorator : function
|
||||
The `deprecated` decorator itself.
|
||||
|
||||
Notes
|
||||
-----
|
||||
.. versionadded:: 1.4.0
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
def _deprecated_imp(*args, **kwargs):
|
||||
# Poor man's replacement for the with statement
|
||||
with assert_warns(DeprecationWarning):
|
||||
f(*args, **kwargs)
|
||||
|
||||
if isinstance(conditional, collections.abc.Callable):
|
||||
cond = conditional()
|
||||
else:
|
||||
cond = conditional
|
||||
if cond:
|
||||
return nose.tools.make_decorator(f)(_deprecated_imp)
|
||||
else:
|
||||
return f
|
||||
return deprecate_decorator
|
||||
|
||||
|
||||
def parametrize(vars, input):
|
||||
"""
|
||||
Pytest compatibility class. This implements the simplest level of
|
||||
pytest.mark.parametrize for use in nose as an aid in making the transition
|
||||
to pytest. It achieves that by adding a dummy var parameter and ignoring
|
||||
the doc_func parameter of the base class. It does not support variable
|
||||
substitution by name, nor does it support nesting or classes. See the
|
||||
pytest documentation for usage.
|
||||
|
||||
.. versionadded:: 1.14.0
|
||||
|
||||
"""
|
||||
from .parameterized import parameterized
|
||||
|
||||
return parameterized(input)
|
||||
|
||||
_needs_refcount = skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
|
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
|
545
venv/Lib/site-packages/numpy/testing/_private/nosetester.py
Normal file
545
venv/Lib/site-packages/numpy/testing/_private/nosetester.py
Normal file
|
@ -0,0 +1,545 @@
|
|||
"""
|
||||
Nose test running.
|
||||
|
||||
This module implements ``test()`` and ``bench()`` functions for NumPy modules.
|
||||
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
import numpy as np
|
||||
|
||||
from .utils import import_nose, suppress_warnings
|
||||
|
||||
|
||||
__all__ = ['get_package_name', 'run_module_suite', 'NoseTester',
|
||||
'_numpy_tester', 'get_package_name', 'import_nose',
|
||||
'suppress_warnings']
|
||||
|
||||
|
||||
def get_package_name(filepath):
|
||||
"""
|
||||
Given a path where a package is installed, determine its name.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filepath : str
|
||||
Path to a file. If the determination fails, "numpy" is returned.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> np.testing.nosetester.get_package_name('nonsense')
|
||||
'numpy'
|
||||
|
||||
"""
|
||||
|
||||
fullpath = filepath[:]
|
||||
pkg_name = []
|
||||
while 'site-packages' in filepath or 'dist-packages' in filepath:
|
||||
filepath, p2 = os.path.split(filepath)
|
||||
if p2 in ('site-packages', 'dist-packages'):
|
||||
break
|
||||
pkg_name.append(p2)
|
||||
|
||||
# if package name determination failed, just default to numpy/scipy
|
||||
if not pkg_name:
|
||||
if 'scipy' in fullpath:
|
||||
return 'scipy'
|
||||
else:
|
||||
return 'numpy'
|
||||
|
||||
# otherwise, reverse to get correct order and return
|
||||
pkg_name.reverse()
|
||||
|
||||
# don't include the outer egg directory
|
||||
if pkg_name[0].endswith('.egg'):
|
||||
pkg_name.pop(0)
|
||||
|
||||
return '.'.join(pkg_name)
|
||||
|
||||
|
||||
def run_module_suite(file_to_run=None, argv=None):
|
||||
"""
|
||||
Run a test module.
|
||||
|
||||
Equivalent to calling ``$ nosetests <argv> <file_to_run>`` from
|
||||
the command line
|
||||
|
||||
Parameters
|
||||
----------
|
||||
file_to_run : str, optional
|
||||
Path to test module, or None.
|
||||
By default, run the module from which this function is called.
|
||||
argv : list of strings
|
||||
Arguments to be passed to the nose test runner. ``argv[0]`` is
|
||||
ignored. All command line arguments accepted by ``nosetests``
|
||||
will work. If it is the default value None, sys.argv is used.
|
||||
|
||||
.. versionadded:: 1.9.0
|
||||
|
||||
Examples
|
||||
--------
|
||||
Adding the following::
|
||||
|
||||
if __name__ == "__main__" :
|
||||
run_module_suite(argv=sys.argv)
|
||||
|
||||
at the end of a test module will run the tests when that module is
|
||||
called in the python interpreter.
|
||||
|
||||
Alternatively, calling::
|
||||
|
||||
>>> run_module_suite(file_to_run="numpy/tests/test_matlib.py") # doctest: +SKIP
|
||||
|
||||
from an interpreter will run all the test routine in 'test_matlib.py'.
|
||||
"""
|
||||
if file_to_run is None:
|
||||
f = sys._getframe(1)
|
||||
file_to_run = f.f_locals.get('__file__', None)
|
||||
if file_to_run is None:
|
||||
raise AssertionError
|
||||
|
||||
if argv is None:
|
||||
argv = sys.argv + [file_to_run]
|
||||
else:
|
||||
argv = argv + [file_to_run]
|
||||
|
||||
nose = import_nose()
|
||||
from .noseclasses import KnownFailurePlugin
|
||||
nose.run(argv=argv, addplugins=[KnownFailurePlugin()])
|
||||
|
||||
|
||||
class NoseTester:
|
||||
"""
|
||||
Nose test runner.
|
||||
|
||||
This class is made available as numpy.testing.Tester, and a test function
|
||||
is typically added to a package's __init__.py like so::
|
||||
|
||||
from numpy.testing import Tester
|
||||
test = Tester().test
|
||||
|
||||
Calling this test function finds and runs all tests associated with the
|
||||
package and all its sub-packages.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
package_path : str
|
||||
Full path to the package to test.
|
||||
package_name : str
|
||||
Name of the package to test.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
package : module, str or None, optional
|
||||
The package to test. If a string, this should be the full path to
|
||||
the package. If None (default), `package` is set to the module from
|
||||
which `NoseTester` is initialized.
|
||||
raise_warnings : None, str or sequence of warnings, optional
|
||||
This specifies which warnings to configure as 'raise' instead
|
||||
of being shown once during the test execution. Valid strings are:
|
||||
|
||||
- "develop" : equals ``(Warning,)``
|
||||
- "release" : equals ``()``, don't raise on any warnings.
|
||||
|
||||
Default is "release".
|
||||
depth : int, optional
|
||||
If `package` is None, then this can be used to initialize from the
|
||||
module of the caller of (the caller of (...)) the code that
|
||||
initializes `NoseTester`. Default of 0 means the module of the
|
||||
immediate caller; higher values are useful for utility routines that
|
||||
want to initialize `NoseTester` objects on behalf of other code.
|
||||
|
||||
"""
|
||||
def __init__(self, package=None, raise_warnings="release", depth=0,
|
||||
check_fpu_mode=False):
|
||||
# Back-compat: 'None' used to mean either "release" or "develop"
|
||||
# depending on whether this was a release or develop version of
|
||||
# numpy. Those semantics were fine for testing numpy, but not so
|
||||
# helpful for downstream projects like scipy that use
|
||||
# numpy.testing. (They want to set this based on whether *they* are a
|
||||
# release or develop version, not whether numpy is.) So we continue to
|
||||
# accept 'None' for back-compat, but it's now just an alias for the
|
||||
# default "release".
|
||||
if raise_warnings is None:
|
||||
raise_warnings = "release"
|
||||
|
||||
package_name = None
|
||||
if package is None:
|
||||
f = sys._getframe(1 + depth)
|
||||
package_path = f.f_locals.get('__file__', None)
|
||||
if package_path is None:
|
||||
raise AssertionError
|
||||
package_path = os.path.dirname(package_path)
|
||||
package_name = f.f_locals.get('__name__', None)
|
||||
elif isinstance(package, type(os)):
|
||||
package_path = os.path.dirname(package.__file__)
|
||||
package_name = getattr(package, '__name__', None)
|
||||
else:
|
||||
package_path = str(package)
|
||||
|
||||
self.package_path = package_path
|
||||
|
||||
# Find the package name under test; this name is used to limit coverage
|
||||
# reporting (if enabled).
|
||||
if package_name is None:
|
||||
package_name = get_package_name(package_path)
|
||||
self.package_name = package_name
|
||||
|
||||
# Set to "release" in constructor in maintenance branches.
|
||||
self.raise_warnings = raise_warnings
|
||||
|
||||
# Whether to check for FPU mode changes
|
||||
self.check_fpu_mode = check_fpu_mode
|
||||
|
||||
def _test_argv(self, label, verbose, extra_argv):
|
||||
''' Generate argv for nosetest command
|
||||
|
||||
Parameters
|
||||
----------
|
||||
label : {'fast', 'full', '', attribute identifier}, optional
|
||||
see ``test`` docstring
|
||||
verbose : int, optional
|
||||
Verbosity value for test outputs, in the range 1-10. Default is 1.
|
||||
extra_argv : list, optional
|
||||
List with any extra arguments to pass to nosetests.
|
||||
|
||||
Returns
|
||||
-------
|
||||
argv : list
|
||||
command line arguments that will be passed to nose
|
||||
'''
|
||||
argv = [__file__, self.package_path, '-s']
|
||||
if label and label != 'full':
|
||||
if not isinstance(label, str):
|
||||
raise TypeError('Selection label should be a string')
|
||||
if label == 'fast':
|
||||
label = 'not slow'
|
||||
argv += ['-A', label]
|
||||
argv += ['--verbosity', str(verbose)]
|
||||
|
||||
# When installing with setuptools, and also in some other cases, the
|
||||
# test_*.py files end up marked +x executable. Nose, by default, does
|
||||
# not run files marked with +x as they might be scripts. However, in
|
||||
# our case nose only looks for test_*.py files under the package
|
||||
# directory, which should be safe.
|
||||
argv += ['--exe']
|
||||
|
||||
if extra_argv:
|
||||
argv += extra_argv
|
||||
return argv
|
||||
|
||||
def _show_system_info(self):
|
||||
nose = import_nose()
|
||||
|
||||
import numpy
|
||||
print("NumPy version %s" % numpy.__version__)
|
||||
relaxed_strides = numpy.ones((10, 1), order="C").flags.f_contiguous
|
||||
print("NumPy relaxed strides checking option:", relaxed_strides)
|
||||
npdir = os.path.dirname(numpy.__file__)
|
||||
print("NumPy is installed in %s" % npdir)
|
||||
|
||||
if 'scipy' in self.package_name:
|
||||
import scipy
|
||||
print("SciPy version %s" % scipy.__version__)
|
||||
spdir = os.path.dirname(scipy.__file__)
|
||||
print("SciPy is installed in %s" % spdir)
|
||||
|
||||
pyversion = sys.version.replace('\n', '')
|
||||
print("Python version %s" % pyversion)
|
||||
print("nose version %d.%d.%d" % nose.__versioninfo__)
|
||||
|
||||
def _get_custom_doctester(self):
|
||||
""" Return instantiated plugin for doctests
|
||||
|
||||
Allows subclassing of this class to override doctester
|
||||
|
||||
A return value of None means use the nose builtin doctest plugin
|
||||
"""
|
||||
from .noseclasses import NumpyDoctest
|
||||
return NumpyDoctest()
|
||||
|
||||
def prepare_test_args(self, label='fast', verbose=1, extra_argv=None,
|
||||
doctests=False, coverage=False, timer=False):
|
||||
"""
|
||||
Run tests for module using nose.
|
||||
|
||||
This method does the heavy lifting for the `test` method. It takes all
|
||||
the same arguments, for details see `test`.
|
||||
|
||||
See Also
|
||||
--------
|
||||
test
|
||||
|
||||
"""
|
||||
# fail with nice error message if nose is not present
|
||||
import_nose()
|
||||
# compile argv
|
||||
argv = self._test_argv(label, verbose, extra_argv)
|
||||
# our way of doing coverage
|
||||
if coverage:
|
||||
argv += ['--cover-package=%s' % self.package_name, '--with-coverage',
|
||||
'--cover-tests', '--cover-erase']
|
||||
|
||||
if timer:
|
||||
if timer is True:
|
||||
argv += ['--with-timer']
|
||||
elif isinstance(timer, int):
|
||||
argv += ['--with-timer', '--timer-top-n', str(timer)]
|
||||
|
||||
# construct list of plugins
|
||||
import nose.plugins.builtin
|
||||
from nose.plugins import EntryPointPluginManager
|
||||
from .noseclasses import (KnownFailurePlugin, Unplugger,
|
||||
FPUModeCheckPlugin)
|
||||
plugins = [KnownFailurePlugin()]
|
||||
plugins += [p() for p in nose.plugins.builtin.plugins]
|
||||
if self.check_fpu_mode:
|
||||
plugins += [FPUModeCheckPlugin()]
|
||||
argv += ["--with-fpumodecheckplugin"]
|
||||
try:
|
||||
# External plugins (like nose-timer)
|
||||
entrypoint_manager = EntryPointPluginManager()
|
||||
entrypoint_manager.loadPlugins()
|
||||
plugins += [p for p in entrypoint_manager.plugins]
|
||||
except ImportError:
|
||||
# Relies on pkg_resources, not a hard dependency
|
||||
pass
|
||||
|
||||
# add doctesting if required
|
||||
doctest_argv = '--with-doctest' in argv
|
||||
if doctests == False and doctest_argv:
|
||||
doctests = True
|
||||
plug = self._get_custom_doctester()
|
||||
if plug is None:
|
||||
# use standard doctesting
|
||||
if doctests and not doctest_argv:
|
||||
argv += ['--with-doctest']
|
||||
else: # custom doctesting
|
||||
if doctest_argv: # in fact the unplugger would take care of this
|
||||
argv.remove('--with-doctest')
|
||||
plugins += [Unplugger('doctest'), plug]
|
||||
if doctests:
|
||||
argv += ['--with-' + plug.name]
|
||||
return argv, plugins
|
||||
|
||||
def test(self, label='fast', verbose=1, extra_argv=None,
|
||||
doctests=False, coverage=False, raise_warnings=None,
|
||||
timer=False):
|
||||
"""
|
||||
Run tests for module using nose.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
label : {'fast', 'full', '', attribute identifier}, optional
|
||||
Identifies the tests to run. This can be a string to pass to
|
||||
the nosetests executable with the '-A' option, or one of several
|
||||
special values. Special values are:
|
||||
|
||||
* 'fast' - the default - which corresponds to the ``nosetests -A``
|
||||
option of 'not slow'.
|
||||
* 'full' - fast (as above) and slow tests as in the
|
||||
'no -A' option to nosetests - this is the same as ''.
|
||||
* None or '' - run all tests.
|
||||
* attribute_identifier - string passed directly to nosetests as '-A'.
|
||||
|
||||
verbose : int, optional
|
||||
Verbosity value for test outputs, in the range 1-10. Default is 1.
|
||||
extra_argv : list, optional
|
||||
List with any extra arguments to pass to nosetests.
|
||||
doctests : bool, optional
|
||||
If True, run doctests in module. Default is False.
|
||||
coverage : bool, optional
|
||||
If True, report coverage of NumPy code. Default is False.
|
||||
(This requires the
|
||||
`coverage module <https://nedbatchelder.com/code/modules/coveragehtml>`_).
|
||||
raise_warnings : None, str or sequence of warnings, optional
|
||||
This specifies which warnings to configure as 'raise' instead
|
||||
of being shown once during the test execution. Valid strings are:
|
||||
|
||||
* "develop" : equals ``(Warning,)``
|
||||
* "release" : equals ``()``, do not raise on any warnings.
|
||||
timer : bool or int, optional
|
||||
Timing of individual tests with ``nose-timer`` (which needs to be
|
||||
installed). If True, time tests and report on all of them.
|
||||
If an integer (say ``N``), report timing results for ``N`` slowest
|
||||
tests.
|
||||
|
||||
Returns
|
||||
-------
|
||||
result : object
|
||||
Returns the result of running the tests as a
|
||||
``nose.result.TextTestResult`` object.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Each NumPy module exposes `test` in its namespace to run all tests for it.
|
||||
For example, to run all tests for numpy.lib:
|
||||
|
||||
>>> np.lib.test() #doctest: +SKIP
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> result = np.lib.test() #doctest: +SKIP
|
||||
Running unit tests for numpy.lib
|
||||
...
|
||||
Ran 976 tests in 3.933s
|
||||
|
||||
OK
|
||||
|
||||
>>> result.errors #doctest: +SKIP
|
||||
[]
|
||||
>>> result.knownfail #doctest: +SKIP
|
||||
[]
|
||||
"""
|
||||
|
||||
# cap verbosity at 3 because nose becomes *very* verbose beyond that
|
||||
verbose = min(verbose, 3)
|
||||
|
||||
from . import utils
|
||||
utils.verbose = verbose
|
||||
|
||||
argv, plugins = self.prepare_test_args(
|
||||
label, verbose, extra_argv, doctests, coverage, timer)
|
||||
|
||||
if doctests:
|
||||
print("Running unit tests and doctests for %s" % self.package_name)
|
||||
else:
|
||||
print("Running unit tests for %s" % self.package_name)
|
||||
|
||||
self._show_system_info()
|
||||
|
||||
# reset doctest state on every run
|
||||
import doctest
|
||||
doctest.master = None
|
||||
|
||||
if raise_warnings is None:
|
||||
raise_warnings = self.raise_warnings
|
||||
|
||||
_warn_opts = dict(develop=(Warning,),
|
||||
release=())
|
||||
if isinstance(raise_warnings, str):
|
||||
raise_warnings = _warn_opts[raise_warnings]
|
||||
|
||||
with suppress_warnings("location") as sup:
|
||||
# Reset the warning filters to the default state,
|
||||
# so that running the tests is more repeatable.
|
||||
warnings.resetwarnings()
|
||||
# Set all warnings to 'warn', this is because the default 'once'
|
||||
# has the bad property of possibly shadowing later warnings.
|
||||
warnings.filterwarnings('always')
|
||||
# Force the requested warnings to raise
|
||||
for warningtype in raise_warnings:
|
||||
warnings.filterwarnings('error', category=warningtype)
|
||||
# Filter out annoying import messages.
|
||||
sup.filter(message='Not importing directory')
|
||||
sup.filter(message="numpy.dtype size changed")
|
||||
sup.filter(message="numpy.ufunc size changed")
|
||||
sup.filter(category=np.ModuleDeprecationWarning)
|
||||
# Filter out boolean '-' deprecation messages. This allows
|
||||
# older versions of scipy to test without a flood of messages.
|
||||
sup.filter(message=".*boolean negative.*")
|
||||
sup.filter(message=".*boolean subtract.*")
|
||||
# Filter out distutils cpu warnings (could be localized to
|
||||
# distutils tests). ASV has problems with top level import,
|
||||
# so fetch module for suppression here.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("always")
|
||||
from ...distutils import cpuinfo
|
||||
sup.filter(category=UserWarning, module=cpuinfo)
|
||||
# Filter out some deprecation warnings inside nose 1.3.7 when run
|
||||
# on python 3.5b2. See
|
||||
# https://github.com/nose-devs/nose/issues/929
|
||||
# Note: it is hard to filter based on module for sup (lineno could
|
||||
# be implemented).
|
||||
warnings.filterwarnings("ignore", message=".*getargspec.*",
|
||||
category=DeprecationWarning,
|
||||
module=r"nose\.")
|
||||
|
||||
from .noseclasses import NumpyTestProgram
|
||||
|
||||
t = NumpyTestProgram(argv=argv, exit=False, plugins=plugins)
|
||||
|
||||
return t.result
|
||||
|
||||
def bench(self, label='fast', verbose=1, extra_argv=None):
|
||||
"""
|
||||
Run benchmarks for module using nose.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
label : {'fast', 'full', '', attribute identifier}, optional
|
||||
Identifies the benchmarks to run. This can be a string to pass to
|
||||
the nosetests executable with the '-A' option, or one of several
|
||||
special values. Special values are:
|
||||
|
||||
* 'fast' - the default - which corresponds to the ``nosetests -A``
|
||||
option of 'not slow'.
|
||||
* 'full' - fast (as above) and slow benchmarks as in the
|
||||
'no -A' option to nosetests - this is the same as ''.
|
||||
* None or '' - run all tests.
|
||||
* attribute_identifier - string passed directly to nosetests as '-A'.
|
||||
|
||||
verbose : int, optional
|
||||
Verbosity value for benchmark outputs, in the range 1-10. Default is 1.
|
||||
extra_argv : list, optional
|
||||
List with any extra arguments to pass to nosetests.
|
||||
|
||||
Returns
|
||||
-------
|
||||
success : bool
|
||||
Returns True if running the benchmarks works, False if an error
|
||||
occurred.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Benchmarks are like tests, but have names starting with "bench" instead
|
||||
of "test", and can be found under the "benchmarks" sub-directory of the
|
||||
module.
|
||||
|
||||
Each NumPy module exposes `bench` in its namespace to run all benchmarks
|
||||
for it.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> success = np.lib.bench() #doctest: +SKIP
|
||||
Running benchmarks for numpy.lib
|
||||
...
|
||||
using 562341 items:
|
||||
unique:
|
||||
0.11
|
||||
unique1d:
|
||||
0.11
|
||||
ratio: 1.0
|
||||
nUnique: 56230 == 56230
|
||||
...
|
||||
OK
|
||||
|
||||
>>> success #doctest: +SKIP
|
||||
True
|
||||
|
||||
"""
|
||||
|
||||
print("Running benchmarks for %s" % self.package_name)
|
||||
self._show_system_info()
|
||||
|
||||
argv = self._test_argv(label, verbose, extra_argv)
|
||||
argv += ['--match', r'(?:^|[\\b_\\.%s-])[Bb]ench' % os.sep]
|
||||
|
||||
# import nose or make informative error
|
||||
nose = import_nose()
|
||||
|
||||
# get plugin to disable doctests
|
||||
from .noseclasses import Unplugger
|
||||
add_plugins = [Unplugger('doctest')]
|
||||
|
||||
return nose.run(argv=argv, addplugins=add_plugins)
|
||||
|
||||
|
||||
def _numpy_tester():
|
||||
if hasattr(np, "__version__") and ".dev0" in np.__version__:
|
||||
mode = "develop"
|
||||
else:
|
||||
mode = "release"
|
||||
return NoseTester(raise_warnings=mode, depth=1,
|
||||
check_fpu_mode=True)
|
444
venv/Lib/site-packages/numpy/testing/_private/parameterized.py
Normal file
444
venv/Lib/site-packages/numpy/testing/_private/parameterized.py
Normal file
|
@ -0,0 +1,444 @@
|
|||
"""
|
||||
tl;dr: all code code is licensed under simplified BSD, unless stated otherwise.
|
||||
|
||||
Unless stated otherwise in the source files, all code is copyright 2010 David
|
||||
Wolever <david@wolever.net>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of David Wolever.
|
||||
|
||||
"""
|
||||
import re
|
||||
import inspect
|
||||
import warnings
|
||||
from functools import wraps
|
||||
from types import MethodType
|
||||
from collections import namedtuple
|
||||
|
||||
try:
|
||||
from collections import OrderedDict as MaybeOrderedDict
|
||||
except ImportError:
|
||||
MaybeOrderedDict = dict
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
_param = namedtuple("param", "args kwargs")
|
||||
|
||||
class param(_param):
|
||||
""" Represents a single parameter to a test case.
|
||||
|
||||
For example::
|
||||
|
||||
>>> p = param("foo", bar=16)
|
||||
>>> p
|
||||
param("foo", bar=16)
|
||||
>>> p.args
|
||||
('foo', )
|
||||
>>> p.kwargs
|
||||
{'bar': 16}
|
||||
|
||||
Intended to be used as an argument to ``@parameterized``::
|
||||
|
||||
@parameterized([
|
||||
param("foo", bar=16),
|
||||
])
|
||||
def test_stuff(foo, bar=16):
|
||||
pass
|
||||
"""
|
||||
|
||||
def __new__(cls, *args , **kwargs):
|
||||
return _param.__new__(cls, args, kwargs)
|
||||
|
||||
@classmethod
|
||||
def explicit(cls, args=None, kwargs=None):
|
||||
""" Creates a ``param`` by explicitly specifying ``args`` and
|
||||
``kwargs``::
|
||||
|
||||
>>> param.explicit([1,2,3])
|
||||
param(*(1, 2, 3))
|
||||
>>> param.explicit(kwargs={"foo": 42})
|
||||
param(*(), **{"foo": "42"})
|
||||
"""
|
||||
args = args or ()
|
||||
kwargs = kwargs or {}
|
||||
return cls(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def from_decorator(cls, args):
|
||||
""" Returns an instance of ``param()`` for ``@parameterized`` argument
|
||||
``args``::
|
||||
|
||||
>>> param.from_decorator((42, ))
|
||||
param(args=(42, ), kwargs={})
|
||||
>>> param.from_decorator("foo")
|
||||
param(args=("foo", ), kwargs={})
|
||||
"""
|
||||
if isinstance(args, param):
|
||||
return args
|
||||
elif isinstance(args, (str,)):
|
||||
args = (args, )
|
||||
try:
|
||||
return cls(*args)
|
||||
except TypeError as e:
|
||||
if "after * must be" not in str(e):
|
||||
raise
|
||||
raise TypeError(
|
||||
"Parameters must be tuples, but %r is not (hint: use '(%r, )')"
|
||||
%(args, args),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return "param(*%r, **%r)" %self
|
||||
|
||||
|
||||
class QuietOrderedDict(MaybeOrderedDict):
|
||||
""" When OrderedDict is available, use it to make sure that the kwargs in
|
||||
doc strings are consistently ordered. """
|
||||
__str__ = dict.__str__
|
||||
__repr__ = dict.__repr__
|
||||
|
||||
|
||||
def parameterized_argument_value_pairs(func, p):
|
||||
"""Return tuples of parameterized arguments and their values.
|
||||
|
||||
This is useful if you are writing your own doc_func
|
||||
function and need to know the values for each parameter name::
|
||||
|
||||
>>> def func(a, foo=None, bar=42, **kwargs): pass
|
||||
>>> p = param(1, foo=7, extra=99)
|
||||
>>> parameterized_argument_value_pairs(func, p)
|
||||
[("a", 1), ("foo", 7), ("bar", 42), ("**kwargs", {"extra": 99})]
|
||||
|
||||
If the function's first argument is named ``self`` then it will be
|
||||
ignored::
|
||||
|
||||
>>> def func(self, a): pass
|
||||
>>> p = param(1)
|
||||
>>> parameterized_argument_value_pairs(func, p)
|
||||
[("a", 1)]
|
||||
|
||||
Additionally, empty ``*args`` or ``**kwargs`` will be ignored::
|
||||
|
||||
>>> def func(foo, *args): pass
|
||||
>>> p = param(1)
|
||||
>>> parameterized_argument_value_pairs(func, p)
|
||||
[("foo", 1)]
|
||||
>>> p = param(1, 16)
|
||||
>>> parameterized_argument_value_pairs(func, p)
|
||||
[("foo", 1), ("*args", (16, ))]
|
||||
"""
|
||||
argspec = inspect.getargspec(func)
|
||||
arg_offset = 1 if argspec.args[:1] == ["self"] else 0
|
||||
|
||||
named_args = argspec.args[arg_offset:]
|
||||
|
||||
result = list(zip(named_args, p.args))
|
||||
named_args = argspec.args[len(result) + arg_offset:]
|
||||
varargs = p.args[len(result):]
|
||||
|
||||
result.extend([
|
||||
(name, p.kwargs.get(name, default))
|
||||
for (name, default)
|
||||
in zip(named_args, argspec.defaults or [])
|
||||
])
|
||||
|
||||
seen_arg_names = {n for (n, _) in result}
|
||||
keywords = QuietOrderedDict(sorted([
|
||||
(name, p.kwargs[name])
|
||||
for name in p.kwargs
|
||||
if name not in seen_arg_names
|
||||
]))
|
||||
|
||||
if varargs:
|
||||
result.append(("*%s" %(argspec.varargs, ), tuple(varargs)))
|
||||
|
||||
if keywords:
|
||||
result.append(("**%s" %(argspec.keywords, ), keywords))
|
||||
|
||||
return result
|
||||
|
||||
def short_repr(x, n=64):
|
||||
""" A shortened repr of ``x`` which is guaranteed to be ``unicode``::
|
||||
|
||||
>>> short_repr("foo")
|
||||
u"foo"
|
||||
>>> short_repr("123456789", n=4)
|
||||
u"12...89"
|
||||
"""
|
||||
|
||||
x_repr = repr(x)
|
||||
if isinstance(x_repr, bytes):
|
||||
try:
|
||||
x_repr = str(x_repr, "utf-8")
|
||||
except UnicodeDecodeError:
|
||||
x_repr = str(x_repr, "latin1")
|
||||
if len(x_repr) > n:
|
||||
x_repr = x_repr[:n//2] + "..." + x_repr[len(x_repr) - n//2:]
|
||||
return x_repr
|
||||
|
||||
def default_doc_func(func, num, p):
|
||||
if func.__doc__ is None:
|
||||
return None
|
||||
|
||||
all_args_with_values = parameterized_argument_value_pairs(func, p)
|
||||
|
||||
# Assumes that the function passed is a bound method.
|
||||
descs = ["%s=%s" %(n, short_repr(v)) for n, v in all_args_with_values]
|
||||
|
||||
# The documentation might be a multiline string, so split it
|
||||
# and just work with the first string, ignoring the period
|
||||
# at the end if there is one.
|
||||
first, nl, rest = func.__doc__.lstrip().partition("\n")
|
||||
suffix = ""
|
||||
if first.endswith("."):
|
||||
suffix = "."
|
||||
first = first[:-1]
|
||||
args = "%s[with %s]" %(len(first) and " " or "", ", ".join(descs))
|
||||
return "".join([first.rstrip(), args, suffix, nl, rest])
|
||||
|
||||
def default_name_func(func, num, p):
|
||||
base_name = func.__name__
|
||||
name_suffix = "_%s" %(num, )
|
||||
if len(p.args) > 0 and isinstance(p.args[0], (str,)):
|
||||
name_suffix += "_" + parameterized.to_safe_name(p.args[0])
|
||||
return base_name + name_suffix
|
||||
|
||||
|
||||
# force nose for numpy purposes.
|
||||
_test_runner_override = 'nose'
|
||||
_test_runner_guess = False
|
||||
_test_runners = set(["unittest", "unittest2", "nose", "nose2", "pytest"])
|
||||
_test_runner_aliases = {
|
||||
"_pytest": "pytest",
|
||||
}
|
||||
|
||||
def set_test_runner(name):
|
||||
global _test_runner_override
|
||||
if name not in _test_runners:
|
||||
raise TypeError(
|
||||
"Invalid test runner: %r (must be one of: %s)"
|
||||
%(name, ", ".join(_test_runners)),
|
||||
)
|
||||
_test_runner_override = name
|
||||
|
||||
def detect_runner():
|
||||
""" Guess which test runner we're using by traversing the stack and looking
|
||||
for the first matching module. This *should* be reasonably safe, as
|
||||
it's done during test discovery where the test runner should be the
|
||||
stack frame immediately outside. """
|
||||
if _test_runner_override is not None:
|
||||
return _test_runner_override
|
||||
global _test_runner_guess
|
||||
if _test_runner_guess is False:
|
||||
stack = inspect.stack()
|
||||
for record in reversed(stack):
|
||||
frame = record[0]
|
||||
module = frame.f_globals.get("__name__").partition(".")[0]
|
||||
if module in _test_runner_aliases:
|
||||
module = _test_runner_aliases[module]
|
||||
if module in _test_runners:
|
||||
_test_runner_guess = module
|
||||
break
|
||||
else:
|
||||
_test_runner_guess = None
|
||||
return _test_runner_guess
|
||||
|
||||
class parameterized:
|
||||
""" Parameterize a test case::
|
||||
|
||||
class TestInt:
|
||||
@parameterized([
|
||||
("A", 10),
|
||||
("F", 15),
|
||||
param("10", 42, base=42)
|
||||
])
|
||||
def test_int(self, input, expected, base=16):
|
||||
actual = int(input, base=base)
|
||||
assert_equal(actual, expected)
|
||||
|
||||
@parameterized([
|
||||
(2, 3, 5)
|
||||
(3, 5, 8),
|
||||
])
|
||||
def test_add(a, b, expected):
|
||||
assert_equal(a + b, expected)
|
||||
"""
|
||||
|
||||
def __init__(self, input, doc_func=None):
|
||||
self.get_input = self.input_as_callable(input)
|
||||
self.doc_func = doc_func or default_doc_func
|
||||
|
||||
def __call__(self, test_func):
|
||||
self.assert_not_in_testcase_subclass()
|
||||
|
||||
@wraps(test_func)
|
||||
def wrapper(test_self=None):
|
||||
test_cls = test_self and type(test_self)
|
||||
|
||||
original_doc = wrapper.__doc__
|
||||
for num, args in enumerate(wrapper.parameterized_input):
|
||||
p = param.from_decorator(args)
|
||||
unbound_func, nose_tuple = self.param_as_nose_tuple(test_self, test_func, num, p)
|
||||
try:
|
||||
wrapper.__doc__ = nose_tuple[0].__doc__
|
||||
# Nose uses `getattr(instance, test_func.__name__)` to get
|
||||
# a method bound to the test instance (as opposed to a
|
||||
# method bound to the instance of the class created when
|
||||
# tests were being enumerated). Set a value here to make
|
||||
# sure nose can get the correct test method.
|
||||
if test_self is not None:
|
||||
setattr(test_cls, test_func.__name__, unbound_func)
|
||||
yield nose_tuple
|
||||
finally:
|
||||
if test_self is not None:
|
||||
delattr(test_cls, test_func.__name__)
|
||||
wrapper.__doc__ = original_doc
|
||||
wrapper.parameterized_input = self.get_input()
|
||||
wrapper.parameterized_func = test_func
|
||||
test_func.__name__ = "_parameterized_original_%s" %(test_func.__name__, )
|
||||
return wrapper
|
||||
|
||||
def param_as_nose_tuple(self, test_self, func, num, p):
|
||||
nose_func = wraps(func)(lambda *args: func(*args[:-1], **args[-1]))
|
||||
nose_func.__doc__ = self.doc_func(func, num, p)
|
||||
# Track the unbound function because we need to setattr the unbound
|
||||
# function onto the class for nose to work (see comments above), and
|
||||
# Python 3 doesn't let us pull the function out of a bound method.
|
||||
unbound_func = nose_func
|
||||
if test_self is not None:
|
||||
nose_func = MethodType(nose_func, test_self)
|
||||
return unbound_func, (nose_func, ) + p.args + (p.kwargs or {}, )
|
||||
|
||||
def assert_not_in_testcase_subclass(self):
|
||||
parent_classes = self._terrible_magic_get_defining_classes()
|
||||
if any(issubclass(cls, TestCase) for cls in parent_classes):
|
||||
raise Exception("Warning: '@parameterized' tests won't work "
|
||||
"inside subclasses of 'TestCase' - use "
|
||||
"'@parameterized.expand' instead.")
|
||||
|
||||
def _terrible_magic_get_defining_classes(self):
|
||||
""" Returns the set of parent classes of the class currently being defined.
|
||||
Will likely only work if called from the ``parameterized`` decorator.
|
||||
This function is entirely @brandon_rhodes's fault, as he suggested
|
||||
the implementation: http://stackoverflow.com/a/8793684/71522
|
||||
"""
|
||||
stack = inspect.stack()
|
||||
if len(stack) <= 4:
|
||||
return []
|
||||
frame = stack[4]
|
||||
code_context = frame[4] and frame[4][0].strip()
|
||||
if not (code_context and code_context.startswith("class ")):
|
||||
return []
|
||||
_, _, parents = code_context.partition("(")
|
||||
parents, _, _ = parents.partition(")")
|
||||
return eval("[" + parents + "]", frame[0].f_globals, frame[0].f_locals)
|
||||
|
||||
@classmethod
|
||||
def input_as_callable(cls, input):
|
||||
if callable(input):
|
||||
return lambda: cls.check_input_values(input())
|
||||
input_values = cls.check_input_values(input)
|
||||
return lambda: input_values
|
||||
|
||||
@classmethod
|
||||
def check_input_values(cls, input_values):
|
||||
# Explicitly convert non-list inputs to a list so that:
|
||||
# 1. A helpful exception will be raised if they aren't iterable, and
|
||||
# 2. Generators are unwrapped exactly once (otherwise `nosetests
|
||||
# --processes=n` has issues; see:
|
||||
# https://github.com/wolever/nose-parameterized/pull/31)
|
||||
if not isinstance(input_values, list):
|
||||
input_values = list(input_values)
|
||||
return [ param.from_decorator(p) for p in input_values ]
|
||||
|
||||
@classmethod
|
||||
def expand(cls, input, name_func=None, doc_func=None, **legacy):
|
||||
""" A "brute force" method of parameterizing test cases. Creates new
|
||||
test cases and injects them into the namespace that the wrapped
|
||||
function is being defined in. Useful for parameterizing tests in
|
||||
subclasses of 'UnitTest', where Nose test generators don't work.
|
||||
|
||||
>>> @parameterized.expand([("foo", 1, 2)])
|
||||
... def test_add1(name, input, expected):
|
||||
... actual = add1(input)
|
||||
... assert_equal(actual, expected)
|
||||
...
|
||||
>>> locals()
|
||||
... 'test_add1_foo_0': <function ...> ...
|
||||
>>>
|
||||
"""
|
||||
|
||||
if "testcase_func_name" in legacy:
|
||||
warnings.warn("testcase_func_name= is deprecated; use name_func=",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
if not name_func:
|
||||
name_func = legacy["testcase_func_name"]
|
||||
|
||||
if "testcase_func_doc" in legacy:
|
||||
warnings.warn("testcase_func_doc= is deprecated; use doc_func=",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
if not doc_func:
|
||||
doc_func = legacy["testcase_func_doc"]
|
||||
|
||||
doc_func = doc_func or default_doc_func
|
||||
name_func = name_func or default_name_func
|
||||
|
||||
def parameterized_expand_wrapper(f, instance=None):
|
||||
stack = inspect.stack()
|
||||
frame = stack[1]
|
||||
frame_locals = frame[0].f_locals
|
||||
|
||||
parameters = cls.input_as_callable(input)()
|
||||
for num, p in enumerate(parameters):
|
||||
name = name_func(f, num, p)
|
||||
frame_locals[name] = cls.param_as_standalone_func(p, f, name)
|
||||
frame_locals[name].__doc__ = doc_func(f, num, p)
|
||||
|
||||
f.__test__ = False
|
||||
return parameterized_expand_wrapper
|
||||
|
||||
@classmethod
|
||||
def param_as_standalone_func(cls, p, func, name):
|
||||
@wraps(func)
|
||||
def standalone_func(*a):
|
||||
return func(*(a + p.args), **p.kwargs)
|
||||
standalone_func.__name__ = name
|
||||
|
||||
# place_as is used by py.test to determine what source file should be
|
||||
# used for this test.
|
||||
standalone_func.place_as = func
|
||||
|
||||
# Remove __wrapped__ because py.test will try to look at __wrapped__
|
||||
# to determine which parameters should be used with this test case,
|
||||
# and obviously we don't need it to do any parameterization.
|
||||
try:
|
||||
del standalone_func.__wrapped__
|
||||
except AttributeError:
|
||||
pass
|
||||
return standalone_func
|
||||
|
||||
@classmethod
|
||||
def to_safe_name(cls, s):
|
||||
return str(re.sub("[^a-zA-Z0-9_]+", "_", s))
|
2509
venv/Lib/site-packages/numpy/testing/_private/utils.py
Normal file
2509
venv/Lib/site-packages/numpy/testing/_private/utils.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue