Download lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py from parallel-reasoner/env-full: direct link, hf CLI and curl.
- Browser
- Download file 17 kB
-
https://huggingface.co/parallel-reasoner/env-full/resolve/b9918be14658eb32f7f27abe8daee683afea2901/lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py
- Command line
-
hf download hf://parallel-reasoner/env-full@b9918be14658eb32f7f27abe8daee683afea2901/lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py
-
curl -L -o test_array_object.py https://huggingface.co/parallel-reasoner/env-full/resolve/b9918be14658eb32f7f27abe8daee683afea2901/lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py
17 kB
| import operator | |
| from numpy.testing import assert_raises, suppress_warnings | |
| import numpy as np | |
| import pytest | |
| from .. import ones, asarray, reshape, result_type, all, equal | |
| from .._array_object import Array | |
| from .._dtypes import ( | |
| _all_dtypes, | |
| _boolean_dtypes, | |
| _real_floating_dtypes, | |
| _floating_dtypes, | |
| _complex_floating_dtypes, | |
| _integer_dtypes, | |
| _integer_or_boolean_dtypes, | |
| _real_numeric_dtypes, | |
| _numeric_dtypes, | |
| int8, | |
| int16, | |
| int32, | |
| int64, | |
| uint64, | |
| bool as bool_, | |
| ) | |
| def test_validate_index(): | |
| # The indexing tests in the official array API test suite test that the | |
| # array object correctly handles the subset of indices that are required | |
| # by the spec. But the NumPy array API implementation specifically | |
| # disallows any index not required by the spec, via Array._validate_index. | |
| # This test focuses on testing that non-valid indices are correctly | |
| # rejected. See | |
| # https://data-apis.org/array-api/latest/API_specification/indexing.html | |
| # and the docstring of Array._validate_index for the exact indexing | |
| # behavior that should be allowed. This does not test indices that are | |
| # already invalid in NumPy itself because Array will generally just pass | |
| # such indices directly to the underlying np.ndarray. | |
| a = ones((3, 4)) | |
| # Out of bounds slices are not allowed | |
| assert_raises(IndexError, lambda: a[:4]) | |
| assert_raises(IndexError, lambda: a[:-4]) | |
| assert_raises(IndexError, lambda: a[:3:-1]) | |
| assert_raises(IndexError, lambda: a[:-5:-1]) | |
| assert_raises(IndexError, lambda: a[4:]) | |
| assert_raises(IndexError, lambda: a[-4:]) | |
| assert_raises(IndexError, lambda: a[4::-1]) | |
| assert_raises(IndexError, lambda: a[-4::-1]) | |
| assert_raises(IndexError, lambda: a[...,:5]) | |
| assert_raises(IndexError, lambda: a[...,:-5]) | |
| assert_raises(IndexError, lambda: a[...,:5:-1]) | |
| assert_raises(IndexError, lambda: a[...,:-6:-1]) | |
| assert_raises(IndexError, lambda: a[...,5:]) | |
| assert_raises(IndexError, lambda: a[...,-5:]) | |
| assert_raises(IndexError, lambda: a[...,5::-1]) | |
| assert_raises(IndexError, lambda: a[...,-5::-1]) | |
| # Boolean indices cannot be part of a larger tuple index | |
| assert_raises(IndexError, lambda: a[a[:,0]==1,0]) | |
| assert_raises(IndexError, lambda: a[a[:,0]==1,...]) | |
| assert_raises(IndexError, lambda: a[..., a[0]==1]) | |
| assert_raises(IndexError, lambda: a[[True, True, True]]) | |
| assert_raises(IndexError, lambda: a[(True, True, True),]) | |
| # Integer array indices are not allowed (except for 0-D) | |
| idx = asarray([[0, 1]]) | |
| assert_raises(IndexError, lambda: a[idx]) | |
| assert_raises(IndexError, lambda: a[idx,]) | |
| assert_raises(IndexError, lambda: a[[0, 1]]) | |
| assert_raises(IndexError, lambda: a[(0, 1), (0, 1)]) | |
| assert_raises(IndexError, lambda: a[[0, 1]]) | |
| assert_raises(IndexError, lambda: a[np.array([[0, 1]])]) | |
| # Multiaxis indices must contain exactly as many indices as dimensions | |
| assert_raises(IndexError, lambda: a[()]) | |
| assert_raises(IndexError, lambda: a[0,]) | |
| assert_raises(IndexError, lambda: a[0]) | |
| assert_raises(IndexError, lambda: a[:]) | |
| def test_operators(): | |
| # For every operator, we test that it works for the required type | |
| # combinations and raises TypeError otherwise | |
| binary_op_dtypes = { | |
| "__add__": "numeric", | |
| "__and__": "integer_or_boolean", | |
| "__eq__": "all", | |
| "__floordiv__": "real numeric", | |
| "__ge__": "real numeric", | |
| "__gt__": "real numeric", | |
| "__le__": "real numeric", | |
| "__lshift__": "integer", | |
| "__lt__": "real numeric", | |
| "__mod__": "real numeric", | |
| "__mul__": "numeric", | |
| "__ne__": "all", | |
| "__or__": "integer_or_boolean", | |
| "__pow__": "numeric", | |
| "__rshift__": "integer", | |
| "__sub__": "numeric", | |
| "__truediv__": "floating", | |
| "__xor__": "integer_or_boolean", | |
| } | |
| # Recompute each time because of in-place ops | |
| def _array_vals(): | |
| for d in _integer_dtypes: | |
| yield asarray(1, dtype=d) | |
| for d in _boolean_dtypes: | |
| yield asarray(False, dtype=d) | |
| for d in _floating_dtypes: | |
| yield asarray(1.0, dtype=d) | |
| BIG_INT = int(1e30) | |
| for op, dtypes in binary_op_dtypes.items(): | |
| ops = [op] | |
| if op not in ["__eq__", "__ne__", "__le__", "__ge__", "__lt__", "__gt__"]: | |
| rop = "__r" + op[2:] | |
| iop = "__i" + op[2:] | |
| ops += [rop, iop] | |
| for s in [1, 1.0, 1j, BIG_INT, False]: | |
| for _op in ops: | |
| for a in _array_vals(): | |
| # Test array op scalar. From the spec, the following combinations | |
| # are supported: | |
| # - Python bool for a bool array dtype, | |
| # - a Python int within the bounds of the given dtype for integer array dtypes, | |
| # - a Python int or float for real floating-point array dtypes | |
| # - a Python int, float, or complex for complex floating-point array dtypes | |
| if ((dtypes == "all" | |
| or dtypes == "numeric" and a.dtype in _numeric_dtypes | |
| or dtypes == "real numeric" and a.dtype in _real_numeric_dtypes | |
| or dtypes == "integer" and a.dtype in _integer_dtypes | |
| or dtypes == "integer_or_boolean" and a.dtype in _integer_or_boolean_dtypes | |
| or dtypes == "boolean" and a.dtype in _boolean_dtypes | |
| or dtypes == "floating" and a.dtype in _floating_dtypes | |
| ) | |
| # bool is a subtype of int, which is why we avoid | |
| # isinstance here. | |
| and (a.dtype in _boolean_dtypes and type(s) == bool | |
| or a.dtype in _integer_dtypes and type(s) == int | |
| or a.dtype in _real_floating_dtypes and type(s) in [float, int] | |
| or a.dtype in _complex_floating_dtypes and type(s) in [complex, float, int] | |
| )): | |
| if a.dtype in _integer_dtypes and s == BIG_INT: | |
| assert_raises(OverflowError, lambda: getattr(a, _op)(s)) | |
| else: | |
| # Only test for no error | |
| with suppress_warnings() as sup: | |
| # ignore warnings from pow(BIG_INT) | |
| sup.filter(RuntimeWarning, | |
| "invalid value encountered in power") | |
| getattr(a, _op)(s) | |
| else: | |
| assert_raises(TypeError, lambda: getattr(a, _op)(s)) | |
| # Test array op array. | |
| for _op in ops: | |
| for x in _array_vals(): | |
| for y in _array_vals(): | |
| # See the promotion table in NEP 47 or the array | |
| # API spec page on type promotion. Mixed kind | |
| # promotion is not defined. | |
| if (x.dtype == uint64 and y.dtype in [int8, int16, int32, int64] | |
| or y.dtype == uint64 and x.dtype in [int8, int16, int32, int64] | |
| or x.dtype in _integer_dtypes and y.dtype not in _integer_dtypes | |
| or y.dtype in _integer_dtypes and x.dtype not in _integer_dtypes | |
| or x.dtype in _boolean_dtypes and y.dtype not in _boolean_dtypes | |
| or y.dtype in _boolean_dtypes and x.dtype not in _boolean_dtypes | |
| or x.dtype in _floating_dtypes and y.dtype not in _floating_dtypes | |
| or y.dtype in _floating_dtypes and x.dtype not in _floating_dtypes | |
| ): | |
| assert_raises(TypeError, lambda: getattr(x, _op)(y)) | |
| # Ensure in-place operators only promote to the same dtype as the left operand. | |
| elif ( | |
| _op.startswith("__i") | |
| and result_type(x.dtype, y.dtype) != x.dtype | |
| ): | |
| assert_raises(TypeError, lambda: getattr(x, _op)(y)) | |
| # Ensure only those dtypes that are required for every operator are allowed. | |
| elif (dtypes == "all" and (x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes | |
| or x.dtype in _numeric_dtypes and y.dtype in _numeric_dtypes) | |
| or (dtypes == "real numeric" and x.dtype in _real_numeric_dtypes and y.dtype in _real_numeric_dtypes) | |
| or (dtypes == "numeric" and x.dtype in _numeric_dtypes and y.dtype in _numeric_dtypes) | |
| or dtypes == "integer" and x.dtype in _integer_dtypes and y.dtype in _integer_dtypes | |
| or dtypes == "integer_or_boolean" and (x.dtype in _integer_dtypes and y.dtype in _integer_dtypes | |
| or x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes) | |
| or dtypes == "boolean" and x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes | |
| or dtypes == "floating" and x.dtype in _floating_dtypes and y.dtype in _floating_dtypes | |
| ): | |
| getattr(x, _op)(y) | |
| else: | |
| assert_raises(TypeError, lambda: getattr(x, _op)(y)) | |
| unary_op_dtypes = { | |
| "__abs__": "numeric", | |
| "__invert__": "integer_or_boolean", | |
| "__neg__": "numeric", | |
| "__pos__": "numeric", | |
| } | |
| for op, dtypes in unary_op_dtypes.items(): | |
| for a in _array_vals(): | |
| if ( | |
| dtypes == "numeric" | |
| and a.dtype in _numeric_dtypes | |
| or dtypes == "integer_or_boolean" | |
| and a.dtype in _integer_or_boolean_dtypes | |
| ): | |
| # Only test for no error | |
| getattr(a, op)() | |
| else: | |
| assert_raises(TypeError, lambda: getattr(a, op)()) | |
| # Finally, matmul() must be tested separately, because it works a bit | |
| # different from the other operations. | |
| def _matmul_array_vals(): | |
| for a in _array_vals(): | |
| yield a | |
| for d in _all_dtypes: | |
| yield ones((3, 4), dtype=d) | |
| yield ones((4, 2), dtype=d) | |
| yield ones((4, 4), dtype=d) | |
| # Scalars always error | |
| for _op in ["__matmul__", "__rmatmul__", "__imatmul__"]: | |
| for s in [1, 1.0, False]: | |
| for a in _matmul_array_vals(): | |
| if (type(s) in [float, int] and a.dtype in _floating_dtypes | |
| or type(s) == int and a.dtype in _integer_dtypes): | |
| # Type promotion is valid, but @ is not allowed on 0-D | |
| # inputs, so the error is a ValueError | |
| assert_raises(ValueError, lambda: getattr(a, _op)(s)) | |
| else: | |
| assert_raises(TypeError, lambda: getattr(a, _op)(s)) | |
| for x in _matmul_array_vals(): | |
| for y in _matmul_array_vals(): | |
| if (x.dtype == uint64 and y.dtype in [int8, int16, int32, int64] | |
| or y.dtype == uint64 and x.dtype in [int8, int16, int32, int64] | |
| or x.dtype in _integer_dtypes and y.dtype not in _integer_dtypes | |
| or y.dtype in _integer_dtypes and x.dtype not in _integer_dtypes | |
| or x.dtype in _floating_dtypes and y.dtype not in _floating_dtypes | |
| or y.dtype in _floating_dtypes and x.dtype not in _floating_dtypes | |
| or x.dtype in _boolean_dtypes | |
| or y.dtype in _boolean_dtypes | |
| ): | |
| assert_raises(TypeError, lambda: x.__matmul__(y)) | |
| assert_raises(TypeError, lambda: y.__rmatmul__(x)) | |
| assert_raises(TypeError, lambda: x.__imatmul__(y)) | |
| elif x.shape == () or y.shape == () or x.shape[1] != y.shape[0]: | |
| assert_raises(ValueError, lambda: x.__matmul__(y)) | |
| assert_raises(ValueError, lambda: y.__rmatmul__(x)) | |
| if result_type(x.dtype, y.dtype) != x.dtype: | |
| assert_raises(TypeError, lambda: x.__imatmul__(y)) | |
| else: | |
| assert_raises(ValueError, lambda: x.__imatmul__(y)) | |
| else: | |
| x.__matmul__(y) | |
| y.__rmatmul__(x) | |
| if result_type(x.dtype, y.dtype) != x.dtype: | |
| assert_raises(TypeError, lambda: x.__imatmul__(y)) | |
| elif y.shape[0] != y.shape[1]: | |
| # This one fails because x @ y has a different shape from x | |
| assert_raises(ValueError, lambda: x.__imatmul__(y)) | |
| else: | |
| x.__imatmul__(y) | |
| def test_python_scalar_construtors(): | |
| b = asarray(False) | |
| i = asarray(0) | |
| f = asarray(0.0) | |
| c = asarray(0j) | |
| assert bool(b) == False | |
| assert int(i) == 0 | |
| assert float(f) == 0.0 | |
| assert operator.index(i) == 0 | |
| # bool/int/float/complex should only be allowed on 0-D arrays. | |
| assert_raises(TypeError, lambda: bool(asarray([False]))) | |
| assert_raises(TypeError, lambda: int(asarray([0]))) | |
| assert_raises(TypeError, lambda: float(asarray([0.0]))) | |
| assert_raises(TypeError, lambda: complex(asarray([0j]))) | |
| assert_raises(TypeError, lambda: operator.index(asarray([0]))) | |
| # bool should work on all types of arrays | |
| assert bool(b) is bool(i) is bool(f) is bool(c) is False | |
| # int should fail on complex arrays | |
| assert int(b) == int(i) == int(f) == 0 | |
| assert_raises(TypeError, lambda: int(c)) | |
| # float should fail on complex arrays | |
| assert float(b) == float(i) == float(f) == 0.0 | |
| assert_raises(TypeError, lambda: float(c)) | |
| # complex should work on all types of arrays | |
| assert complex(b) == complex(i) == complex(f) == complex(c) == 0j | |
| # index should only work on integer arrays | |
| assert operator.index(i) == 0 | |
| assert_raises(TypeError, lambda: operator.index(b)) | |
| assert_raises(TypeError, lambda: operator.index(f)) | |
| assert_raises(TypeError, lambda: operator.index(c)) | |
| def test_device_property(): | |
| a = ones((3, 4)) | |
| assert a.device == 'cpu' | |
| assert all(equal(a.to_device('cpu'), a)) | |
| assert_raises(ValueError, lambda: a.to_device('gpu')) | |
| assert all(equal(asarray(a, device='cpu'), a)) | |
| assert_raises(ValueError, lambda: asarray(a, device='gpu')) | |
| def test_array_properties(): | |
| a = ones((1, 2, 3)) | |
| b = ones((2, 3)) | |
| assert_raises(ValueError, lambda: a.T) | |
| assert isinstance(b.T, Array) | |
| assert b.T.shape == (3, 2) | |
| assert isinstance(a.mT, Array) | |
| assert a.mT.shape == (1, 3, 2) | |
| assert isinstance(b.mT, Array) | |
| assert b.mT.shape == (3, 2) | |
| def test___array__(): | |
| a = ones((2, 3), dtype=int16) | |
| assert np.asarray(a) is a._array | |
| b = np.asarray(a, dtype=np.float64) | |
| assert np.all(np.equal(b, np.ones((2, 3), dtype=np.float64))) | |
| assert b.dtype == np.float64 | |
| def test_allow_newaxis(): | |
| a = ones(5) | |
| indexed_a = a[None, :] | |
| assert indexed_a.shape == (1, 5) | |
| def test_disallow_flat_indexing_with_newaxis(): | |
| a = ones((3, 3, 3)) | |
| with pytest.raises(IndexError): | |
| a[None, 0, 0] | |
| def test_disallow_mask_with_newaxis(): | |
| a = ones((3, 3, 3)) | |
| with pytest.raises(IndexError): | |
| a[None, asarray(True)] | |
| def test_error_on_invalid_index(shape, index): | |
| a = ones(shape) | |
| with pytest.raises(IndexError): | |
| a[index] | |
| def test_mask_0d_array_without_errors(): | |
| a = ones(()) | |
| a[asarray(True)] | |
| def test_error_on_invalid_index_with_ellipsis(i): | |
| a = ones((3, 3, 3)) | |
| with pytest.raises(IndexError): | |
| a[..., i] | |
| with pytest.raises(IndexError): | |
| a[i, ...] | |
| def test_array_keys_use_private_array(): | |
| """ | |
| Indexing operations convert array keys before indexing the internal array | |
| Fails when array_api array keys are not converted into NumPy-proper arrays | |
| in __getitem__(). This is achieved by passing array_api arrays with 0-sized | |
| dimensions, which NumPy-proper treats erroneously - not sure why! | |
| TODO: Find and use appropriate __setitem__() case. | |
| """ | |
| a = ones((0, 0), dtype=bool_) | |
| assert a[a].shape == (0,) | |
| a = ones((0,), dtype=bool_) | |
| key = ones((0, 0), dtype=bool_) | |
| with pytest.raises(IndexError): | |
| a[key] | |