From a2d2b4fbbe462b52fcb749473171fc77ad6e7d5f Mon Sep 17 00:00:00 2001 From: Giacomo Caria Date: Wed, 13 Aug 2025 11:08:10 -0400 Subject: [PATCH 1/7] add check for bool type --- xarray/core/dataarray.py | 1 - xarray/core/dataset.py | 9 ++------- xarray/core/indexing.py | 12 ++++-------- xarray/core/variable.py | 6 +++++- xarray/namedarray/utils.py | 2 +- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 98979ce05d7..8e446ca7d7e 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -1516,7 +1516,6 @@ def isel( """ indexers = either_dict_or_kwargs(indexers, indexers_kwargs, "isel") - if any(is_fancy_indexer(idx) for idx in indexers.values()): ds = self._to_temp_dataset()._isel_fancy( indexers, drop=drop, missing_dims=missing_dims diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 0b1d9835cf5..abe2752570a 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -34,12 +34,7 @@ from xarray.computation import ops from xarray.computation.arithmetic import DatasetArithmetic from xarray.core import dtypes as xrdtypes -from xarray.core import ( - duck_array_ops, - formatting, - formatting_html, - utils, -) +from xarray.core import duck_array_ops, formatting, formatting_html, utils from xarray.core._aggregations import DatasetAggregations from xarray.core.common import ( DataWithCoords, @@ -2563,7 +2558,7 @@ def _validate_indexers( # all indexers should be int, slice, np.ndarrays, or Variable for k, v in indexers.items(): - if isinstance(v, int | slice | Variable): + if isinstance(v, int | slice | Variable) and not isinstance(v, bool): yield k, v elif isinstance(v, DataArray): yield k, v.variable diff --git a/xarray/core/indexing.py b/xarray/core/indexing.py index c98175578f8..84c7ab9909d 100644 --- a/xarray/core/indexing.py +++ b/xarray/core/indexing.py @@ -430,7 +430,7 @@ def __init__( new_key = [] for k in key: - if isinstance(k, integer_types): + if isinstance(k, integer_types) and not isinstance(k, bool): k = int(k) elif isinstance(k, slice): k = as_integer_slice(k) @@ -447,7 +447,7 @@ def __init__( k = duck_array_ops.astype(k, np.int64, copy=False) else: raise TypeError( - f"unexpected indexer type for {type(self).__name__}: {k!r}" + f"unexpected indexer type for {type(self).__name__}: {k!r}, {type(k)}" ) new_key.append(k) @@ -1518,7 +1518,7 @@ def is_fancy_indexer(indexer: Any) -> bool: """Return False if indexer is a int, slice, a 1-dimensional list, or a 0 or 1-dimensional ndarray; in all other cases return True """ - if isinstance(indexer, int | slice): + if isinstance(indexer, int | slice) and not isinstance(indexer, bool): return False if isinstance(indexer, np.ndarray): return indexer.ndim > 1 @@ -1650,11 +1650,7 @@ def transpose(self, order): def _apply_vectorized_indexer_dask_wrapper(indices, coord): - from xarray.core.indexing import ( - VectorizedIndexer, - apply_indexer, - as_indexable, - ) + from xarray.core.indexing import VectorizedIndexer, apply_indexer, as_indexable return apply_indexer( as_indexable(coord), VectorizedIndexer((indices.squeeze(axis=-1),)) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 06d7218fe7c..c9ec3ac0c9c 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -633,6 +633,7 @@ def _broadcast_indexes(self, key): the first len(new_order) indexing should be moved to these positions. """ + print(key) key = self._item_key_to_tuple(key) # key is a tuple # key is a tuple of full size key = indexing.expanded_indexer(key, self.ndim) @@ -646,7 +647,10 @@ def _broadcast_indexes(self, key): k.item() if isinstance(k, np.ndarray) and k.ndim == 0 else k for k in key ) - if all(isinstance(k, BASIC_INDEXING_TYPES) for k in key): + if all( + (isinstance(k, BASIC_INDEXING_TYPES) and not isinstance(k, bool)) + for k in key + ): return self._broadcast_indexes_basic(key) self._validate_indexers(key) diff --git a/xarray/namedarray/utils.py b/xarray/namedarray/utils.py index 96060730345..c7cdfc47ab4 100644 --- a/xarray/namedarray/utils.py +++ b/xarray/namedarray/utils.py @@ -183,7 +183,7 @@ def either_dict_or_kwargs( ) -> Mapping[Hashable, T]: if pos_kwargs is None or pos_kwargs == {}: # Need an explicit cast to appease mypy due to invariance; see - # https://github.com/python/mypy/issues/6228 + # https://github.com/python/mypy/issues/Users/gcaria/repositories/xarray/xarray/core/dataarray.py/6228 return cast(Mapping[Hashable, T], kw_kwargs) if not is_dict_like(pos_kwargs): From 3f46ec62e506d5a5a7878e2822f443db41c70f6b Mon Sep 17 00:00:00 2001 From: Giacomo Caria Date: Wed, 13 Aug 2025 11:11:37 -0400 Subject: [PATCH 2/7] clean up --- xarray/core/variable.py | 1 - xarray/namedarray/utils.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index c9ec3ac0c9c..4db024ef3a4 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -633,7 +633,6 @@ def _broadcast_indexes(self, key): the first len(new_order) indexing should be moved to these positions. """ - print(key) key = self._item_key_to_tuple(key) # key is a tuple # key is a tuple of full size key = indexing.expanded_indexer(key, self.ndim) diff --git a/xarray/namedarray/utils.py b/xarray/namedarray/utils.py index c7cdfc47ab4..96060730345 100644 --- a/xarray/namedarray/utils.py +++ b/xarray/namedarray/utils.py @@ -183,7 +183,7 @@ def either_dict_or_kwargs( ) -> Mapping[Hashable, T]: if pos_kwargs is None or pos_kwargs == {}: # Need an explicit cast to appease mypy due to invariance; see - # https://github.com/python/mypy/issues/Users/gcaria/repositories/xarray/xarray/core/dataarray.py/6228 + # https://github.com/python/mypy/issues/6228 return cast(Mapping[Hashable, T], kw_kwargs) if not is_dict_like(pos_kwargs): From aabee3c5e0672045da9ec7533e62134d904ccca0 Mon Sep 17 00:00:00 2001 From: Giacomo Caria Date: Wed, 13 Aug 2025 11:12:37 -0400 Subject: [PATCH 3/7] clean up --- xarray/core/dataarray.py | 1 + 1 file changed, 1 insertion(+) diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 8e446ca7d7e..98979ce05d7 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -1516,6 +1516,7 @@ def isel( """ indexers = either_dict_or_kwargs(indexers, indexers_kwargs, "isel") + if any(is_fancy_indexer(idx) for idx in indexers.values()): ds = self._to_temp_dataset()._isel_fancy( indexers, drop=drop, missing_dims=missing_dims From c613862f1514b6689e85da76e8a9ee86ce7bce85 Mon Sep 17 00:00:00 2001 From: Giacomo Caria Date: Wed, 13 Aug 2025 11:18:32 -0400 Subject: [PATCH 4/7] add test --- xarray/tests/test_indexing.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xarray/tests/test_indexing.py b/xarray/tests/test_indexing.py index db4f6aaf0bd..1f16fa01f97 100644 --- a/xarray/tests/test_indexing.py +++ b/xarray/tests/test_indexing.py @@ -549,6 +549,8 @@ def test_invalid_for_all(indexer_cls) -> None: indexer_cls((slice("foo"),)) with pytest.raises(TypeError): indexer_cls((np.array(["foo"]),)) + with pytest.raises(TypeError): + indexer_cls(True) def check_integer(indexer_cls): From c369a0d23d1734b9ae3889a4a5f92b045cfc6472 Mon Sep 17 00:00:00 2001 From: Giacomo Caria Date: Wed, 13 Aug 2025 18:43:12 -0400 Subject: [PATCH 5/7] add test --- xarray/tests/test_indexing.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xarray/tests/test_indexing.py b/xarray/tests/test_indexing.py index 1f16fa01f97..0866ee85c9d 100644 --- a/xarray/tests/test_indexing.py +++ b/xarray/tests/test_indexing.py @@ -551,6 +551,8 @@ def test_invalid_for_all(indexer_cls) -> None: indexer_cls((np.array(["foo"]),)) with pytest.raises(TypeError): indexer_cls(True) + with pytest.raises(TypeError): + indexer_cls(np.array(True)) def check_integer(indexer_cls): From 7f0fbbee15fde9d4197c09fd832fd7f5b9d61e36 Mon Sep 17 00:00:00 2001 From: Giacomo Caria Date: Wed, 13 Aug 2025 19:12:07 -0400 Subject: [PATCH 6/7] add test --- xarray/tests/test_dataarray.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 71c11626e1e..55551b975c1 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -34,11 +34,7 @@ from xarray.core import dtypes from xarray.core.common import full_like from xarray.core.coordinates import Coordinates, CoordinateValidationError -from xarray.core.indexes import ( - Index, - PandasIndex, - filter_indexes_from_coords, -) +from xarray.core.indexes import Index, PandasIndex, filter_indexes_from_coords from xarray.core.types import QueryEngineOptions, QueryParserOptions from xarray.core.utils import is_scalar from xarray.testing import _assert_internal_invariants @@ -749,6 +745,14 @@ def test_getitem_empty_index(self) -> None: ) assert_identical(da[[]], DataArray(np.zeros((0, 4)), dims=["x", "y"])) + def test_getitem_typeerror(self) -> None: + with pytest.raises(TypeError, match=r"unexpected indexer type"): + self.dv[True] + with pytest.raises(TypeError, match=r"invalid indexer array"): + self.dv[3.0] + with pytest.raises(TypeError, match=r"invalid indexer array"): + self.dv[None] + def test_setitem(self) -> None: # basic indexing should work as numpy's indexing tuples: list[tuple[int | list[int] | slice, int | list[int] | slice]] = [ From ad18e2e191f436660286593a3c756c8c8cabb41f Mon Sep 17 00:00:00 2001 From: Giacomo Caria Date: Wed, 13 Aug 2025 19:14:44 -0400 Subject: [PATCH 7/7] add test --- xarray/tests/test_dataarray.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 55551b975c1..21575e34be9 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -748,6 +748,8 @@ def test_getitem_empty_index(self) -> None: def test_getitem_typeerror(self) -> None: with pytest.raises(TypeError, match=r"unexpected indexer type"): self.dv[True] + with pytest.raises(TypeError, match=r"unexpected indexer type"): + self.dv[np.array(True)] with pytest.raises(TypeError, match=r"invalid indexer array"): self.dv[3.0] with pytest.raises(TypeError, match=r"invalid indexer array"):