From c43f3565e647275df005858e7f1e7c75cb92f4a8 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Fri, 10 Jul 2026 13:26:28 +0200 Subject: [PATCH 1/4] Revert "raise if (device_type, device_id) is not found in the DLPack mappings" This reverts commit a15c7bc6f930fa16cc909d6384d437579b6311fc. --- array_api_strict/_devices.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/array_api_strict/_devices.py b/array_api_strict/_devices.py index c48db2a..8541632 100644 --- a/array_api_strict/_devices.py +++ b/array_api_strict/_devices.py @@ -62,8 +62,9 @@ def _normalize_dl_device(device_type: IntEnum | int, device_id: int) -> tuple[in def _device_from_dlpack_device( device_type: IntEnum | int, device_id: int ) -> Device: - # NB: if the (device_type, device_id) pair not known, raise - return _DLPACK_DEVICE_TO_LOGICAL[_normalize_dl_device(device_type, device_id)] + return _DLPACK_DEVICE_TO_LOGICAL.get( + _normalize_dl_device(device_type, device_id), CPU_DEVICE + ) def check_device(device: Device | None) -> None: From 1c9e47cfe763d75db2b8e284be606adc2bef5284 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Fri, 10 Jul 2026 13:27:54 +0200 Subject: [PATCH 2/4] Revert "add dlpack_device dunder to the F32_device" This reverts commit dbe38b85178bb62c6b21ea2377f1424d8a9f1c7d. --- array_api_strict/_devices.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/array_api_strict/_devices.py b/array_api_strict/_devices.py index 8541632..dbf2e6e 100644 --- a/array_api_strict/_devices.py +++ b/array_api_strict/_devices.py @@ -39,14 +39,12 @@ def __hash__(self) -> int: class DLDeviceType(IntEnum): kDLCPU = 1 kDLCUDA = 2 - kDLMETAL = 8 _DLPACK_DEVICE_FOR: Final[dict[Device, tuple[DLDeviceType, int]]] = { CPU_DEVICE: (DLDeviceType.kDLCPU, 0), Device("device1"): (DLDeviceType.kDLCUDA, 0), Device("device2"): (DLDeviceType.kDLCUDA, 1), - NO_FLOAT64_DEVICE: (DLDeviceType.kDLMETAL, 0), } _DLPACK_DEVICE_TO_LOGICAL: Final[dict[tuple[int, int], Device]] = { From 1efbf5e7f42cfd45523443f21c348640dd23d870 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Fri, 10 Jul 2026 13:28:21 +0200 Subject: [PATCH 3/4] Revert "manually sync dlpack enum updates to _devices.py" This reverts commit 083212060b10d00fda24553937ae97d9e96e4062. --- array_api_strict/_devices.py | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/array_api_strict/_devices.py b/array_api_strict/_devices.py index dbf2e6e..19b43c5 100644 --- a/array_api_strict/_devices.py +++ b/array_api_strict/_devices.py @@ -1,5 +1,4 @@ from typing import Final -from enum import IntEnum from ._dtypes import ( DType, float32, float64, complex64, complex128, int64, @@ -36,34 +35,6 @@ def __hash__(self) -> int: ALL_DEVICES = (CPU_DEVICE, Device("device1"), Device("device2"), NO_FLOAT64_DEVICE) -class DLDeviceType(IntEnum): - kDLCPU = 1 - kDLCUDA = 2 - - -_DLPACK_DEVICE_FOR: Final[dict[Device, tuple[DLDeviceType, int]]] = { - CPU_DEVICE: (DLDeviceType.kDLCPU, 0), - Device("device1"): (DLDeviceType.kDLCUDA, 0), - Device("device2"): (DLDeviceType.kDLCUDA, 1), -} - -_DLPACK_DEVICE_TO_LOGICAL: Final[dict[tuple[int, int], Device]] = { - (int(device_type), device_id): logical_device - for logical_device, (device_type, device_id) in _DLPACK_DEVICE_FOR.items() -} - - -def _normalize_dl_device(device_type: IntEnum | int, device_id: int) -> tuple[int, int]: - return (int(device_type), device_id) - - -def _device_from_dlpack_device( - device_type: IntEnum | int, device_id: int -) -> Device: - return _DLPACK_DEVICE_TO_LOGICAL.get( - _normalize_dl_device(device_type, device_id), CPU_DEVICE - ) - def check_device(device: Device | None) -> None: if device is not None and not isinstance(device, Device): From 9490c92f3899a376cbdc86baf0d2e061d2ce3615 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Fri, 10 Jul 2026 13:35:24 +0200 Subject: [PATCH 4/4] Manually fixup reverting dlpack_device additions --- array_api_strict/_array_object.py | 39 +++++-------------- array_api_strict/_creation_functions.py | 5 +-- array_api_strict/tests/test_array_object.py | 35 +---------------- .../tests/test_creation_functions.py | 9 ----- 4 files changed, 11 insertions(+), 77 deletions(-) diff --git a/array_api_strict/_array_object.py b/array_api_strict/_array_object.py index 8420aee..b0689e1 100644 --- a/array_api_strict/_array_object.py +++ b/array_api_strict/_array_object.py @@ -40,10 +40,7 @@ _real_to_complex_map, _result_type, ) -from ._devices import ( - CPU_DEVICE, Device, device_supports_dtype, _normalize_dl_device, _DLPACK_DEVICE_FOR, - DLDeviceType -) +from ._devices import CPU_DEVICE, Device, device_supports_dtype from ._flags import get_array_api_strict_flags, set_array_api_strict_flags from ._typing import PyCapsule @@ -614,31 +611,12 @@ def __dlpack__( raise NotImplementedError("The copy argument to __dlpack__ is not yet implemented") return self._array.__dlpack__(stream=stream) - - kwargs: dict[str, Any] = {'stream': stream} - self_dl_device = _normalize_dl_device(*_DLPACK_DEVICE_FOR[self._device]) - cpu_dl_device = _normalize_dl_device(DLDeviceType.kDLCPU, 0) - numpy_dl_device: tuple[IntEnum, int] | None = None - - if dl_device not in [_undef, None]: - requested = _normalize_dl_device(dl_device[0], dl_device[1]) - if requested == self_dl_device: - pass - elif requested == cpu_dl_device and self_dl_device != cpu_dl_device: - if copy is False: - raise BufferError( - "Cannot export array to CPU without copying when copy=False" - ) - if copy is _undef: - copy = True - numpy_dl_device = (DLDeviceType.kDLCPU, 0) - else: - raise BufferError("unsupported device requested") - - if max_version is not _undef: - kwargs['max_version'] = max_version - if numpy_dl_device is not None: - kwargs['dl_device'] = numpy_dl_device + else: + kwargs = {'stream': stream} + if max_version is not _undef: + kwargs['max_version'] = max_version + if dl_device is not _undef: + kwargs['dl_device'] = dl_device if copy is not _undef: kwargs['copy'] = copy return self._array.__dlpack__(**kwargs) @@ -647,7 +625,8 @@ def __dlpack_device__(self) -> tuple[IntEnum, int]: """ Performs the operation __dlpack_device__. """ - return _DLPACK_DEVICE_FOR[self._device] + # Note: device support is required for this + return self._array.__dlpack_device__() def __eq__(self, other: Array | complex, /) -> Array: # type: ignore[override] """ diff --git a/array_api_strict/_creation_functions.py b/array_api_strict/_creation_functions.py index b34af5a..0f8fc51 100644 --- a/array_api_strict/_creation_functions.py +++ b/array_api_strict/_creation_functions.py @@ -242,15 +242,12 @@ def from_dlpack( if copy is not _undef: raise ValueError("The copy argument to from_dlpack requires at least version 2023.12 of the array API") + # Going to wait for upstream numpy support if device is not _undef: _check_device(device) else: device = None - if hasattr(x, "__dlpack_device__"): - from ._devices import _device_from_dlpack_device - dl_type, dl_id = x.__dlpack_device__() - device = _device_from_dlpack_device(dl_type, dl_id) if copy in [_undef, None]: # numpy 1.26 does not have the copy= arg return Array._new(np.from_dlpack(x), device=device) diff --git a/array_api_strict/tests/test_array_object.py b/array_api_strict/tests/test_array_object.py index a75d66f..445ee80 100644 --- a/array_api_strict/tests/test_array_object.py +++ b/array_api_strict/tests/test_array_object.py @@ -10,7 +10,7 @@ from .. import ones, arange, reshape, asarray, result_type, all, equal, stack from .._array_object import Array -from .._devices import CPU_DEVICE, Device, DLDeviceType +from .._devices import CPU_DEVICE, Device from .._dtypes import ( _all_dtypes, _boolean_dtypes, @@ -758,39 +758,6 @@ def test_dlpack_2023_12(api_version): a.__dlpack__(copy=True) a.__dlpack__(copy=None) -@pytest.mark.parametrize( - ("device", "expected"), - [ - (CPU_DEVICE, (DLDeviceType.kDLCPU, 0)), - (Device("device1"), (DLDeviceType.kDLCUDA, 0)), - (Device("device2"), (DLDeviceType.kDLCUDA, 1)), - ], -) -def test_dlpack_device_numbers(device, expected): - a = asarray([1, 2, 3], device=device) - assert a.__dlpack_device__() == expected - - -@pytest.mark.parametrize("device", [CPU_DEVICE, Device("device1"), Device("device2")]) -def test_dlpack_export_with_matching_dl_device(device): - if np.lib.NumpyVersion(np.__version__) < "2.1.0": - pytest.skip("dl_device argument requires NumPy >= 2.1.0") - set_array_api_strict_flags(api_version="2023.12") - - a = asarray([1, 2, 3], device=device) - a.__dlpack__(dl_device=a.__dlpack_device__()) - - -@pytest.mark.parametrize("device", [Device("device1"), Device("device2")]) -def test_dlpack_cross_device_export_buffer_error(device): - if np.lib.NumpyVersion(np.__version__) < "2.1.0": - pytest.skip("dl_device argument requires NumPy >= 2.1.0") - set_array_api_strict_flags(api_version="2023.12") - - a = asarray([1, 2, 3], device=device) - with pytest.raises(BufferError): - a.__dlpack__(dl_device=(DLDeviceType.kDLCPU, 0), copy=False) - def test_pickle(): """Check that arrays are pickleable (despite raising on `__new__`)""" diff --git a/array_api_strict/tests/test_creation_functions.py b/array_api_strict/tests/test_creation_functions.py index 7031120..35fcc4b 100644 --- a/array_api_strict/tests/test_creation_functions.py +++ b/array_api_strict/tests/test_creation_functions.py @@ -395,12 +395,3 @@ def test_from_dlpack_default_device(): z = from_dlpack(np.asarray([1, 2, 3])) assert x.device == y.device == z.device == CPU_DEVICE - -@pytest.mark.parametrize( - "device", - [Device("device1"), Device("device2")], -) -def test_from_dlpack_preserves_device(device): - x = asarray([1, 2, 3], device=device) - y = from_dlpack(x) - assert y.device == device