Skip to content

Commit c2e5acd

Browse files
committed
Clean up backend indexing
1 parent 02f61da commit c2e5acd

File tree

5 files changed

+28
-20
lines changed

5 files changed

+28
-20
lines changed

xarray/backends/memory.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import numpy as np
66

77
from xarray.backends.common import AbstractWritableDataStore
8+
from xarray.core import indexing
89
from xarray.core.variable import Variable
910

1011

@@ -24,7 +25,12 @@ def get_attrs(self):
2425
return self._attributes
2526

2627
def get_variables(self):
27-
return self._variables
28+
res = {}
29+
for k, v in self._variables.items():
30+
v = v.copy(deep=True)
31+
res[k] = v
32+
v._data = indexing.LazilyIndexedArray(v._data)
33+
return res
2834

2935
def get_dimensions(self):
3036
return {d: s for v in self._variables.values() for d, s in v.dims.items()}

xarray/backends/scipy_.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def ds(self):
190190
def open_store_variable(self, name, var):
191191
return Variable(
192192
var.dimensions,
193-
ScipyArrayWrapper(name, self),
193+
indexing.LazilyIndexedArray(ScipyArrayWrapper(name, self)),
194194
_decode_attrs(var._attributes),
195195
)
196196

xarray/conventions.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
)
1919
from xarray.core.utils import emit_user_level_warning
2020
from xarray.core.variable import IndexVariable, Variable
21-
from xarray.namedarray.utils import is_duck_dask_array
21+
from xarray.namedarray.utils import is_duck_array
2222

2323
CF_RELATED_DATA = (
2424
"bounds",
@@ -249,7 +249,20 @@ def decode_cf_variable(
249249

250250
encoding.setdefault("dtype", original_dtype)
251251

252-
if not is_duck_dask_array(data):
252+
if (
253+
# we don't need to lazily index duck arrays
254+
not is_duck_array(data)
255+
# These arrays already support lazy indexing
256+
# OR for IndexingAdapters, it makes no sense to wrap them
257+
and not isinstance(data, indexing.ExplicitlyIndexedNDArrayMixin)
258+
):
259+
# this path applies to bare BackendArray objects.
260+
# It is not hit for any internal Xarray backend
261+
emit_user_level_warning(
262+
"The backend you are using has not explicitly supported lazy indexing with Xarray. "
263+
"Please ask the backend developers to support lazy loading by wrapping with LazilyIndexedArray. "
264+
"See https://docs.xarray.dev/en/stable/internals/how-to-add-new-backend.html#how-to-support-lazy-loading for more."
265+
)
253266
data = indexing.LazilyIndexedArray(data)
254267

255268
return Variable(dimensions, data, attributes, encoding=encoding, fastpath=True)

xarray/core/indexes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ def from_variables(
717717

718718
# preserve wrapped pd.Index (if any)
719719
# accessing `.data` can load data from disk, so we only access if needed
720-
data = var._data.array if hasattr(var._data, "array") else var.data
720+
data = var._data if isinstance(var._data, PandasIndexingAdapter) else var.data
721721
# multi-index level variable: get level index
722722
if isinstance(var._data, PandasMultiIndexingAdapter):
723723
level = var._data.level

xarray/core/indexing.py

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -658,17 +658,11 @@ def shape(self) -> _Shape:
658658
def get_duck_array(self):
659659
if isinstance(self.array, ExplicitlyIndexedNDArrayMixin):
660660
array = apply_indexer(self.array, self.key)
661+
array = array.get_duck_array()
661662
else:
662663
# If the array is not an ExplicitlyIndexedNDArrayMixin,
663-
# it may wrap a BackendArray so use its __getitem__
664+
# it is a BackendArray so use its __getitem__
664665
array = self.array[self.key]
665-
666-
# self.array[self.key] is now a numpy array when
667-
# self.array is a BackendArray subclass
668-
# and self.key is BasicIndexer((slice(None, None, None),))
669-
# so we need the explicit check for ExplicitlyIndexed
670-
if isinstance(array, ExplicitlyIndexed):
671-
array = array.get_duck_array()
672666
return _wrap_numpy_scalars(array)
673667

674668
def transpose(self, order):
@@ -734,16 +728,11 @@ def shape(self) -> _Shape:
734728
def get_duck_array(self):
735729
if isinstance(self.array, ExplicitlyIndexedNDArrayMixin):
736730
array = apply_indexer(self.array, self.key)
731+
array = array.get_duck_array()
737732
else:
738733
# If the array is not an ExplicitlyIndexedNDArrayMixin,
739-
# it may wrap a BackendArray so use its __getitem__
734+
# it is a BackendArray so use its __getitem__
740735
array = self.array[self.key]
741-
# self.array[self.key] is now a numpy array when
742-
# self.array is a BackendArray subclass
743-
# and self.key is BasicIndexer((slice(None, None, None),))
744-
# so we need the explicit check for ExplicitlyIndexed
745-
if isinstance(array, ExplicitlyIndexed):
746-
array = array.get_duck_array()
747736
return _wrap_numpy_scalars(array)
748737

749738
def _updated_key(self, new_key: ExplicitIndexer):

0 commit comments

Comments
 (0)