diff options
Diffstat (limited to 'ext/pybind11/tests/test_numpy_dtypes.py')
-rw-r--r-- | ext/pybind11/tests/test_numpy_dtypes.py | 139 |
1 files changed, 93 insertions, 46 deletions
diff --git a/ext/pybind11/tests/test_numpy_dtypes.py b/ext/pybind11/tests/test_numpy_dtypes.py index 52ebe0ede..f63814f9d 100644 --- a/ext/pybind11/tests/test_numpy_dtypes.py +++ b/ext/pybind11/tests/test_numpy_dtypes.py @@ -1,27 +1,69 @@ import re import pytest +pytestmark = pytest.requires_numpy + with pytest.suppress(ImportError): import numpy as np @pytest.fixture(scope='module') def simple_dtype(): - return np.dtype({'names': ['x', 'y', 'z'], - 'formats': ['?', 'u4', 'f4'], - 'offsets': [0, 4, 8]}) + ld = np.dtype('longdouble') + return np.dtype({'names': ['bool_', 'uint_', 'float_', 'ldbl_'], + 'formats': ['?', 'u4', 'f4', 'f{}'.format(ld.itemsize)], + 'offsets': [0, 4, 8, (16 if ld.alignment > 4 else 12)]}) @pytest.fixture(scope='module') def packed_dtype(): - return np.dtype([('x', '?'), ('y', 'u4'), ('z', 'f4')]) + return np.dtype([('bool_', '?'), ('uint_', 'u4'), ('float_', 'f4'), ('ldbl_', 'g')]) + + +def dt_fmt(): + from sys import byteorder + e = '<' if byteorder == 'little' else '>' + return ("{{'names':['bool_','uint_','float_','ldbl_']," + " 'formats':['?','" + e + "u4','" + e + "f4','" + e + "f{}']," + " 'offsets':[0,4,8,{}], 'itemsize':{}}}") + + +def simple_dtype_fmt(): + ld = np.dtype('longdouble') + simple_ld_off = 12 + 4 * (ld.alignment > 4) + return dt_fmt().format(ld.itemsize, simple_ld_off, simple_ld_off + ld.itemsize) + + +def packed_dtype_fmt(): + from sys import byteorder + return "[('bool_', '?'), ('uint_', '{e}u4'), ('float_', '{e}f4'), ('ldbl_', '{e}f{}')]".format( + np.dtype('longdouble').itemsize, e='<' if byteorder == 'little' else '>') + + +def partial_ld_offset(): + return 12 + 4 * (np.dtype('uint64').alignment > 4) + 8 + 8 * ( + np.dtype('longdouble').alignment > 8) + + +def partial_dtype_fmt(): + ld = np.dtype('longdouble') + partial_ld_off = partial_ld_offset() + return dt_fmt().format(ld.itemsize, partial_ld_off, partial_ld_off + ld.itemsize) + + +def partial_nested_fmt(): + ld = np.dtype('longdouble') + partial_nested_off = 8 + 8 * (ld.alignment > 8) + partial_ld_off = partial_ld_offset() + partial_nested_size = partial_nested_off * 2 + partial_ld_off + ld.itemsize + return "{{'names':['a'], 'formats':[{}], 'offsets':[{}], 'itemsize':{}}}".format( + partial_dtype_fmt(), partial_nested_off, partial_nested_size) def assert_equal(actual, expected_data, expected_dtype): np.testing.assert_equal(actual, np.array(expected_data, dtype=expected_dtype)) -@pytest.requires_numpy def test_format_descriptors(): from pybind11_tests import get_format_unbound, print_format_descriptors @@ -29,33 +71,40 @@ def test_format_descriptors(): get_format_unbound() assert re.match('^NumPy type info missing for .*UnboundStruct.*$', str(excinfo.value)) + ld = np.dtype('longdouble') + ldbl_fmt = ('4x' if ld.alignment > 4 else '') + ld.char + ss_fmt = "T{?:bool_:3xI:uint_:f:float_:" + ldbl_fmt + ":ldbl_:}" + dbl = np.dtype('double') + partial_fmt = ("T{?:bool_:3xI:uint_:f:float_:" + + str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8)) + + "xg:ldbl_:}") + nested_extra = str(max(8, ld.alignment)) assert print_format_descriptors() == [ - "T{?:x:3xI:y:f:z:}", - "T{?:x:=I:y:=f:z:}", - "T{T{?:x:3xI:y:f:z:}:a:T{?:x:=I:y:=f:z:}:b:}", - "T{?:x:3xI:y:f:z:12x}", - "T{8xT{?:x:3xI:y:f:z:12x}:a:8x}", + ss_fmt, + "T{?:bool_:^I:uint_:^f:float_:^g:ldbl_:}", + "T{" + ss_fmt + ":a:T{?:bool_:^I:uint_:^f:float_:^g:ldbl_:}:b:}", + partial_fmt, + "T{" + nested_extra + "x" + partial_fmt + ":a:" + nested_extra + "x}", "T{3s:a:3s:b:}", 'T{q:e1:B:e2:}' ] -@pytest.requires_numpy def test_dtype(simple_dtype): from pybind11_tests import (print_dtypes, test_dtype_ctors, test_dtype_methods, trailing_padding_dtype, buffer_to_dtype) + from sys import byteorder + e = '<' if byteorder == 'little' else '>' assert print_dtypes() == [ - "{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}", - "[('x', '?'), ('y', '<u4'), ('z', '<f4')]", - "[('a', {'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8]," - " 'itemsize':12}), ('b', [('x', '?'), ('y', '<u4'), ('z', '<f4')])]", - "{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}", - "{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4']," - " 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}", + simple_dtype_fmt(), + packed_dtype_fmt(), + "[('a', {}), ('b', {})]".format(simple_dtype_fmt(), packed_dtype_fmt()), + partial_dtype_fmt(), + partial_nested_fmt(), "[('a', 'S3'), ('b', 'S3')]", - "[('e1', '<i8'), ('e2', 'u1')]", - "[('x', 'i1'), ('y', '<u8')]" + "[('e1', '" + e + "i8'), ('e2', 'u1')]", + "[('x', 'i1'), ('y', '" + e + "u8')]" ] d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'], @@ -70,13 +119,12 @@ def test_dtype(simple_dtype): assert trailing_padding_dtype() == buffer_to_dtype(np.zeros(1, trailing_padding_dtype())) -@pytest.requires_numpy def test_recarray(simple_dtype, packed_dtype): from pybind11_tests import (create_rec_simple, create_rec_packed, create_rec_nested, print_rec_simple, print_rec_packed, print_rec_nested, create_rec_partial, create_rec_partial_nested) - elements = [(False, 0, 0.0), (True, 1, 1.5), (False, 2, 3.0)] + elements = [(False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)] for func, dtype in [(create_rec_simple, simple_dtype), (create_rec_packed, packed_dtype)]: arr = func(0) @@ -91,15 +139,15 @@ def test_recarray(simple_dtype, packed_dtype): if dtype == simple_dtype: assert print_rec_simple(arr) == [ - "s:0,0,0", - "s:1,1,1.5", - "s:0,2,3" + "s:0,0,0,-0", + "s:1,1,1.5,-2.5", + "s:0,2,3,-5" ] else: assert print_rec_packed(arr) == [ - "p:0,0,0", - "p:1,1,1.5", - "p:0,2,3" + "p:0,0,0,-0", + "p:1,1,1.5,-2.5", + "p:0,2,3,-5" ] nested_dtype = np.dtype([('a', simple_dtype), ('b', packed_dtype)]) @@ -110,18 +158,17 @@ def test_recarray(simple_dtype, packed_dtype): arr = create_rec_nested(3) assert arr.dtype == nested_dtype - assert_equal(arr, [((False, 0, 0.0), (True, 1, 1.5)), - ((True, 1, 1.5), (False, 2, 3.0)), - ((False, 2, 3.0), (True, 3, 4.5))], nested_dtype) + assert_equal(arr, [((False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5)), + ((True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)), + ((False, 2, 3.0, -5.0), (True, 3, 4.5, -7.5))], nested_dtype) assert print_rec_nested(arr) == [ - "n:a=s:0,0,0;b=p:1,1,1.5", - "n:a=s:1,1,1.5;b=p:0,2,3", - "n:a=s:0,2,3;b=p:1,3,4.5" + "n:a=s:0,0,0,-0;b=p:1,1,1.5,-2.5", + "n:a=s:1,1,1.5,-2.5;b=p:0,2,3,-5", + "n:a=s:0,2,3,-5;b=p:1,3,4.5,-7.5" ] arr = create_rec_partial(3) - assert str(arr.dtype) == \ - "{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}" + assert str(arr.dtype) == partial_dtype_fmt() partial_dtype = arr.dtype assert '' not in arr.dtype.fields assert partial_dtype.itemsize > simple_dtype.itemsize @@ -129,16 +176,13 @@ def test_recarray(simple_dtype, packed_dtype): assert_equal(arr, elements, packed_dtype) arr = create_rec_partial_nested(3) - assert str(arr.dtype) == \ - "{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4']," \ - " 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}" + assert str(arr.dtype) == partial_nested_fmt() assert '' not in arr.dtype.fields assert '' not in arr.dtype.fields['a'][0].fields assert arr.dtype.itemsize > partial_dtype.itemsize np.testing.assert_equal(arr['a'], create_rec_partial(3)) -@pytest.requires_numpy def test_array_constructors(): from pybind11_tests import test_array_ctors @@ -151,7 +195,6 @@ def test_array_constructors(): np.testing.assert_array_equal(test_array_ctors(40 + i), data) -@pytest.requires_numpy def test_string_array(): from pybind11_tests import create_string_array, print_string_array @@ -170,13 +213,14 @@ def test_string_array(): assert dtype == arr.dtype -@pytest.requires_numpy def test_enum_array(): from pybind11_tests import create_enum_array, print_enum_array + from sys import byteorder + e = '<' if byteorder == 'little' else '>' arr = create_enum_array(3) dtype = arr.dtype - assert dtype == np.dtype([('e1', '<i8'), ('e2', 'u1')]) + assert dtype == np.dtype([('e1', e + 'i8'), ('e2', 'u1')]) assert print_enum_array(arr) == [ "e1=A,e2=X", "e1=B,e2=Y", @@ -187,14 +231,12 @@ def test_enum_array(): assert create_enum_array(0).dtype == dtype -@pytest.requires_numpy def test_signature(doc): from pybind11_tests import create_rec_nested assert doc(create_rec_nested) == "create_rec_nested(arg0: int) -> numpy.ndarray[NestedStruct]" -@pytest.requires_numpy def test_scalar_conversion(): from pybind11_tests import (create_rec_simple, f_simple, create_rec_packed, f_packed, @@ -216,10 +258,15 @@ def test_scalar_conversion(): assert 'incompatible function arguments' in str(excinfo.value) -@pytest.requires_numpy def test_register_dtype(): from pybind11_tests import register_dtype with pytest.raises(RuntimeError) as excinfo: register_dtype() assert 'dtype is already registered' in str(excinfo.value) + + +@pytest.requires_numpy +def test_compare_buffer_info(): + from pybind11_tests import compare_buffer_info + assert all(compare_buffer_info()) |