3
3
import enum
4
4
import functools
5
5
import operator
6
- import warnings
7
6
from collections import Counter , defaultdict
8
7
from collections .abc import Callable , Hashable , Iterable , Mapping
9
8
from contextlib import suppress
23
22
from xarray .core .utils import (
24
23
NDArrayMixin ,
25
24
either_dict_or_kwargs ,
25
+ emit_user_level_warning ,
26
26
get_valid_numpy_dtype ,
27
27
is_duck_array ,
28
28
is_duck_dask_array ,
@@ -609,7 +609,7 @@ def __getitem__(self, key) -> Any:
609
609
BackendArray_fallback_warning_message = (
610
610
"The array `{0}` does not support indexing using the .vindex and .oindex properties. "
611
611
"The __getitem__ method is being used instead. This fallback behavior will be "
612
- "removed in a future version. Please ensure that the backend array `{1 }` implements "
612
+ "removed in a future version. Please ensure that the backend array `{0 }` implements "
613
613
"support for the .vindex and .oindex properties to avoid potential issues."
614
614
)
615
615
@@ -671,21 +671,8 @@ def shape(self) -> _Shape:
671
671
return self ._shape
672
672
673
673
def get_duck_array (self ) -> Any :
674
- try :
675
- array = apply_indexer (self .array , self .key )
676
- except NotImplementedError as _ :
677
- # If the array is not an ExplicitlyIndexedNDArrayMixin,
678
- # it may wrap a BackendArray subclass that doesn't implement .oindex and .vindex. so use its __getitem__
679
- warnings .warn (
680
- BackendArray_fallback_warning_message .format (
681
- self .array .__class__ .__name__ , self .array .__class__ .__name__
682
- ),
683
- category = DeprecationWarning ,
684
- stacklevel = 2 ,
685
- )
686
- array = self .array [self .key ]
687
-
688
- # self.array[self.key] is now a numpy array when
674
+ array = apply_indexer (self .array , self .key )
675
+ # array[self.key] is now a numpy array when
689
676
# self.array is a BackendArray subclass
690
677
# and self.key is BasicIndexer((slice(None, None, None),))
691
678
# so we need the explicit check for ExplicitlyIndexed
@@ -752,21 +739,9 @@ def shape(self) -> _Shape:
752
739
return np .broadcast (* self .key .tuple ).shape
753
740
754
741
def get_duck_array (self ) -> Any :
755
- try :
756
- array = apply_indexer (self .array , self .key )
757
- except NotImplementedError as _ :
758
- # If the array is not an ExplicitlyIndexedNDArrayMixin,
759
- # it may wrap a BackendArray subclass that doesn't implement .oindex and .vindex. so use its __getitem__
760
- warnings .warn (
761
- BackendArray_fallback_warning_message .format (
762
- self .array .__class__ .__name__ , self .array .__class__ .__name__
763
- ),
764
- category = PendingDeprecationWarning ,
765
- stacklevel = 2 ,
766
- )
767
- array = self .array [self .key ]
742
+ array = apply_indexer (self .array , self .key )
768
743
769
- # self. array[self.key] is now a numpy array when
744
+ # array is now a numpy array when
770
745
# self.array is a BackendArray subclass
771
746
# and self.key is BasicIndexer((slice(None, None, None),))
772
747
# so we need the explicit check for ExplicitlyIndexed
@@ -1136,6 +1111,7 @@ def vectorized_indexing_adapter(
1136
1111
)
1137
1112
1138
1113
1114
+ # TODO: deprecate and delete this method once it is no longer used externally
1139
1115
def explicit_indexing_adapter (
1140
1116
key : ExplicitIndexer ,
1141
1117
shape : _Shape ,
@@ -1163,26 +1139,36 @@ def explicit_indexing_adapter(
1163
1139
-------
1164
1140
Indexing result, in the form of a duck numpy-array.
1165
1141
"""
1166
- # TODO: raise PendingDeprecationWarning here.
1167
- if isinstance (key , VectorizedIndexer ):
1168
- return vectorized_indexing_adapter (
1169
- key .tuple , shape , indexing_support , raw_indexing_method
1170
- )
1171
- elif isinstance (key , OuterIndexer ):
1172
- return outer_indexing_adapter (
1173
- key .tuple , shape , indexing_support , raw_indexing_method
1174
- )
1175
- elif isinstance (key , BasicIndexer ):
1176
- return basic_indexing_adapter (
1177
- key .tuple , shape , indexing_support , raw_indexing_method
1178
- )
1179
- raise TypeError (f"unexpected key type: { key } " )
1142
+
1143
+ # If the array is not an ExplicitlyIndexedNDArrayMixin,
1144
+ # it may wrap a BackendArray subclass that doesn't implement .oindex and .vindex. so use its __getitem__
1145
+ emit_user_level_warning (
1146
+ BackendArray_fallback_warning_message .format ("" ),
1147
+ category = PendingDeprecationWarning ,
1148
+ )
1149
+ raw_key , numpy_indices = decompose_indexer (key , shape , indexing_support )
1150
+ result = raw_indexing_method (raw_key .tuple )
1151
+ if numpy_indices .tuple :
1152
+ indexable = NumpyIndexingAdapter (result )
1153
+ result = apply_indexer (indexable , numpy_indices )
1154
+ return result
1180
1155
1181
1156
1182
1157
def apply_indexer (
1183
1158
indexable : ExplicitlyIndexedNDArrayMixin , indexer : ExplicitIndexer
1184
1159
) -> Any :
1185
1160
"""Apply an indexer to an indexable object."""
1161
+ if not hasattr (indexable , "vindex" ) and not hasattr (indexable , "oindex" ):
1162
+ # This path is used by Lazily*IndexedArray.get_duck_array()
1163
+ classname = type (indexable ).__name__
1164
+ # If the array is not an ExplicitlyIndexedNDArrayMixin,
1165
+ # it may wrap a BackendArray subclass that doesn't implement .oindex and .vindex. so use its __getitem__
1166
+ emit_user_level_warning (
1167
+ BackendArray_fallback_warning_message .format (classname ),
1168
+ category = PendingDeprecationWarning ,
1169
+ )
1170
+ return indexable [indexer ]
1171
+
1186
1172
if isinstance (indexer , VectorizedIndexer ):
1187
1173
return indexable .vindex [indexer .tuple ]
1188
1174
elif isinstance (indexer , OuterIndexer ):
@@ -1206,6 +1192,7 @@ def set_with_indexer(indexable, indexer: ExplicitIndexer, value: Any) -> None:
1206
1192
indexable [indexer .tuple ] = value
1207
1193
1208
1194
1195
+ # TODO: delete this method once explicit_indexing_adapter is no longer used externally
1209
1196
def decompose_indexer (
1210
1197
indexer : ExplicitIndexer , shape : _Shape , indexing_support : IndexingSupport
1211
1198
) -> tuple [ExplicitIndexer , ExplicitIndexer ]:
0 commit comments