diff options
Diffstat (limited to 'ext/pybind11/tests/test_numpy_array.py')
-rw-r--r-- | ext/pybind11/tests/test_numpy_array.py | 327 |
1 files changed, 175 insertions, 152 deletions
diff --git a/ext/pybind11/tests/test_numpy_array.py b/ext/pybind11/tests/test_numpy_array.py index 14c25b371..27433934f 100644 --- a/ext/pybind11/tests/test_numpy_array.py +++ b/ext/pybind11/tests/test_numpy_array.py @@ -1,4 +1,5 @@ import pytest +from pybind11_tests import numpy_array as m pytestmark = pytest.requires_numpy @@ -12,62 +13,55 @@ def arr(): def test_array_attributes(): - from pybind11_tests.array import ( - ndim, shape, strides, writeable, size, itemsize, nbytes, owndata - ) - a = np.array(0, 'f8') - assert ndim(a) == 0 - assert all(shape(a) == []) - assert all(strides(a) == []) + assert m.ndim(a) == 0 + assert all(m.shape(a) == []) + assert all(m.strides(a) == []) with pytest.raises(IndexError) as excinfo: - shape(a, 0) + m.shape(a, 0) assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)' with pytest.raises(IndexError) as excinfo: - strides(a, 0) + m.strides(a, 0) assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)' - assert writeable(a) - assert size(a) == 1 - assert itemsize(a) == 8 - assert nbytes(a) == 8 - assert owndata(a) + assert m.writeable(a) + assert m.size(a) == 1 + assert m.itemsize(a) == 8 + assert m.nbytes(a) == 8 + assert m.owndata(a) a = np.array([[1, 2, 3], [4, 5, 6]], 'u2').view() a.flags.writeable = False - assert ndim(a) == 2 - assert all(shape(a) == [2, 3]) - assert shape(a, 0) == 2 - assert shape(a, 1) == 3 - assert all(strides(a) == [6, 2]) - assert strides(a, 0) == 6 - assert strides(a, 1) == 2 + assert m.ndim(a) == 2 + assert all(m.shape(a) == [2, 3]) + assert m.shape(a, 0) == 2 + assert m.shape(a, 1) == 3 + assert all(m.strides(a) == [6, 2]) + assert m.strides(a, 0) == 6 + assert m.strides(a, 1) == 2 with pytest.raises(IndexError) as excinfo: - shape(a, 2) + m.shape(a, 2) assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)' with pytest.raises(IndexError) as excinfo: - strides(a, 2) + m.strides(a, 2) assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)' - assert not writeable(a) - assert size(a) == 6 - assert itemsize(a) == 2 - assert nbytes(a) == 12 - assert not owndata(a) + assert not m.writeable(a) + assert m.size(a) == 6 + assert m.itemsize(a) == 2 + assert m.nbytes(a) == 12 + assert not m.owndata(a) @pytest.mark.parametrize('args, ret', [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)]) def test_index_offset(arr, args, ret): - from pybind11_tests.array import index_at, index_at_t, offset_at, offset_at_t - assert index_at(arr, *args) == ret - assert index_at_t(arr, *args) == ret - assert offset_at(arr, *args) == ret * arr.dtype.itemsize - assert offset_at_t(arr, *args) == ret * arr.dtype.itemsize + assert m.index_at(arr, *args) == ret + assert m.index_at_t(arr, *args) == ret + assert m.offset_at(arr, *args) == ret * arr.dtype.itemsize + assert m.offset_at_t(arr, *args) == ret * arr.dtype.itemsize def test_dim_check_fail(arr): - from pybind11_tests.array import (index_at, index_at_t, offset_at, offset_at_t, data, data_t, - mutate_data, mutate_data_t) - for func in (index_at, index_at_t, offset_at, offset_at_t, data, data_t, - mutate_data, mutate_data_t): + for func in (m.index_at, m.index_at_t, m.offset_at, m.offset_at_t, m.data, m.data_t, + m.mutate_data, m.mutate_data_t): with pytest.raises(IndexError) as excinfo: func(arr, 1, 2, 3) assert str(excinfo.value) == 'too many indices for an array: 3 (ndim = 2)' @@ -79,63 +73,53 @@ def test_dim_check_fail(arr): ([0, 1], [2, 3, 4, 5, 6]), ([1, 2], [6])]) def test_data(arr, args, ret): - from pybind11_tests.array import data, data_t from sys import byteorder - assert all(data_t(arr, *args) == ret) - assert all(data(arr, *args)[(0 if byteorder == 'little' else 1)::2] == ret) - assert all(data(arr, *args)[(1 if byteorder == 'little' else 0)::2] == 0) - - -def test_mutate_readonly(arr): - from pybind11_tests.array import mutate_data, mutate_data_t, mutate_at_t - arr.flags.writeable = False - for func, args in (mutate_data, ()), (mutate_data_t, ()), (mutate_at_t, (0, 0)): - with pytest.raises(ValueError) as excinfo: - func(arr, *args) - assert str(excinfo.value) == 'array is not writeable' + assert all(m.data_t(arr, *args) == ret) + assert all(m.data(arr, *args)[(0 if byteorder == 'little' else 1)::2] == ret) + assert all(m.data(arr, *args)[(1 if byteorder == 'little' else 0)::2] == 0) @pytest.mark.parametrize('dim', [0, 1, 3]) def test_at_fail(arr, dim): - from pybind11_tests.array import at_t, mutate_at_t - for func in at_t, mutate_at_t: + for func in m.at_t, m.mutate_at_t: with pytest.raises(IndexError) as excinfo: func(arr, *([0] * dim)) assert str(excinfo.value) == 'index dimension mismatch: {} (ndim = 2)'.format(dim) def test_at(arr): - from pybind11_tests.array import at_t, mutate_at_t + assert m.at_t(arr, 0, 2) == 3 + assert m.at_t(arr, 1, 0) == 4 - assert at_t(arr, 0, 2) == 3 - assert at_t(arr, 1, 0) == 4 + assert all(m.mutate_at_t(arr, 0, 2).ravel() == [1, 2, 4, 4, 5, 6]) + assert all(m.mutate_at_t(arr, 1, 0).ravel() == [1, 2, 4, 5, 5, 6]) - assert all(mutate_at_t(arr, 0, 2).ravel() == [1, 2, 4, 4, 5, 6]) - assert all(mutate_at_t(arr, 1, 0).ravel() == [1, 2, 4, 5, 5, 6]) +def test_mutate_readonly(arr): + arr.flags.writeable = False + for func, args in (m.mutate_data, ()), (m.mutate_data_t, ()), (m.mutate_at_t, (0, 0)): + with pytest.raises(ValueError) as excinfo: + func(arr, *args) + assert str(excinfo.value) == 'array is not writeable' -def test_mutate_data(arr): - from pybind11_tests.array import mutate_data, mutate_data_t - assert all(mutate_data(arr).ravel() == [2, 4, 6, 8, 10, 12]) - assert all(mutate_data(arr).ravel() == [4, 8, 12, 16, 20, 24]) - assert all(mutate_data(arr, 1).ravel() == [4, 8, 12, 32, 40, 48]) - assert all(mutate_data(arr, 0, 1).ravel() == [4, 16, 24, 64, 80, 96]) - assert all(mutate_data(arr, 1, 2).ravel() == [4, 16, 24, 64, 80, 192]) +def test_mutate_data(arr): + assert all(m.mutate_data(arr).ravel() == [2, 4, 6, 8, 10, 12]) + assert all(m.mutate_data(arr).ravel() == [4, 8, 12, 16, 20, 24]) + assert all(m.mutate_data(arr, 1).ravel() == [4, 8, 12, 32, 40, 48]) + assert all(m.mutate_data(arr, 0, 1).ravel() == [4, 16, 24, 64, 80, 96]) + assert all(m.mutate_data(arr, 1, 2).ravel() == [4, 16, 24, 64, 80, 192]) - assert all(mutate_data_t(arr).ravel() == [5, 17, 25, 65, 81, 193]) - assert all(mutate_data_t(arr).ravel() == [6, 18, 26, 66, 82, 194]) - assert all(mutate_data_t(arr, 1).ravel() == [6, 18, 26, 67, 83, 195]) - assert all(mutate_data_t(arr, 0, 1).ravel() == [6, 19, 27, 68, 84, 196]) - assert all(mutate_data_t(arr, 1, 2).ravel() == [6, 19, 27, 68, 84, 197]) + assert all(m.mutate_data_t(arr).ravel() == [5, 17, 25, 65, 81, 193]) + assert all(m.mutate_data_t(arr).ravel() == [6, 18, 26, 66, 82, 194]) + assert all(m.mutate_data_t(arr, 1).ravel() == [6, 18, 26, 67, 83, 195]) + assert all(m.mutate_data_t(arr, 0, 1).ravel() == [6, 19, 27, 68, 84, 196]) + assert all(m.mutate_data_t(arr, 1, 2).ravel() == [6, 19, 27, 68, 84, 197]) def test_bounds_check(arr): - from pybind11_tests.array import (index_at, index_at_t, data, data_t, - mutate_data, mutate_data_t, at_t, mutate_at_t) - funcs = (index_at, index_at_t, data, data_t, - mutate_data, mutate_data_t, at_t, mutate_at_t) - for func in funcs: + for func in (m.index_at, m.index_at_t, m.data, m.data_t, + m.mutate_data, m.mutate_data_t, m.at_t, m.mutate_at_t): with pytest.raises(IndexError) as excinfo: func(arr, 2, 0) assert str(excinfo.value) == 'index 2 is out of bounds for axis 0 with size 2' @@ -145,18 +129,13 @@ def test_bounds_check(arr): def test_make_c_f_array(): - from pybind11_tests.array import ( - make_c_array, make_f_array - ) - assert make_c_array().flags.c_contiguous - assert not make_c_array().flags.f_contiguous - assert make_f_array().flags.f_contiguous - assert not make_f_array().flags.c_contiguous + assert m.make_c_array().flags.c_contiguous + assert not m.make_c_array().flags.f_contiguous + assert m.make_f_array().flags.f_contiguous + assert not m.make_f_array().flags.c_contiguous def test_wrap(): - from pybind11_tests.array import wrap - def assert_references(a, b, base=None): if base is None: base = a @@ -178,36 +157,39 @@ def test_wrap(): a1 = np.array([1, 2], dtype=np.int16) assert a1.flags.owndata and a1.base is None - a2 = wrap(a1) + a2 = m.wrap(a1) assert_references(a1, a2) a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='F') assert a1.flags.owndata and a1.base is None - a2 = wrap(a1) + a2 = m.wrap(a1) assert_references(a1, a2) a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='C') a1.flags.writeable = False - a2 = wrap(a1) + a2 = m.wrap(a1) assert_references(a1, a2) a1 = np.random.random((4, 4, 4)) - a2 = wrap(a1) + a2 = m.wrap(a1) assert_references(a1, a2) a1t = a1.transpose() - a2 = wrap(a1t) + a2 = m.wrap(a1t) assert_references(a1t, a2, a1) a1d = a1.diagonal() - a2 = wrap(a1d) + a2 = m.wrap(a1d) assert_references(a1d, a2, a1) + a1m = a1[::-1, ::-1, ::-1] + a2 = m.wrap(a1m) + assert_references(a1m, a2, a1) + def test_numpy_view(capture): - from pybind11_tests.array import ArrayClass with capture: - ac = ArrayClass() + ac = m.ArrayClass() ac_view_1 = ac.numpy_view() ac_view_2 = ac.numpy_view() assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32)) @@ -234,29 +216,24 @@ def test_numpy_view(capture): @pytest.unsupported_on_pypy def test_cast_numpy_int64_to_uint64(): - from pybind11_tests.array import function_taking_uint64 - function_taking_uint64(123) - function_taking_uint64(np.uint64(123)) + m.function_taking_uint64(123) + m.function_taking_uint64(np.uint64(123)) def test_isinstance(): - from pybind11_tests.array import isinstance_untyped, isinstance_typed - - assert isinstance_untyped(np.array([1, 2, 3]), "not an array") - assert isinstance_typed(np.array([1.0, 2.0, 3.0])) + assert m.isinstance_untyped(np.array([1, 2, 3]), "not an array") + assert m.isinstance_typed(np.array([1.0, 2.0, 3.0])) def test_constructors(): - from pybind11_tests.array import default_constructors, converting_constructors - - defaults = default_constructors() + defaults = m.default_constructors() for a in defaults.values(): assert a.size == 0 assert defaults["array"].dtype == np.array([]).dtype assert defaults["array_t<int32>"].dtype == np.int32 assert defaults["array_t<double>"].dtype == np.float64 - results = converting_constructors([1, 2, 3]) + results = m.converting_constructors([1, 2, 3]) for a in results.values(): np.testing.assert_array_equal(a, [1, 2, 3]) assert results["array"].dtype == np.int_ @@ -265,22 +242,20 @@ def test_constructors(): def test_overload_resolution(msg): - from pybind11_tests.array import overloaded, overloaded2, overloaded3, overloaded4, overloaded5 - # Exact overload matches: - assert overloaded(np.array([1], dtype='float64')) == 'double' - assert overloaded(np.array([1], dtype='float32')) == 'float' - assert overloaded(np.array([1], dtype='ushort')) == 'unsigned short' - assert overloaded(np.array([1], dtype='intc')) == 'int' - assert overloaded(np.array([1], dtype='longlong')) == 'long long' - assert overloaded(np.array([1], dtype='complex')) == 'double complex' - assert overloaded(np.array([1], dtype='csingle')) == 'float complex' + assert m.overloaded(np.array([1], dtype='float64')) == 'double' + assert m.overloaded(np.array([1], dtype='float32')) == 'float' + assert m.overloaded(np.array([1], dtype='ushort')) == 'unsigned short' + assert m.overloaded(np.array([1], dtype='intc')) == 'int' + assert m.overloaded(np.array([1], dtype='longlong')) == 'long long' + assert m.overloaded(np.array([1], dtype='complex')) == 'double complex' + assert m.overloaded(np.array([1], dtype='csingle')) == 'float complex' # No exact match, should call first convertible version: - assert overloaded(np.array([1], dtype='uint8')) == 'double' + assert m.overloaded(np.array([1], dtype='uint8')) == 'double' with pytest.raises(TypeError) as excinfo: - overloaded("not an array") + m.overloaded("not an array") assert msg(excinfo.value) == """ overloaded(): incompatible function arguments. The following argument types are supported: 1. (arg0: numpy.ndarray[float64]) -> str @@ -294,14 +269,14 @@ def test_overload_resolution(msg): Invoked with: 'not an array' """ - assert overloaded2(np.array([1], dtype='float64')) == 'double' - assert overloaded2(np.array([1], dtype='float32')) == 'float' - assert overloaded2(np.array([1], dtype='complex64')) == 'float complex' - assert overloaded2(np.array([1], dtype='complex128')) == 'double complex' - assert overloaded2(np.array([1], dtype='float32')) == 'float' + assert m.overloaded2(np.array([1], dtype='float64')) == 'double' + assert m.overloaded2(np.array([1], dtype='float32')) == 'float' + assert m.overloaded2(np.array([1], dtype='complex64')) == 'float complex' + assert m.overloaded2(np.array([1], dtype='complex128')) == 'double complex' + assert m.overloaded2(np.array([1], dtype='float32')) == 'float' - assert overloaded3(np.array([1], dtype='float64')) == 'double' - assert overloaded3(np.array([1], dtype='intc')) == 'int' + assert m.overloaded3(np.array([1], dtype='float64')) == 'double' + assert m.overloaded3(np.array([1], dtype='intc')) == 'int' expected_exc = """ overloaded3(): incompatible function arguments. The following argument types are supported: 1. (arg0: numpy.ndarray[int32]) -> str @@ -310,70 +285,118 @@ def test_overload_resolution(msg): Invoked with:""" with pytest.raises(TypeError) as excinfo: - overloaded3(np.array([1], dtype='uintc')) + m.overloaded3(np.array([1], dtype='uintc')) assert msg(excinfo.value) == expected_exc + " array([1], dtype=uint32)" with pytest.raises(TypeError) as excinfo: - overloaded3(np.array([1], dtype='float32')) + m.overloaded3(np.array([1], dtype='float32')) assert msg(excinfo.value) == expected_exc + " array([ 1.], dtype=float32)" with pytest.raises(TypeError) as excinfo: - overloaded3(np.array([1], dtype='complex')) + m.overloaded3(np.array([1], dtype='complex')) assert msg(excinfo.value) == expected_exc + " array([ 1.+0.j])" # Exact matches: - assert overloaded4(np.array([1], dtype='double')) == 'double' - assert overloaded4(np.array([1], dtype='longlong')) == 'long long' + assert m.overloaded4(np.array([1], dtype='double')) == 'double' + assert m.overloaded4(np.array([1], dtype='longlong')) == 'long long' # Non-exact matches requiring conversion. Since float to integer isn't a # save conversion, it should go to the double overload, but short can go to # either (and so should end up on the first-registered, the long long). - assert overloaded4(np.array([1], dtype='float32')) == 'double' - assert overloaded4(np.array([1], dtype='short')) == 'long long' + assert m.overloaded4(np.array([1], dtype='float32')) == 'double' + assert m.overloaded4(np.array([1], dtype='short')) == 'long long' - assert overloaded5(np.array([1], dtype='double')) == 'double' - assert overloaded5(np.array([1], dtype='uintc')) == 'unsigned int' - assert overloaded5(np.array([1], dtype='float32')) == 'unsigned int' + assert m.overloaded5(np.array([1], dtype='double')) == 'double' + assert m.overloaded5(np.array([1], dtype='uintc')) == 'unsigned int' + assert m.overloaded5(np.array([1], dtype='float32')) == 'unsigned int' -def test_greedy_string_overload(): # issue 685 - from pybind11_tests.array import issue685 +def test_greedy_string_overload(): + """Tests fix for #685 - ndarray shouldn't go to std::string overload""" - assert issue685("abc") == "string" - assert issue685(np.array([97, 98, 99], dtype='b')) == "array" - assert issue685(123) == "other" + assert m.issue685("abc") == "string" + assert m.issue685(np.array([97, 98, 99], dtype='b')) == "array" + assert m.issue685(123) == "other" def test_array_unchecked_fixed_dims(msg): - from pybind11_tests.array import (proxy_add2, proxy_init3F, proxy_init3, proxy_squared_L2_norm, - proxy_auxiliaries2, array_auxiliaries2) - z1 = np.array([[1, 2], [3, 4]], dtype='float64') - proxy_add2(z1, 10) + m.proxy_add2(z1, 10) assert np.all(z1 == [[11, 12], [13, 14]]) with pytest.raises(ValueError) as excinfo: - proxy_add2(np.array([1., 2, 3]), 5.0) + m.proxy_add2(np.array([1., 2, 3]), 5.0) assert msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2" expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int') - assert np.all(proxy_init3(3.0) == expect_c) + assert np.all(m.proxy_init3(3.0) == expect_c) expect_f = np.transpose(expect_c) - assert np.all(proxy_init3F(3.0) == expect_f) + assert np.all(m.proxy_init3F(3.0) == expect_f) - assert proxy_squared_L2_norm(np.array(range(6))) == 55 - assert proxy_squared_L2_norm(np.array(range(6), dtype="float64")) == 55 + assert m.proxy_squared_L2_norm(np.array(range(6))) == 55 + assert m.proxy_squared_L2_norm(np.array(range(6), dtype="float64")) == 55 - assert proxy_auxiliaries2(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32] - assert proxy_auxiliaries2(z1) == array_auxiliaries2(z1) + assert m.proxy_auxiliaries2(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32] + assert m.proxy_auxiliaries2(z1) == m.array_auxiliaries2(z1) def test_array_unchecked_dyn_dims(msg): - from pybind11_tests.array import (proxy_add2_dyn, proxy_init3_dyn, proxy_auxiliaries2_dyn, - array_auxiliaries2) z1 = np.array([[1, 2], [3, 4]], dtype='float64') - proxy_add2_dyn(z1, 10) + m.proxy_add2_dyn(z1, 10) assert np.all(z1 == [[11, 12], [13, 14]]) expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int') - assert np.all(proxy_init3_dyn(3.0) == expect_c) + assert np.all(m.proxy_init3_dyn(3.0) == expect_c) + + assert m.proxy_auxiliaries2_dyn(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32] + assert m.proxy_auxiliaries2_dyn(z1) == m.array_auxiliaries2(z1) - assert proxy_auxiliaries2_dyn(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32] - assert proxy_auxiliaries2_dyn(z1) == array_auxiliaries2(z1) + +def test_array_failure(): + with pytest.raises(ValueError) as excinfo: + m.array_fail_test() + assert str(excinfo.value) == 'cannot create a pybind11::array from a nullptr' + + with pytest.raises(ValueError) as excinfo: + m.array_t_fail_test() + assert str(excinfo.value) == 'cannot create a pybind11::array_t from a nullptr' + + with pytest.raises(ValueError) as excinfo: + m.array_fail_test_negative_size() + assert str(excinfo.value) == 'negative dimensions are not allowed' + + +def test_initializer_list(): + assert m.array_initializer_list1().shape == (1,) + assert m.array_initializer_list2().shape == (1, 2) + assert m.array_initializer_list3().shape == (1, 2, 3) + assert m.array_initializer_list4().shape == (1, 2, 3, 4) + + +def test_array_resize(msg): + a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='float64') + m.array_reshape2(a) + assert(a.size == 9) + assert(np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]])) + + # total size change should succced with refcheck off + m.array_resize3(a, 4, False) + assert(a.size == 64) + # ... and fail with refcheck on + try: + m.array_resize3(a, 3, True) + except ValueError as e: + assert(str(e).startswith("cannot resize an array")) + # transposed array doesn't own data + b = a.transpose() + try: + m.array_resize3(b, 3, False) + except ValueError as e: + assert(str(e).startswith("cannot resize this array: it does not own its data")) + # ... but reshape should be fine + m.array_reshape2(b) + assert(b.shape == (8, 8)) + + +@pytest.unsupported_on_pypy +def test_array_create_and_resize(msg): + a = m.create_and_resize(2) + assert(a.size == 4) + assert(np.all(a == 42.)) |