From 1392e2417150bdea473e3b29867c685c09b25447 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Thu, 12 Nov 2015 17:20:17 +0000 Subject: DOC: document that assert_raises can be used as a context manager --- numpy/testing/utils.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index c6d863f94..099b75bdf 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1102,6 +1102,18 @@ def assert_raises(*args,**kwargs): deemed to have suffered an error, exactly as for an unexpected exception. + Alternatively, `assert_raises` can be used as a context manager: + + >>> from numpy.testing import assert_raises + >>> with assert_raises(ZeroDivisionError): + ... 1 / 0 + + is equivalent to + + >>> def div(x, y): + ... return x / y + >>> assert_raises(ZeroDivisionError, div, 1, 0) + """ __tracebackhide__ = True # Hide traceback for py.test nose = import_nose() -- cgit v1.2.1 From eadc135a5f2ab577748188770af66feafe87859d Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 14 Nov 2015 14:28:25 +0200 Subject: BUG: testing: fix a bug in assert_string_equal --- numpy/testing/utils.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 099b75bdf..8a282ff3c 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1018,11 +1018,12 @@ def assert_string_equal(actual, desired): if not d2.startswith('+ '): raise AssertionError(repr(d2)) l.append(d2) - d3 = diff.pop(0) - if d3.startswith('? '): - l.append(d3) - else: - diff.insert(0, d3) + if diff: + d3 = diff.pop(0) + if d3.startswith('? '): + l.append(d3) + else: + diff.insert(0, d3) if re.match(r'\A'+d2[2:]+r'\Z', d1[2:]): continue diff_list.extend(l) -- cgit v1.2.1 From 70c5052a9f07025c236033cf629506bb38eb6d97 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Sun, 15 Nov 2015 07:48:20 +0000 Subject: ENH: testing: add SkipTest and KnownFailureException * use SkipTest in numpy tests instead of importing it from nose * add a KnownFailureException as an alias for KnownFailureTest (the former is preferred, but the latter is kept for backcompat) * rename the KnownFailure nose plugin into KnownFailurePlugin, and keep the old name for backcompat --- numpy/testing/utils.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 8a282ff3c..00f7ce4d1 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -13,6 +13,7 @@ from functools import partial import shutil import contextlib from tempfile import mkdtemp + from .nosetester import import_nose from numpy.core import float32, empty, arange, array_repr, ndarray @@ -28,11 +29,27 @@ __all__ = ['assert_equal', 'assert_almost_equal', 'assert_approx_equal', 'raises', 'rand', 'rundocs', 'runstring', 'verbose', 'measure', 'assert_', 'assert_array_almost_equal_nulp', 'assert_raises_regex', 'assert_array_max_ulp', 'assert_warns', 'assert_no_warnings', - 'assert_allclose', 'IgnoreException', 'clear_and_catch_warnings'] + 'assert_allclose', 'IgnoreException', 'clear_and_catch_warnings', + 'SkipTest', 'KnownFailureException'] -verbose = 0 +class KnownFailureException(Exception): + '''Raise this exception to mark a test as a known failing test.''' + pass + +KnownFailureTest = KnownFailureException # backwards compat + +# nose.SkipTest is unittest.case.SkipTest +# import it into the namespace, so that it's available as np.testing.SkipTest +try: + from unittest.case import SkipTest +except ImportError: + # on py2.6 unittest.case is not available. Ask nose for a replacement. + SkipTest = import_nose().SkipTest + + +verbose = 0 def assert_(val, msg=''): """ -- cgit v1.2.1 From 443184b12513ce2a8adcc2a81c143bc4bc697219 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Sat, 19 Dec 2015 15:01:55 -0700 Subject: ENH: Add context manager `temppath` to manage a temporary file. Context manager intended for use when the same temporary file needs to be opened and closed more than once. The context manager creates the file, closes it, and returns the path to the file. On exit from the context block the file is removed. The file should be closed before exiting the context as an error will be raised on windows if not. Also fix up the `tempdir` context manager to deal with exceptions. Tests are added for both `temppath` and `tempdir`. --- numpy/testing/utils.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 00f7ce4d1..e85e2f95f 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -12,7 +12,7 @@ import warnings from functools import partial import shutil import contextlib -from tempfile import mkdtemp +from tempfile import mkdtemp, mkstemp from .nosetester import import_nose from numpy.core import float32, empty, arange, array_repr, ndarray @@ -30,7 +30,7 @@ __all__ = ['assert_equal', 'assert_almost_equal', 'assert_approx_equal', 'assert_', 'assert_array_almost_equal_nulp', 'assert_raises_regex', 'assert_array_max_ulp', 'assert_warns', 'assert_no_warnings', 'assert_allclose', 'IgnoreException', 'clear_and_catch_warnings', - 'SkipTest', 'KnownFailureException'] + 'SkipTest', 'KnownFailureException', 'temppath', 'tempdir'] class KnownFailureException(Exception): @@ -1810,8 +1810,31 @@ def tempdir(*args, **kwargs): """ tmpdir = mkdtemp(*args, **kwargs) - yield tmpdir - shutil.rmtree(tmpdir) + try: + yield tmpdir + finally: + shutil.rmtree(tmpdir) + +@contextlib.contextmanager +def temppath(*args, **kwargs): + """Context manager for temporary files. + + Context manager that returns the path to a closed temporary file. Its + parameters are the same as for tempfile.mkstemp and are passed directly + to that function. The underlying file is removed when the context is + exited, so it should be closed at that time. + + Windows does not allow a temporary file to be opened if it is already + open, so the underlying file must be closed after opening before it + can be opened again. + + """ + fd, path = mkstemp(*args, **kwargs) + os.close(fd) + try: + yield path + finally: + os.remove(path) class clear_and_catch_warnings(warnings.catch_warnings): -- cgit v1.2.1 From 8bc592fabf4a2b0bc76db996b1523330ba095be3 Mon Sep 17 00:00:00 2001 From: gfyoung Date: Sat, 19 Dec 2015 16:49:35 -0800 Subject: DOC: Use print only as function when print_function is imported from __future__ Closes gh-6863. --- numpy/testing/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 00f7ce4d1..49d249339 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1293,7 +1293,7 @@ def measure(code_str,times=1,label=None): -------- >>> etime = np.testing.measure('for i in range(1000): np.sqrt(i**2)', ... times=times) - >>> print "Time for a single execution : ", etime / times, "s" + >>> print("Time for a single execution : ", etime / times, "s") Time for a single execution : 0.005 s """ -- cgit v1.2.1 From 2edc202a2a70a17893e523dd4eb56b6668522981 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Mon, 4 Jan 2016 15:58:55 +0000 Subject: DEP: deprecate np.testing.rand --- numpy/testing/utils.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 0c4ebe1b9..f545cd3c2 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -16,6 +16,7 @@ from tempfile import mkdtemp, mkstemp from .nosetester import import_nose from numpy.core import float32, empty, arange, array_repr, ndarray +from numpy.lib.utils import deprecate if sys.version_info[0] >= 3: from io import StringIO @@ -122,6 +123,8 @@ def gisinf(x): raise TypeError("isinf not supported for this type") return st +@deprecate(message="numpy.testing.rand is deprecated in numpy 1.11. " + "Use numpy.random.rand instead.") def rand(*args): """Returns an array of random numbers with the given shape. -- cgit v1.2.1 From 53ad26a84ac2aa6f5a37f09aa9feae5afed44f79 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Tue, 12 Jan 2016 20:44:34 -0800 Subject: TST, ENH: make all comparisons with NaT false Now, NaT compares like NaN: - NaT != NaT -> True - NaT == NaT (and all other comparisons) -> False We discussed this on the mailing list back in October: https://mail.scipy.org/pipermail/numpy-discussion/2015-October/073968.html --- numpy/testing/utils.py | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index f545cd3c2..8e71a3399 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -15,7 +15,7 @@ import contextlib from tempfile import mkdtemp, mkstemp from .nosetester import import_nose -from numpy.core import float32, empty, arange, array_repr, ndarray +from numpy.core import float32, empty, arange, array_repr, ndarray, dtype from numpy.lib.utils import deprecate if sys.version_info[0] >= 3: @@ -343,16 +343,31 @@ def assert_equal(actual,desired,err_msg='',verbose=True): except AssertionError: raise AssertionError(msg) + def isnat(x): + return (hasattr(x, 'dtype') + and getattr(x.dtype, 'kind', '_') in 'mM' + and x != x) + # Inf/nan/negative zero handling try: # isscalar test to check cases such as [np.nan] != np.nan - if isscalar(desired) != isscalar(actual): + # dtypes compare equal to strings, but unlike strings aren't scalars, + # so we need to exclude them from this check + if (isscalar(desired) != isscalar(actual) + and not (isinstance(desired, dtype) + or isinstance(actual, dtype))): raise AssertionError(msg) + # check NaT before NaN, because isfinite errors on datetime dtypes + if isnat(desired) and isnat(actual): + if desired.dtype.kind != actual.dtype.kind: + # datetime64 and timedelta64 NaT should not be comparable + raise AssertionError(msg) + return # If one of desired/actual is not finite, handle it specially here: # check that both are nan if any is a nan, and test for equality # otherwise - if not (gisfinite(desired) and gisfinite(actual)): + elif not (gisfinite(desired) and gisfinite(actual)): isdesnan = gisnan(desired) isactnan = gisnan(actual) if isdesnan or isactnan: @@ -663,6 +678,9 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, def isnumber(x): return x.dtype.char in '?bhilqpBHILQPefdgFDG' + def isdatetime(x): + return x.dtype.char in 'mM' + def chk_same_position(x_id, y_id, hasval='nan'): """Handling nan/inf: check that x and y have the nan/inf at the same locations.""" @@ -675,6 +693,15 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, names=('x', 'y'), precision=precision) raise AssertionError(msg) + def chk_same_dtype(x_dt, y_dt): + try: + assert_equal(x_dt, y_dt) + except AssertionError: + msg = build_err_msg([x, y], err_msg + '\nx and y dtype mismatch', + verbose=verbose, header=header, + names=('x', 'y'), precision=precision) + raise AssertionError(msg) + try: cond = (x.shape == () or y.shape == ()) or x.shape == y.shape if not cond: @@ -712,6 +739,20 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, val = safe_comparison(x[~x_id], y[~y_id]) else: val = safe_comparison(x, y) + elif isdatetime(x) and isdatetime(y): + x_isnat, y_isnat = (x != x), (y != y) + + if any(x_isnat) or any(y_isnat): + # cannot mix timedelta64/datetime64 NaT + chk_same_dtype(x.dtype, y.dtype) + chk_same_position(x_isnat, y_isnat, hasval='nat') + + if all(x_isnat): + return + if any(x_isnat): + val = safe_comparison(x[~x_isnat], y[~y_isnat]) + else: + val = safe_comparison(x, y) else: val = safe_comparison(x, y) @@ -1826,7 +1867,7 @@ def temppath(*args, **kwargs): parameters are the same as for tempfile.mkstemp and are passed directly to that function. The underlying file is removed when the context is exited, so it should be closed at that time. - + Windows does not allow a temporary file to be opened if it is already open, so the underlying file must be closed after opening before it can be opened again. -- cgit v1.2.1 From d588b48a0e2fd4a78cadc1336571f59ba6be83c6 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Thu, 14 Jan 2016 22:06:15 -0800 Subject: TST: Make assert_warns an optional contextmanager --- numpy/testing/utils.py | 69 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 18 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 8e71a3399..72105ca31 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1706,7 +1706,22 @@ class WarningManager(object): self._module.showwarning = self._showwarning -def assert_warns(warning_class, func, *args, **kw): +@contextlib.contextmanager +def _assert_warns_context(warning_class, name=None): + __tracebackhide__ = True # Hide traceback for py.test + with warnings.catch_warnings(record=True) as l: + warnings.simplefilter('always') + yield + if not len(l) > 0: + name_str = " when calling %s" % name if name is not None else "" + raise AssertionError("No warning raised" + name_str) + if not l[0].category is warning_class: + name_str = "%s " % name if name is not None else "" + raise AssertionError("First warning %sis not a %s (is %s)" + % (name_str, warning_class, l[0])) + + +def assert_warns(warning_class, *args, **kwargs): """ Fail unless the given callable throws the specified warning. @@ -1715,6 +1730,12 @@ def assert_warns(warning_class, func, *args, **kw): If a different type of warning is thrown, it will not be caught, and the test case will be deemed to have suffered an error. + If called with all arguments other than the warning class omitted, may be + used as a context manager: + + with assert_warns(SomeWarning): + do_something() + .. versionadded:: 1.4.0 Parameters @@ -1733,22 +1754,35 @@ def assert_warns(warning_class, func, *args, **kw): The value returned by `func`. """ + if not args: + return _assert_warns_context(warning_class) + + func = args[0] + args = args[1:] + with _assert_warns_context(warning_class, name=func.__name__): + return func(*args, **kwargs) + + +@contextlib.contextmanager +def _assert_no_warnings_context(name=None): __tracebackhide__ = True # Hide traceback for py.test with warnings.catch_warnings(record=True) as l: warnings.simplefilter('always') - result = func(*args, **kw) - if not len(l) > 0: - raise AssertionError("No warning raised when calling %s" - % func.__name__) - if not l[0].category is warning_class: - raise AssertionError("First warning for %s is not a " - "%s( is %s)" % (func.__name__, warning_class, l[0])) - return result + yield + if len(l) > 0: + name_str = " when calling %s" % name if name is not None else "" + raise AssertionError("Got warnings%s: %s" % (name_str, l)) + -def assert_no_warnings(func, *args, **kw): +def assert_no_warnings(*args, **kwargs): """ Fail if the given callable produces any warnings. + If called with all arguments omitted, may be used as a context manager: + + with assert_no_warnings(): + do_something() + .. versionadded:: 1.7.0 Parameters @@ -1765,14 +1799,13 @@ def assert_no_warnings(func, *args, **kw): The value returned by `func`. """ - __tracebackhide__ = True # Hide traceback for py.test - with warnings.catch_warnings(record=True) as l: - warnings.simplefilter('always') - result = func(*args, **kw) - if len(l) > 0: - raise AssertionError("Got warnings when calling %s: %s" - % (func.__name__, l)) - return result + if not args: + return _assert_no_warnings_context() + + func = args[0] + args = args[1:] + with _assert_no_warnings_context(name=func.__name__): + return func(*args, **kwargs) def _gen_alignment_data(dtype=float32, type='binary', max_size=24): -- cgit v1.2.1 From da98bbc030c272edb1a8548a458b3957e29ce346 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Sat, 16 Jan 2016 16:35:28 -0800 Subject: DOC: document changes to assert_warns --- numpy/testing/utils.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 72105ca31..10a48ad79 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1736,6 +1736,8 @@ def assert_warns(warning_class, *args, **kwargs): with assert_warns(SomeWarning): do_something() + The ability to be used as a context manager is new in NumPy v1.11.0. + .. versionadded:: 1.4.0 Parameters @@ -1783,6 +1785,8 @@ def assert_no_warnings(*args, **kwargs): with assert_no_warnings(): do_something() + The ability to be used as a context manager is new in NumPy v1.11.0. + .. versionadded:: 1.7.0 Parameters -- cgit v1.2.1 From e0cb3f79936656d6d2f48cbad46a3a9f2bad5ae1 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Sat, 16 Jan 2016 19:00:43 -0700 Subject: Revert "Merge pull request #7001 from shoyer/NaT-comparison" This reverts commit 7141f40b58ed1e7071cde78ab7bc8ab37e9c5983, reversing changes made to 8fa6e3bef26a6d4a2c92f2824129aa4409be2590. The original broke some pandas tests. The current plan to get this in is * reversion * issue FutureWarning in 1.11 and 1.12 * make the change in 1.13. --- numpy/testing/utils.py | 49 ++++--------------------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 8e71a3399..f545cd3c2 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -15,7 +15,7 @@ import contextlib from tempfile import mkdtemp, mkstemp from .nosetester import import_nose -from numpy.core import float32, empty, arange, array_repr, ndarray, dtype +from numpy.core import float32, empty, arange, array_repr, ndarray from numpy.lib.utils import deprecate if sys.version_info[0] >= 3: @@ -343,31 +343,16 @@ def assert_equal(actual,desired,err_msg='',verbose=True): except AssertionError: raise AssertionError(msg) - def isnat(x): - return (hasattr(x, 'dtype') - and getattr(x.dtype, 'kind', '_') in 'mM' - and x != x) - # Inf/nan/negative zero handling try: # isscalar test to check cases such as [np.nan] != np.nan - # dtypes compare equal to strings, but unlike strings aren't scalars, - # so we need to exclude them from this check - if (isscalar(desired) != isscalar(actual) - and not (isinstance(desired, dtype) - or isinstance(actual, dtype))): + if isscalar(desired) != isscalar(actual): raise AssertionError(msg) - # check NaT before NaN, because isfinite errors on datetime dtypes - if isnat(desired) and isnat(actual): - if desired.dtype.kind != actual.dtype.kind: - # datetime64 and timedelta64 NaT should not be comparable - raise AssertionError(msg) - return # If one of desired/actual is not finite, handle it specially here: # check that both are nan if any is a nan, and test for equality # otherwise - elif not (gisfinite(desired) and gisfinite(actual)): + if not (gisfinite(desired) and gisfinite(actual)): isdesnan = gisnan(desired) isactnan = gisnan(actual) if isdesnan or isactnan: @@ -678,9 +663,6 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, def isnumber(x): return x.dtype.char in '?bhilqpBHILQPefdgFDG' - def isdatetime(x): - return x.dtype.char in 'mM' - def chk_same_position(x_id, y_id, hasval='nan'): """Handling nan/inf: check that x and y have the nan/inf at the same locations.""" @@ -693,15 +675,6 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, names=('x', 'y'), precision=precision) raise AssertionError(msg) - def chk_same_dtype(x_dt, y_dt): - try: - assert_equal(x_dt, y_dt) - except AssertionError: - msg = build_err_msg([x, y], err_msg + '\nx and y dtype mismatch', - verbose=verbose, header=header, - names=('x', 'y'), precision=precision) - raise AssertionError(msg) - try: cond = (x.shape == () or y.shape == ()) or x.shape == y.shape if not cond: @@ -739,20 +712,6 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, val = safe_comparison(x[~x_id], y[~y_id]) else: val = safe_comparison(x, y) - elif isdatetime(x) and isdatetime(y): - x_isnat, y_isnat = (x != x), (y != y) - - if any(x_isnat) or any(y_isnat): - # cannot mix timedelta64/datetime64 NaT - chk_same_dtype(x.dtype, y.dtype) - chk_same_position(x_isnat, y_isnat, hasval='nat') - - if all(x_isnat): - return - if any(x_isnat): - val = safe_comparison(x[~x_isnat], y[~y_isnat]) - else: - val = safe_comparison(x, y) else: val = safe_comparison(x, y) @@ -1867,7 +1826,7 @@ def temppath(*args, **kwargs): parameters are the same as for tempfile.mkstemp and are passed directly to that function. The underlying file is removed when the context is exited, so it should be closed at that time. - + Windows does not allow a temporary file to be opened if it is already open, so the underlying file must be closed after opening before it can be opened again. -- cgit v1.2.1 From 91a86f6715604183741f84d429a3a5c2fc7d7e9e Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Fri, 19 Feb 2016 15:02:35 -0800 Subject: Clarify error on repr failure in assert_equal. assert_equal(np.array([0, 1]), np.matrix([0, 1])) used to print x: array([0, 1]) y: [repr failed] now prints x: array([0, 1]) y: [repr failed for : The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()] --- numpy/testing/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index f2588788d..133330a12 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -252,8 +252,8 @@ def build_err_msg(arrays, err_msg, header='Items are not equal:', try: r = r_func(a) - except: - r = '[repr failed]' + except Exception as exc: + r = '[repr failed for <{}>: {}]'.format(type(a).__name__, exc) if r.count('\n') > 3: r = '\n'.join(r.splitlines()[:3]) r += '...' -- cgit v1.2.1 From 6198616b25d50abc9aabbce6784c10aaa10b33ce Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Mon, 4 Apr 2016 12:39:39 -0600 Subject: MAINT: Remove nose.SkipTest import. This was only needed for Python 2.6 as it is available from unittest in later Python versions. --- numpy/testing/utils.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 133330a12..9511e00be 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -13,6 +13,7 @@ from functools import partial import shutil import contextlib from tempfile import mkdtemp, mkstemp +from unittest.case import SkipTest from .nosetester import import_nose from numpy.core import float32, empty, arange, array_repr, ndarray @@ -38,20 +39,11 @@ class KnownFailureException(Exception): '''Raise this exception to mark a test as a known failing test.''' pass -KnownFailureTest = KnownFailureException # backwards compat - - -# nose.SkipTest is unittest.case.SkipTest -# import it into the namespace, so that it's available as np.testing.SkipTest -try: - from unittest.case import SkipTest -except ImportError: - # on py2.6 unittest.case is not available. Ask nose for a replacement. - SkipTest = import_nose().SkipTest - +KnownFailureTest = KnownFailureException # backwards compat verbose = 0 + def assert_(val, msg=''): """ Assert that works in release mode. -- cgit v1.2.1 From 0002eda3f817f296bb10ddfc297ca6f19b727940 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Mon, 4 Apr 2016 12:45:54 -0600 Subject: STY: PEP8, two blank lines between top level function definitions. --- numpy/testing/utils.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 9511e00be..3667e67e0 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -62,6 +62,7 @@ def assert_(val, msg=''): smsg = msg raise AssertionError(smsg) + def gisnan(x): """like isnan, but always raise an error if type not supported instead of returning a TypeError object. @@ -79,6 +80,7 @@ def gisnan(x): raise TypeError("isnan not supported for this type") return st + def gisfinite(x): """like isfinite, but always raise an error if type not supported instead of returning a TypeError object. @@ -97,6 +99,7 @@ def gisfinite(x): raise TypeError("isfinite not supported for this type") return st + def gisinf(x): """like isinf, but always raise an error if type not supported instead of returning a TypeError object. @@ -115,6 +118,7 @@ def gisinf(x): raise TypeError("isinf not supported for this type") return st + @deprecate(message="numpy.testing.rand is deprecated in numpy 1.11. " "Use numpy.random.rand instead.") def rand(*args): @@ -130,6 +134,7 @@ def rand(*args): f[i] = random.random() return results + if os.name == 'nt': # Code "stolen" from enthought/debug/memusage.py def GetPerformanceAttributes(object, counter, instance=None, @@ -252,6 +257,7 @@ def build_err_msg(arrays, err_msg, header='Items are not equal:', msg.append(' %s: %s' % (names[i], r)) return '\n'.join(msg) + def assert_equal(actual,desired,err_msg='',verbose=True): """ Raises an AssertionError if two objects are not equal. @@ -366,6 +372,7 @@ def assert_equal(actual,desired,err_msg='',verbose=True): if not (desired == actual): raise AssertionError(msg) + def print_assert_equal(test_string, actual, desired): """ Test if two objects are equal, and print an error message if test fails. @@ -406,6 +413,7 @@ def print_assert_equal(test_string, actual, desired): pprint.pprint(desired, msg) raise AssertionError(msg.getvalue()) + def assert_almost_equal(actual,desired,decimal=7,err_msg='',verbose=True): """ Raises an AssertionError if two items are not equal up to desired @@ -622,6 +630,7 @@ def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True): if np.abs(sc_desired - sc_actual) >= np.power(10., -(significant-1)): raise AssertionError(msg) + def assert_array_compare(comparison, x, y, err_msg='', verbose=True, header='', precision=6): __tracebackhide__ = True # Hide traceback for py.test @@ -732,6 +741,7 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, names=('x', 'y'), precision=precision) raise ValueError(msg) + def assert_array_equal(x, y, err_msg='', verbose=True): """ Raises an AssertionError if two array_like objects are not equal. @@ -798,6 +808,7 @@ def assert_array_equal(x, y, err_msg='', verbose=True): assert_array_compare(operator.__eq__, x, y, err_msg=err_msg, verbose=verbose, header='Arrays are not equal') + def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True): """ Raises an AssertionError if two objects are not equal up to desired @@ -975,9 +986,11 @@ def assert_array_less(x, y, err_msg='', verbose=True): verbose=verbose, header='Arrays are not less-ordered') + def runstring(astr, dict): exec(astr, dict) + def assert_string_equal(actual, desired): """ Test if two strings are equal. @@ -1382,6 +1395,7 @@ def assert_allclose(actual, desired, rtol=1e-7, atol=0, equal_nan=False, assert_array_compare(compare, actual, desired, err_msg=str(err_msg), verbose=verbose, header=header) + def assert_array_almost_equal_nulp(x, y, nulp=1): """ Compare two arrays relatively to their spacing. @@ -1444,6 +1458,7 @@ def assert_array_almost_equal_nulp(x, y, nulp=1): msg = "X and Y are not equal to %d ULP (max is %g)" % (nulp, max_nulp) raise AssertionError(msg) + def assert_array_max_ulp(a, b, maxulp=1, dtype=None): """ Check that all items of arrays differ in at most N Units in the Last Place. @@ -1488,6 +1503,7 @@ def assert_array_max_ulp(a, b, maxulp=1, dtype=None): maxulp) return ret + def nulp_diff(x, y, dtype=None): """For each item in x and y, return the number of representable floating points between them. @@ -1541,6 +1557,7 @@ def nulp_diff(x, y, dtype=None): ry = integer_repr(y) return _diff(rx, ry, t) + def _integer_repr(x, vdt, comp): # Reinterpret binary representation of the float as sign-magnitude: # take into account two-complement representation @@ -1555,6 +1572,7 @@ def _integer_repr(x, vdt, comp): return rx + def integer_repr(x): """Return the signed-magnitude interpretation of the binary representation of x.""" @@ -1566,6 +1584,7 @@ def integer_repr(x): else: raise ValueError("Unsupported dtype %s" % x.dtype) + # The following two classes are copied from python 2.6 warnings module (context # manager) class WarningMessage(object): @@ -1600,6 +1619,7 @@ class WarningMessage(object): "line : %r}" % (self.message, self._category_name, self.filename, self.lineno, self.line)) + class WarningManager(object): """ A context manager that copies and restores the warnings filter upon @@ -1847,6 +1867,7 @@ def tempdir(*args, **kwargs): finally: shutil.rmtree(tmpdir) + @contextlib.contextmanager def temppath(*args, **kwargs): """Context manager for temporary files. @@ -1855,7 +1876,7 @@ def temppath(*args, **kwargs): parameters are the same as for tempfile.mkstemp and are passed directly to that function. The underlying file is removed when the context is exited, so it should be closed at that time. - + Windows does not allow a temporary file to be opened if it is already open, so the underlying file must be closed after opening before it can be opened again. -- cgit v1.2.1 From c185c71c8eb7192e44ac381ce9883805068815ea Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Sat, 14 May 2016 22:14:04 +0200 Subject: MAINT: clean up testing.assert_raises_regexp, 2.6-specific code removed. The global also was ugly and not useful. --- numpy/testing/utils.py | 75 ++++++++------------------------------------------ 1 file changed, 12 insertions(+), 63 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 3667e67e0..3f4a8568a 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1146,9 +1146,6 @@ def assert_raises(*args,**kwargs): return nose.tools.assert_raises(*args,**kwargs) -assert_raises_regex_impl = None - - def assert_raises_regex(exception_class, expected_regexp, callable_obj=None, *args, **kwargs): """ @@ -1159,70 +1156,22 @@ def assert_raises_regex(exception_class, expected_regexp, Name of this function adheres to Python 3.2+ reference, but should work in all versions down to 2.6. + Notes + ----- + .. versionadded:: 1.9.0 + """ __tracebackhide__ = True # Hide traceback for py.test nose = import_nose() - global assert_raises_regex_impl - if assert_raises_regex_impl is None: - try: - # Python 3.2+ - assert_raises_regex_impl = nose.tools.assert_raises_regex - except AttributeError: - try: - # 2.7+ - assert_raises_regex_impl = nose.tools.assert_raises_regexp - except AttributeError: - # 2.6 - - # This class is copied from Python2.7 stdlib almost verbatim - class _AssertRaisesContext(object): - """A context manager used to implement TestCase.assertRaises* methods.""" - - def __init__(self, expected, expected_regexp=None): - self.expected = expected - self.expected_regexp = expected_regexp - - def failureException(self, msg): - return AssertionError(msg) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - if exc_type is None: - try: - exc_name = self.expected.__name__ - except AttributeError: - exc_name = str(self.expected) - raise self.failureException( - "{0} not raised".format(exc_name)) - if not issubclass(exc_type, self.expected): - # let unexpected exceptions pass through - return False - self.exception = exc_value # store for later retrieval - if self.expected_regexp is None: - return True - - expected_regexp = self.expected_regexp - if isinstance(expected_regexp, basestring): - expected_regexp = re.compile(expected_regexp) - if not expected_regexp.search(str(exc_value)): - raise self.failureException( - '"%s" does not match "%s"' % - (expected_regexp.pattern, str(exc_value))) - return True - - def impl(cls, regex, callable_obj, *a, **kw): - mgr = _AssertRaisesContext(cls, regex) - if callable_obj is None: - return mgr - with mgr: - callable_obj(*a, **kw) - assert_raises_regex_impl = impl - - return assert_raises_regex_impl(exception_class, expected_regexp, - callable_obj, *args, **kwargs) + if sys.version_info.major >= 3: + funcname = nose.tools.assert_raises_regex + else: + # Only present in Python 2.7, missing from unittest in 2.6 + funcname = nose.tools.assert_raises_regexp + + return funcname(exception_class, expected_regexp, callable_obj, + *args, **kwargs) def decorate_methods(cls, decorator, testmatch=None): -- cgit v1.2.1 From 55002a5204240bfaabdc19bd670c50e47881247c Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Sat, 18 Jun 2016 13:00:33 -0600 Subject: ENH: Make assert_almost_equal & assert_array_almost_equal consistent. This changes the check for scalars in assert_almost_equal so that abs(actual - desired) < 1.5 * 10**(-decimal) Note that the previous documentation claimed that the functions were equivalent to abs(actual - desired) < .5 * 10**(-decimal) but that was not how they behaved in practice. Due to the change in implementation, some very delicate tests may fail that did not fail before. No extra failures were noted in scipy. Closes #5200. --- numpy/testing/utils.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 3f4a8568a..dfed5d148 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -424,11 +424,14 @@ def assert_almost_equal(actual,desired,decimal=7,err_msg='',verbose=True): instead of this function for more consistent floating point comparisons. - The test is equivalent to ``abs(desired-actual) < 0.5 * 10**(-decimal)``. + The test verifies that the elements of ``actual`` and ``desired`` satisfy. - Given two objects (numbers or ndarrays), check that all elements of these - objects are almost equal. An exception is raised at conflicting values. - For ndarrays this delegates to assert_array_almost_equal + ``abs(desired-actual) < 1.5 * 10**(-decimal)`` + + That is a looser test than originally documented, but agrees with what the + actual implementation in `assert_array_almost_equal` did up to rounding + vagaries. An exception is raised at conflicting values. For ndarrays this + delegates to assert_array_almost_equal Parameters ---------- @@ -529,7 +532,7 @@ def assert_almost_equal(actual,desired,decimal=7,err_msg='',verbose=True): return except (NotImplementedError, TypeError): pass - if round(abs(desired - actual), decimal) != 0: + if abs(desired - actual) >= 1.5 * 10.0**(-decimal): raise AssertionError(_build_err_msg()) @@ -819,14 +822,16 @@ def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True): instead of this function for more consistent floating point comparisons. - The test verifies identical shapes and verifies values with - ``abs(desired-actual) < 0.5 * 10**(-decimal)``. + The test verifies identical shapes and that the elements of ``actual`` and + ``desired`` satisfy. - Given two array_like objects, check that the shape is equal and all - elements of these objects are almost equal. An exception is raised at - shape mismatch or conflicting values. In contrast to the standard usage - in numpy, NaNs are compared like numbers, no assertion is raised if - both objects have NaNs in the same positions. + ``abs(desired-actual) < 1.5 * 10**(-decimal)`` + + That is a looser test than originally documented, but agrees with what the + actual implementation did up to rounding vagaries. An exception is raised + at shape mismatch or conflicting values. In contrast to the standard usage + in numpy, NaNs are compared like numbers, no assertion is raised if both + objects have NaNs in the same positions. Parameters ---------- @@ -903,12 +908,12 @@ def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True): # casting of x later. dtype = result_type(y, 1.) y = array(y, dtype=dtype, copy=False, subok=True) - z = abs(x-y) + z = abs(x - y) if not issubdtype(z.dtype, number): z = z.astype(float_) # handle object arrays - return around(z, decimal) <= 10.0**(-decimal) + return z < 1.5 * 10.0**(-decimal) assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose, header=('Arrays are not almost equal to %d decimals' % decimal), -- cgit v1.2.1 From a05b65337725072710ee00dd695aa2df47eb5b4e Mon Sep 17 00:00:00 2001 From: bertrand Date: Mon, 13 Jun 2016 20:53:10 -0400 Subject: MAINT,DOC: add to compat.py3k a function to load modules. Fix some doc for f2py.compile (issue #7683) --- numpy/testing/utils.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 3f4a8568a..447495c50 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1083,18 +1083,13 @@ def rundocs(filename=None, raise_on_error=True): >>> np.lib.test(doctests=True) #doctest: +SKIP """ + from numpy.compat import npy_load_module import doctest - import imp if filename is None: f = sys._getframe(1) filename = f.f_globals['__file__'] name = os.path.splitext(os.path.basename(filename))[0] - path = [os.path.dirname(filename)] - file, pathname, description = imp.find_module(name, path) - try: - m = imp.load_module(name, file, pathname, description) - finally: - file.close() + m = npy_load_module(name, filename) tests = doctest.DocTestFinder().find(m) runner = doctest.DocTestRunner(verbose=False) -- cgit v1.2.1 From 76eff9ca4648e96ba1f560e83f40383f68805493 Mon Sep 17 00:00:00 2001 From: mattip Date: Sat, 6 Aug 2016 23:15:40 +0300 Subject: ENH: skip or avoid gc/objectmodel differences btwn pypy and cpython --- numpy/testing/utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'numpy/testing/utils.py') diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index dc1115e1b..176d87800 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -32,7 +32,8 @@ __all__ = ['assert_equal', 'assert_almost_equal', 'assert_approx_equal', 'assert_', 'assert_array_almost_equal_nulp', 'assert_raises_regex', 'assert_array_max_ulp', 'assert_warns', 'assert_no_warnings', 'assert_allclose', 'IgnoreException', 'clear_and_catch_warnings', - 'SkipTest', 'KnownFailureException', 'temppath', 'tempdir'] + 'SkipTest', 'KnownFailureException', 'temppath', 'tempdir', 'IS_PYPY', + 'HAS_REFCOUNT'] class KnownFailureException(Exception): @@ -43,6 +44,8 @@ class KnownFailureException(Exception): KnownFailureTest = KnownFailureException # backwards compat verbose = 0 +IS_PYPY = '__pypy__' in sys.modules +HAS_REFCOUNT = getattr(sys, 'getrefcount', None) is not None def assert_(val, msg=''): """ @@ -1274,6 +1277,8 @@ def _assert_valid_refcount(op): Check that ufuncs don't mishandle refcount of object `1`. Used in a few regression tests. """ + if not HAS_REFCOUNT: + return True import numpy as np b = np.arange(100*100).reshape(100, 100) -- cgit v1.2.1