from __future__ import division, absolute_import, print_function import pickle import sys import operator import numpy as np from numpy.core._rational_tests import rational from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, dec ) def assert_dtype_equal(a, b): assert_equal(a, b) assert_equal(hash(a), hash(b), "two equivalent types do not hash to the same value !") def assert_dtype_not_equal(a, b): assert_(a != b) assert_(hash(a) != hash(b), "two different types hash to the same value !") class TestBuiltin(object): def test_run(self): """Only test hash runs at all.""" for t in [int, float, complex, np.int32, str, object, np.unicode]: dt = np.dtype(t) hash(dt) def test_dtype(self): # Make sure equivalent byte order char hash the same (e.g. < and = on # little endian) for t in [int, float]: dt = np.dtype(t) dt2 = dt.newbyteorder("<") dt3 = dt.newbyteorder(">") if dt == dt2: assert_(dt.byteorder != dt2.byteorder, "bogus test") assert_dtype_equal(dt, dt2) else: assert_(dt.byteorder != dt3.byteorder, "bogus test") assert_dtype_equal(dt, dt3) def test_equivalent_dtype_hashing(self): # Make sure equivalent dtypes with different type num hash equal uintp = np.dtype(np.uintp) if uintp.itemsize == 4: left = uintp right = np.dtype(np.uint32) else: left = uintp right = np.dtype(np.ulonglong) assert_(left == right) assert_(hash(left) == hash(right)) def test_invalid_types(self): # Make sure invalid type strings raise an error assert_raises(TypeError, np.dtype, 'O3') assert_raises(TypeError, np.dtype, 'O5') assert_raises(TypeError, np.dtype, 'O7') assert_raises(TypeError, np.dtype, 'b3') assert_raises(TypeError, np.dtype, 'h4') assert_raises(TypeError, np.dtype, 'I5') assert_raises(TypeError, np.dtype, 'e3') assert_raises(TypeError, np.dtype, 'f5') if np.dtype('g').itemsize == 8 or np.dtype('g').itemsize == 16: assert_raises(TypeError, np.dtype, 'g12') elif np.dtype('g').itemsize == 12: assert_raises(TypeError, np.dtype, 'g16') if np.dtype('l').itemsize == 8: assert_raises(TypeError, np.dtype, 'l4') assert_raises(TypeError, np.dtype, 'L4') else: assert_raises(TypeError, np.dtype, 'l8') assert_raises(TypeError, np.dtype, 'L8') if np.dtype('q').itemsize == 8: assert_raises(TypeError, np.dtype, 'q4') assert_raises(TypeError, np.dtype, 'Q4') else: assert_raises(TypeError, np.dtype, 'q8') assert_raises(TypeError, np.dtype, 'Q8') def test_bad_param(self): # Can't give a size that's too small assert_raises(ValueError, np.dtype, {'names':['f0', 'f1'], 'formats':['i4', 'i1'], 'offsets':[0, 4], 'itemsize':4}) # If alignment is enabled, the alignment (4) must divide the itemsize assert_raises(ValueError, np.dtype, {'names':['f0', 'f1'], 'formats':['i4', 'i1'], 'offsets':[0, 4], 'itemsize':9}, align=True) # If alignment is enabled, the individual fields must be aligned assert_raises(ValueError, np.dtype, {'names':['f0', 'f1'], 'formats':['i1', 'f4'], 'offsets':[0, 2]}, align=True) def test_field_order_equality(self): x = np.dtype({'names': ['A', 'B'], 'formats': ['i4', 'f4'], 'offsets': [0, 4]}) y = np.dtype({'names': ['B', 'A'], 'formats': ['f4', 'i4'], 'offsets': [4, 0]}) assert_equal(x == y, False) class TestRecord(object): def test_equivalent_record(self): """Test whether equivalent record dtypes hash the same.""" a = np.dtype([('yo', int)]) b = np.dtype([('yo', int)]) assert_dtype_equal(a, b) def test_different_names(self): # In theory, they may hash the same (collision) ? a = np.dtype([('yo', int)]) b = np.dtype([('ye', int)]) assert_dtype_not_equal(a, b) def test_different_titles(self): # In theory, they may hash the same (collision) ? a = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'], 'titles': ['Red pixel', 'Blue pixel']}) b = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'], 'titles': ['RRed pixel', 'Blue pixel']}) assert_dtype_not_equal(a, b) def test_mutate(self): # Mutating a dtype should reset the cached hash value a = np.dtype([('yo', int)]) b = np.dtype([('yo', int)]) c = np.dtype([('ye', int)]) assert_dtype_equal(a, b) assert_dtype_not_equal(a, c) a.names = ['ye'] assert_dtype_equal(a, c) assert_dtype_not_equal(a, b) state = b.__reduce__()[2] a.__setstate__(state) assert_dtype_equal(a, b) assert_dtype_not_equal(a, c) def test_not_lists(self): """Test if an appropriate exception is raised when passing bad values to the dtype constructor. """ assert_raises(TypeError, np.dtype, dict(names=set(['A', 'B']), formats=['f8', 'i4'])) assert_raises(TypeError, np.dtype, dict(names=['A', 'B'], formats=set(['f8', 'i4']))) def test_aligned_size(self): # Check that structured dtypes get padded to an aligned size dt = np.dtype('i4, i1', align=True) assert_equal(dt.itemsize, 8) dt = np.dtype([('f0', 'i4'), ('f1', 'i1')], align=True) assert_equal(dt.itemsize, 8) dt = np.dtype({'names':['f0', 'f1'], 'formats':['i4', 'u1'], 'offsets':[0, 4]}, align=True) assert_equal(dt.itemsize, 8) dt = np.dtype({'f0': ('i4', 0), 'f1':('u1', 4)}, align=True) assert_equal(dt.itemsize, 8) # Nesting should preserve that alignment dt1 = np.dtype([('f0', 'i4'), ('f1', [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')]), ('f2', 'i1')], align=True) assert_equal(dt1.itemsize, 20) dt2 = np.dtype({'names':['f0', 'f1', 'f2'], 'formats':['i4', [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')], 'i1'], 'offsets':[0, 4, 16]}, align=True) assert_equal(dt2.itemsize, 20) dt3 = np.dtype({'f0': ('i4', 0), 'f1': ([('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')], 4), 'f2': ('i1', 16)}, align=True) assert_equal(dt3.itemsize, 20) assert_equal(dt1, dt2) assert_equal(dt2, dt3) # Nesting should preserve packing dt1 = np.dtype([('f0', 'i4'), ('f1', [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')]), ('f2', 'i1')], align=False) assert_equal(dt1.itemsize, 11) dt2 = np.dtype({'names':['f0', 'f1', 'f2'], 'formats':['i4', [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')], 'i1'], 'offsets':[0, 4, 10]}, align=False) assert_equal(dt2.itemsize, 11) dt3 = np.dtype({'f0': ('i4', 0), 'f1': ([('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')], 4), 'f2': ('i1', 10)}, align=False) assert_equal(dt3.itemsize, 11) assert_equal(dt1, dt2) assert_equal(dt2, dt3) def test_union_struct(self): # Should be able to create union dtypes dt = np.dtype({'names':['f0', 'f1', 'f2'], 'formats':['f4', (64, 64)), (1,)), ('rtile', '>f4', (64, 36))], (3,)), ('bottom', [('bleft', ('>f4', (8, 64)), (1,)), ('bright', '>f4', (8, 36))])]) assert_equal(str(dt), "[('top', [('tiles', ('>f4', (64, 64)), (1,)), " "('rtile', '>f4', (64, 36))], (3,)), " "('bottom', [('bleft', ('>f4', (8, 64)), (1,)), " "('bright', '>f4', (8, 36))])]") # If the sticky aligned flag is set to True, it makes the # str() function use a dict representation with an 'aligned' flag dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)), ('rtile', '>f4', (64, 36))], (3,)), ('bottom', [('bleft', ('>f4', (8, 64)), (1,)), ('bright', '>f4', (8, 36))])], align=True) assert_equal(str(dt), "{'names':['top','bottom'], " "'formats':[([('tiles', ('>f4', (64, 64)), (1,)), " "('rtile', '>f4', (64, 36))], (3,))," "[('bleft', ('>f4', (8, 64)), (1,)), " "('bright', '>f4', (8, 36))]], " "'offsets':[0,76800], " "'itemsize':80000, " "'aligned':True}") assert_equal(np.dtype(eval(str(dt))), dt) dt = np.dtype({'names': ['r', 'g', 'b'], 'formats': ['u1', 'u1', 'u1'], 'offsets': [0, 1, 2], 'titles': ['Red pixel', 'Green pixel', 'Blue pixel']}) assert_equal(str(dt), "[(('Red pixel', 'r'), 'u1'), " "(('Green pixel', 'g'), 'u1'), " "(('Blue pixel', 'b'), 'u1')]") dt = np.dtype({'names': ['rgba', 'r', 'g', 'b'], 'formats': ['f4', (64, 64)), (1,)), ('rtile', '>f4', (64, 36))], (3,)), ('bottom', [('bleft', ('>f4', (8, 64)), (1,)), ('bright', '>f4', (8, 36))])]) assert_equal(repr(dt), "dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)), " "('rtile', '>f4', (64, 36))], (3,)), " "('bottom', [('bleft', ('>f4', (8, 64)), (1,)), " "('bright', '>f4', (8, 36))])])") dt = np.dtype({'names': ['r', 'g', 'b'], 'formats': ['u1', 'u1', 'u1'], 'offsets': [0, 1, 2], 'titles': ['Red pixel', 'Green pixel', 'Blue pixel']}, align=True) assert_equal(repr(dt), "dtype([(('Red pixel', 'r'), 'u1'), " "(('Green pixel', 'g'), 'u1'), " "(('Blue pixel', 'b'), 'u1')], align=True)") dt = np.dtype({'names': ['rgba', 'r', 'g', 'b'], 'formats': ['= 3) def test_dtype_str_with_long_in_shape(self): # Pull request #376, should not error np.dtype('(1L,)i4') def test_base_dtype_with_object_type(self): # Issue gh-2798, should not error. np.array(['a'], dtype="O").astype(("O", [("name", "O")])) def test_empty_string_to_object(self): # Pull request #4722 np.array(["", ""]).astype(object) class TestDtypeAttributeDeletion(object): def test_dtype_non_writable_attributes_deletion(self): dt = np.dtype(np.double) attr = ["subdtype", "descr", "str", "name", "base", "shape", "isbuiltin", "isnative", "isalignedstruct", "fields", "metadata", "hasobject"] for s in attr: assert_raises(AttributeError, delattr, dt, s) def test_dtype_writable_attributes_deletion(self): dt = np.dtype(np.double) attr = ["names"] for s in attr: assert_raises(AttributeError, delattr, dt, s) class TestDtypeAttributes(object): def test_descr_has_trailing_void(self): # see gh-6359 dtype = np.dtype({ 'names': ['A', 'B'], 'formats': ['f4', 'f4'], 'offsets': [0, 8], 'itemsize': 16}) new_dtype = np.dtype(dtype.descr) assert_equal(new_dtype.itemsize, 16) def test_name_builtin(self): for t in np.typeDict.values(): name = t.__name__ if name.endswith('_'): name = name[:-1] assert_equal(np.dtype(t).name, name) def test_name_dtype_subclass(self): # Ticket #4357 class user_def_subcls(np.void): pass assert_equal(np.dtype(user_def_subcls).name, 'user_def_subcls') class TestPickling(object): def check_pickling(self, dtype): for proto in range(pickle.HIGHEST_PROTOCOL + 1): pickled = pickle.loads(pickle.dumps(dtype, proto)) assert_equal(pickled, dtype) assert_equal(pickled.descr, dtype.descr) if dtype.metadata is not None: assert_equal(pickled.metadata, dtype.metadata) # Check the reconstructed dtype is functional x = np.zeros(3, dtype=dtype) y = np.zeros(3, dtype=pickled) assert_equal(x, y) assert_equal(x[0], y[0]) def test_builtin(self): for t in [int, float, complex, np.int32, str, object, np.unicode, bool]: self.check_pickling(np.dtype(t)) def test_structured(self): dt = np.dtype(([('a', '>f4', (2, 1)), ('b', '