From 5845809d82d9f4895954a871e27c9b2e39acd79e Mon Sep 17 00:00:00 2001 From: Bryn Pickering <17178478+brynpickering@users.noreply.github.com> Date: Tue, 20 May 2025 15:50:48 +0100 Subject: [PATCH 1/3] Coerce unknown types to O dtype --- xarray/compat/array_api_compat.py | 13 +++++++++---- xarray/tests/test_dtypes.py | 4 ++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/xarray/compat/array_api_compat.py b/xarray/compat/array_api_compat.py index e1e5d5c5bdc..1b6c440cc7a 100644 --- a/xarray/compat/array_api_compat.py +++ b/xarray/compat/array_api_compat.py @@ -38,10 +38,15 @@ def _future_array_api_result_type(*arrays_and_dtypes, xp): def result_type(*arrays_and_dtypes, xp) -> np.dtype: - if xp is np or any( - isinstance(getattr(t, "dtype", t), np.dtype) for t in arrays_and_dtypes - ): - return xp.result_type(*arrays_and_dtypes) + is_np_dtype = [ + hasattr(t, "dtype") and isinstance(t.dtype, np.dtype) for t in arrays_and_dtypes + ] + if xp is np or any(is_np_dtype): + all_valid_arrays_and_dtypes = [ + t if is_np_dtype[i] or t.__class__.__module__ == "builtins" else np.object_ + for i, t in enumerate(arrays_and_dtypes) + ] + return xp.result_type(*all_valid_arrays_and_dtypes) else: return _future_array_api_result_type(*arrays_and_dtypes, xp=xp) diff --git a/xarray/tests/test_dtypes.py b/xarray/tests/test_dtypes.py index 0ccda1d8074..9b76e7d431a 100644 --- a/xarray/tests/test_dtypes.py +++ b/xarray/tests/test_dtypes.py @@ -32,6 +32,10 @@ class DummyArrayAPINamespace: ([np.dtype(" None: From ef3df17dbf4c7e209a820cc3d9a54918a513d2a8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 14:57:50 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/tests/test_dtypes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xarray/tests/test_dtypes.py b/xarray/tests/test_dtypes.py index 9b76e7d431a..3b9c60517f9 100644 --- a/xarray/tests/test_dtypes.py +++ b/xarray/tests/test_dtypes.py @@ -32,10 +32,10 @@ class DummyArrayAPINamespace: ([np.dtype(" None: From 1756bc4ba9bb4a05f85b66de3ca07b2a3d7c129b Mon Sep 17 00:00:00 2001 From: Bryn Pickering <17178478+brynpickering@users.noreply.github.com> Date: Fri, 23 May 2025 14:34:39 +0100 Subject: [PATCH 3/3] Add comment on setting obj dtype --- xarray/compat/array_api_compat.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xarray/compat/array_api_compat.py b/xarray/compat/array_api_compat.py index 1b6c440cc7a..166a23ba2f8 100644 --- a/xarray/compat/array_api_compat.py +++ b/xarray/compat/array_api_compat.py @@ -42,6 +42,9 @@ def result_type(*arrays_and_dtypes, xp) -> np.dtype: hasattr(t, "dtype") and isinstance(t.dtype, np.dtype) for t in arrays_and_dtypes ] if xp is np or any(is_np_dtype): + # Numpy can only apply type promotion rules on non-builtin & numpy-compatible Python objects. + # So we convert any incompatible objects (e.g. user-defined class instances) stored in the array to numpy Object dtype. + # Then, numpy's type promotion will fall back to Object dtype rather than raising an exception. all_valid_arrays_and_dtypes = [ t if is_np_dtype[i] or t.__class__.__module__ == "builtins" else np.object_ for i, t in enumerate(arrays_and_dtypes)