import sys import operator import pytest import ctypes import gc import types from typing import Any import numpy as np from numpy.core._rational_tests import rational from numpy.core._multiarray_tests import create_custom_field_dtype from numpy.testing import ( assert_, assert_equal, assert_array_equal, assert_raises, HAS_REFCOUNT, IS_PYSTON, _OLD_PROMOTION) from numpy.compat import pickle from itertools import permutations import random import hypothesis from hypothesis.extra import numpy as hynp 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: @pytest.mark.parametrize('t', [int, float, complex, np.int32, str, object, np.compat.unicode]) def test_run(self, t): """Only test hash runs at all.""" dt = np.dtype(t) hash(dt) @pytest.mark.parametrize('t', [int, float]) def test_dtype(self, t): # Make sure equivalent byte order char hash the same (e.g. < and = on # little endian) 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_richcompare_invalid_dtype_equality(self): # Make sure objects that cannot be converted to valid # dtypes results in False/True when compared to valid dtypes. # Here 7 cannot be converted to dtype. No exceptions should be raised assert not np.dtype(np.int32) == 7, "dtype richcompare failed for ==" assert np.dtype(np.int32) != 7, "dtype richcompare failed for !=" @pytest.mark.parametrize( 'operation', [operator.le, operator.lt, operator.ge, operator.gt]) def test_richcompare_invalid_dtype_comparison(self, operation): # Make sure TypeError is raised for comparison operators # for invalid dtypes. Here 7 is an invalid dtype. with pytest.raises(TypeError): operation(np.dtype(np.int32), 7) @pytest.mark.parametrize("dtype", ['Bool', 'Bytes0', 'Complex32', 'Complex64', 'Datetime64', 'Float16', 'Float32', 'Float64', 'Int8', 'Int16', 'Int32', 'Int64', 'Object0', 'Str0', 'Timedelta64', 'UInt8', 'UInt16', 'Uint32', 'UInt32', 'Uint64', 'UInt64', 'Void0', "Float128", "Complex128"]) def test_numeric_style_types_are_invalid(self, dtype): with assert_raises(TypeError): np.dtype(dtype) def test_remaining_dtypes_with_bad_bytesize(self): # The np. aliases were deprecated, these probably should be too assert np.dtype("int0") is np.dtype("intp") assert np.dtype("uint0") is np.dtype("uintp") assert np.dtype("bool8") is np.dtype("bool") assert np.dtype("bytes0") is np.dtype("bytes") assert np.dtype("str0") is np.dtype("str") assert np.dtype("object0") is np.dtype("object") @pytest.mark.parametrize( 'value', ['m8', 'M8', 'datetime64', 'timedelta64', 'i4, (2,3)f8, f4', 'a3, 3u8, (3,4)a10', '>f', '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}") with np.printoptions(legacy='1.21'): 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)") def test_repr_structured_not_packed(self): dt = np.dtype({'names': ['rgba', 'r', 'g', 'b'], 'formats': ['i4") assert np.result_type(dt).isnative assert np.result_type(dt).num == dt.num # dtype with empty space: struct_dt = np.dtype(">i4,i1,f4', (2, 1)), ('b', 'u4')]) self.check(BigEndStruct, expected) def test_little_endian_structure_packed(self): class LittleEndStruct(ctypes.LittleEndianStructure): _fields_ = [ ('one', ctypes.c_uint8), ('two', ctypes.c_uint32) ] _pack_ = 1 expected = np.dtype([('one', 'u1'), ('two', 'B'), ('b', '>H') ], align=True) self.check(PaddedStruct, expected) def test_simple_endian_types(self): self.check(ctypes.c_uint16.__ctype_le__, np.dtype('u2')) self.check(ctypes.c_uint8.__ctype_le__, np.dtype('u1')) self.check(ctypes.c_uint8.__ctype_be__, np.dtype('u1')) all_types = set(np.typecodes['All']) all_pairs = permutations(all_types, 2) @pytest.mark.parametrize("pair", all_pairs) def test_pairs(self, pair): """ Check that np.dtype('x,y') matches [np.dtype('x'), np.dtype('y')] Example: np.dtype('d,I') -> dtype([('f0', ' None: alias = np.dtype[Any] assert isinstance(alias, types.GenericAlias) assert alias.__origin__ is np.dtype @pytest.mark.parametrize("code", np.typecodes["All"]) def test_dtype_subclass(self, code: str) -> None: cls = type(np.dtype(code)) alias = cls[Any] assert isinstance(alias, types.GenericAlias) assert alias.__origin__ is cls @pytest.mark.parametrize("arg_len", range(4)) def test_subscript_tuple(self, arg_len: int) -> None: arg_tup = (Any,) * arg_len if arg_len == 1: assert np.dtype[arg_tup] else: with pytest.raises(TypeError): np.dtype[arg_tup] def test_subscript_scalar(self) -> None: assert np.dtype[Any] def test_result_type_integers_and_unitless_timedelta64(): # Regression test for gh-20077. The following call of `result_type` # would cause a seg. fault. td = np.timedelta64(4) result = np.result_type(0, td) assert_dtype_equal(result, td.dtype) @pytest.mark.skipif(sys.version_info >= (3, 9), reason="Requires python 3.8") def test_class_getitem_38() -> None: match = "Type subscription requires python >= 3.9" with pytest.raises(TypeError, match=match): np.dtype[Any]