From 6b4223e3e03c1cb3df63ec41bb4c897a70eab15b Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Thu, 7 Nov 2024 17:46:03 -0700 Subject: [PATCH 1/3] Require NumPy >= 2.1 Fixes #21 --- .github/workflows/array-api-tests.yml | 7 +--- .github/workflows/tests.yml | 7 +--- array_api_strict/__init__.py | 6 +++ array_api_strict/_array_object.py | 40 +++++--------------- array_api_strict/_creation_functions.py | 23 ----------- array_api_strict/tests/test_array_object.py | 42 ++++++++------------- requirements-dev.txt | 2 +- requirements.txt | 2 +- setup.py | 2 +- 9 files changed, 37 insertions(+), 94 deletions(-) diff --git a/.github/workflows/array-api-tests.yml b/.github/workflows/array-api-tests.yml index 9f168cb..cbfe5a2 100644 --- a/.github/workflows/array-api-tests.yml +++ b/.github/workflows/array-api-tests.yml @@ -12,10 +12,7 @@ jobs: strategy: matrix: python-version: ['3.9', '3.10', '3.11', '3.12'] - numpy-version: ['1.26', 'dev'] - exclude: - - python-version: '3.8' - numpy-version: 'dev' + numpy-version: ['2.1', 'dev'] steps: - name: Checkout array-api-strict @@ -38,7 +35,7 @@ jobs: if [[ "${{ matrix.numpy-version }}" == "dev" ]]; then python -m pip install --pre --extra-index https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy; else - python -m pip install 'numpy>=1.26,<2.0'; + python -m pip install 'numpy==${{ matrix.numpy-version }}'; fi python -m pip install ${GITHUB_WORKSPACE}/array-api-strict python -m pip install -r ${GITHUB_WORKSPACE}/array-api-tests/requirements.txt diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d8124d4..312f9cd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,10 +6,7 @@ jobs: strategy: matrix: python-version: ['3.9', '3.10', '3.11', '3.12'] - numpy-version: ['1.26', 'dev'] - exclude: - - python-version: '3.8' - numpy-version: 'dev' + numpy-version: ['2.1', 'dev'] fail-fast: true steps: - uses: actions/checkout@v4 @@ -22,7 +19,7 @@ jobs: if [[ "${{ matrix.numpy-version }}" == "dev" ]]; then python -m pip install --pre --extra-index https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy; else - python -m pip install 'numpy>=1.26,<2.0'; + python -m pip install 'numpy==${{ matrix.numpy-version }}'; fi python -m pip install -r requirements-dev.txt - name: Run Tests diff --git a/array_api_strict/__init__.py b/array_api_strict/__init__.py index ff43660..cbda499 100644 --- a/array_api_strict/__init__.py +++ b/array_api_strict/__init__.py @@ -16,6 +16,12 @@ """ +import numpy as np +from numpy.lib import NumpyVersion + +if NumpyVersion(np.__version__) < NumpyVersion('2.1.0'): + raise ImportError("array-api-strict requires NumPy >= 2.1.0") + __all__ = [] # Warning: __array_api_version__ could change globally with diff --git a/array_api_strict/_array_object.py b/array_api_strict/_array_object.py index 53669d1..76cdfac 100644 --- a/array_api_strict/_array_object.py +++ b/array_api_strict/_array_object.py @@ -162,19 +162,7 @@ def __array__(self, dtype: None | np.dtype[Any] = None, copy: None | bool = None if _allow_array: if self._device != CPU_DEVICE: raise RuntimeError(f"Can not convert array on the '{self._device}' device to a Numpy array.") - # copy keyword is new in 2.0.0; for older versions don't use it - # retry without that keyword. - if np.__version__[0] < '2': - return np.asarray(self._array, dtype=dtype) - elif np.__version__.startswith('2.0.0-dev0'): - # Handle dev version for which we can't know based on version - # number whether or not the copy keyword is supported. - try: - return np.asarray(self._array, dtype=dtype, copy=copy) - except TypeError: - return np.asarray(self._array, dtype=dtype) - else: - return np.asarray(self._array, dtype=dtype, copy=copy) + return np.asarray(self._array, dtype=dtype, copy=copy) raise ValueError("Conversion from an array_api_strict array to a NumPy ndarray is not supported") # These are various helper functions to make the array behavior match the @@ -586,24 +574,14 @@ def __dlpack__( if copy is not _default: raise ValueError("The copy argument to __dlpack__ requires at least version 2023.12 of the array API") - if np.__version__[0] < '2.1': - if max_version not in [_default, None]: - raise NotImplementedError("The max_version argument to __dlpack__ is not yet implemented") - if dl_device not in [_default, None]: - raise NotImplementedError("The device argument to __dlpack__ is not yet implemented") - if copy not in [_default, None]: - raise NotImplementedError("The copy argument to __dlpack__ is not yet implemented") - - return self._array.__dlpack__(stream=stream) - else: - kwargs = {'stream': stream} - if max_version is not _default: - kwargs['max_version'] = max_version - if dl_device is not _default: - kwargs['dl_device'] = dl_device - if copy is not _default: - kwargs['copy'] = copy - return self._array.__dlpack__(**kwargs) + kwargs = {'stream': stream} + if max_version is not _default: + kwargs['max_version'] = max_version + if dl_device is not _default: + kwargs['dl_device'] = dl_device + if copy is not _default: + kwargs['copy'] = copy + return self._array.__dlpack__(**kwargs) def __dlpack_device__(self: Array, /) -> Tuple[IntEnum, int]: """ diff --git a/array_api_strict/_creation_functions.py b/array_api_strict/_creation_functions.py index d6d3efa..8d7705b 100644 --- a/array_api_strict/_creation_functions.py +++ b/array_api_strict/_creation_functions.py @@ -83,29 +83,6 @@ def asarray( if isinstance(obj, Array) and device is None: device = obj.device - if np.__version__[0] < '2': - if copy is False: - # Note: copy=False is not yet implemented in np.asarray for - # NumPy 1 - - # Work around it by creating the new array and seeing if NumPy - # copies it. - if isinstance(obj, Array): - new_array = np.array(obj._array, copy=copy, dtype=_np_dtype) - if new_array is not obj._array: - raise ValueError("Unable to avoid copy while creating an array from given array.") - return Array._new(new_array, device=device) - elif _supports_buffer_protocol(obj): - # Buffer protocol will always support no-copy - return Array._new(np.array(obj, copy=copy, dtype=_np_dtype), device=device) - else: - # No-copy is unsupported for Python built-in types. - raise ValueError("Unable to avoid copy while creating an array from given object.") - - if copy is None: - # NumPy 1 treats copy=False the same as the standard copy=None - copy = False - if isinstance(obj, Array): return Array._new(np.array(obj._array, copy=copy, dtype=_np_dtype), device=device) if dtype is None and isinstance(obj, int) and (obj > 2 ** 64 or obj < -(2 ** 63)): diff --git a/array_api_strict/tests/test_array_object.py b/array_api_strict/tests/test_array_object.py index 96fd31e..0480f00 100644 --- a/array_api_strict/tests/test_array_object.py +++ b/array_api_strict/tests/test_array_object.py @@ -456,31 +456,19 @@ def dlpack_2023_12(api_version): set_array_api_strict_flags(api_version=api_version) a = asarray([1, 2, 3], dtype=int8) - # Never an error - a.__dlpack__() - - if np.__version__ < '2.1': - exception = NotImplementedError if api_version >= '2023.12' else ValueError - pytest.raises(exception, lambda: - a.__dlpack__(dl_device=CPU_DEVICE)) - pytest.raises(exception, lambda: - a.__dlpack__(dl_device=None)) - pytest.raises(exception, lambda: - a.__dlpack__(max_version=(1, 0))) - pytest.raises(exception, lambda: - a.__dlpack__(max_version=None)) - pytest.raises(exception, lambda: - a.__dlpack__(copy=False)) - pytest.raises(exception, lambda: - a.__dlpack__(copy=True)) - pytest.raises(exception, lambda: - a.__dlpack__(copy=None)) - else: - a.__dlpack__(dl_device=CPU_DEVICE) - a.__dlpack__(dl_device=None) - a.__dlpack__(max_version=(1, 0)) - a.__dlpack__(max_version=None) - a.__dlpack__(copy=False) - a.__dlpack__(copy=True) - a.__dlpack__(copy=None) + # Do not error + a.__dlpack__() + a.__dlpack__(dl_device=CPU_DEVICE) + a.__dlpack__(dl_device=None) + a.__dlpack__(max_version=(1, 0)) + a.__dlpack__(max_version=None) + a.__dlpack__(copy=False) + a.__dlpack__(copy=True) + a.__dlpack__(copy=None) + + x = np.from_dlpack(a) + assert isinstance(x, np.ndarray) + assert x.dtype == np.int8 + assert x.shape == (3,) + assert np.all(x == np.asarray([1, 2, 3])) diff --git a/requirements-dev.txt b/requirements-dev.txt index 137e973..62673a8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,3 @@ pytest hypothesis -numpy +numpy>=2.1 diff --git a/requirements.txt b/requirements.txt index 24ce15a..92ce2ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -numpy +numpy>=2.1 diff --git a/setup.py b/setup.py index 29a94df..21d7417 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ url="https://data-apis.org/array-api-strict/", license="MIT", python_requires=">=3.9", - install_requires=["numpy"], + install_requires=["numpy>=2.1"], classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", From 0129dc4541f0c1d6d462abff92995c805319533b Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Thu, 7 Nov 2024 17:50:31 -0700 Subject: [PATCH 2/3] Fix installation of numpy 2.1 on CI --- .github/workflows/array-api-tests.yml | 2 +- .github/workflows/tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/array-api-tests.yml b/.github/workflows/array-api-tests.yml index cbfe5a2..452b156 100644 --- a/.github/workflows/array-api-tests.yml +++ b/.github/workflows/array-api-tests.yml @@ -35,7 +35,7 @@ jobs: if [[ "${{ matrix.numpy-version }}" == "dev" ]]; then python -m pip install --pre --extra-index https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy; else - python -m pip install 'numpy==${{ matrix.numpy-version }}'; + python -m pip install 'numpy>=${{ matrix.numpy-version }},<${{ matrix.numpy-version }}.99'; fi python -m pip install ${GITHUB_WORKSPACE}/array-api-strict python -m pip install -r ${GITHUB_WORKSPACE}/array-api-tests/requirements.txt diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 312f9cd..e88b5ac 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: if [[ "${{ matrix.numpy-version }}" == "dev" ]]; then python -m pip install --pre --extra-index https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy; else - python -m pip install 'numpy==${{ matrix.numpy-version }}'; + python -m pip install 'numpy>=${{ matrix.numpy-version }},<${{ matrix.numpy-version }}.99'; fi python -m pip install -r requirements-dev.txt - name: Run Tests From 54ce945f772ffbf773af59bd957cc7c920409bfd Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Thu, 7 Nov 2024 17:56:18 -0700 Subject: [PATCH 3/3] NumPy 2.1 requires Python >= 3.10 --- .github/workflows/array-api-tests.yml | 2 +- .github/workflows/tests.yml | 2 +- setup.py | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/array-api-tests.yml b/.github/workflows/array-api-tests.yml index 452b156..4386cde 100644 --- a/.github/workflows/array-api-tests.yml +++ b/.github/workflows/array-api-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.9', '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] numpy-version: ['2.1', 'dev'] steps: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e88b5ac..a03c045 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.9', '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] numpy-version: ['2.1', 'dev'] fail-fast: true steps: diff --git a/setup.py b/setup.py index 21d7417..89e85e5 100644 --- a/setup.py +++ b/setup.py @@ -15,14 +15,15 @@ long_description_content_type="text/markdown", url="https://data-apis.org/array-api-strict/", license="MIT", - python_requires=">=3.9", + python_requires=">=3.10", install_requires=["numpy>=2.1"], classifiers=[ "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", ],