diff --git a/asv_bench/benchmarks/indexing.py b/asv_bench/benchmarks/indexing.py index cd212895d99..c4cfbbbdfdf 100644 --- a/asv_bench/benchmarks/indexing.py +++ b/asv_bench/benchmarks/indexing.py @@ -125,3 +125,16 @@ def setup(self, key): requires_dask() super().setup(key) self.ds = self.ds.chunk({"x": 100, "y": 50, "t": 50}) + + +class BooleanIndexing: + # https://github.com/pydata/xarray/issues/2227 + def setup(self): + self.ds = xr.Dataset( + {"a": ("time", np.arange(10_000_000))}, + coords={"time": np.arange(10_000_000)}, + ) + self.time_filter = self.ds.time > 50_000 + + def time_indexing(self): + self.ds.isel(time=self.time_filter) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 1268f7f3982..e460e1e230c 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -24,6 +24,13 @@ New functions/methods - Added :py:func:`~xarray.map_blocks`, modeled after :py:func:`dask.array.map_blocks` By `Deepak Cherian `_. +Bug fixes +~~~~~~~~~ +- Reintroduce support for :mod:`weakref` (broken in v0.13.0). Support has been + reinstated for :class:`DataArray` and :class:`Dataset` objects only. Internal xarray + objects remain unaddressable by weakref in order to save memory. + (:issue:`3317`) by `Guido Imperiale `_. + .. _whats-new.0.13.0: @@ -32,7 +39,7 @@ v0.13.0 (17 Sep 2019) This release includes many exciting changes: wrapping of `NEP18 `_ compliant -numpy-like arrays; new :py:meth:`~Dataset.plot.scatter` method that can scatter +numpy-like arrays; new :py:meth:`~Dataset.plot.scatter` plotting method that can scatter two ``DataArrays`` in a ``Dataset`` against each other; support for converting pandas DataFrames to xarray objects that wrap ``pydata/sparse``; and more! diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 21643694d5b..690b73d12b3 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -248,7 +248,15 @@ class DataArray(AbstractArray, DataWithCoords): Dictionary for holding arbitrary metadata. """ - __slots__ = ("_accessors", "_coords", "_file_obj", "_name", "_indexes", "_variable") + __slots__ = ( + "_accessors", + "_coords", + "_file_obj", + "_name", + "_indexes", + "_variable", + "__weakref__", + ) _groupby_cls = groupby.DataArrayGroupBy _rolling_cls = rolling.DataArrayRolling diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index eaffb5b7387..25ea2a873e9 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -420,6 +420,7 @@ class Dataset(Mapping, ImplementsDatasetReduce, DataWithCoords): "_file_obj", "_indexes", "_variables", + "__weakref__", ) _groupby_cls = groupby.DatasetGroupBy @@ -1783,7 +1784,7 @@ def _validate_indexers( elif isinstance(v, Dataset): raise TypeError("cannot use a Dataset as an indexer") elif isinstance(v, Sequence) and len(v) == 0: - v = IndexVariable((k,), np.zeros((0,), dtype="int64")) + v = Variable((k,), np.zeros((0,), dtype="int64")) else: v = np.asarray(v) @@ -1797,16 +1798,13 @@ def _validate_indexers( if v.ndim == 0: v = Variable((), v) elif v.ndim == 1: - v = IndexVariable((k,), v) + v = Variable((k,), v) else: raise IndexError( "Unlabeled multi-dimensional array cannot be " "used for indexing: {}".format(k) ) - if v.ndim == 1: - v = v.to_index_variable() - indexers_list.append((k, v)) return indexers_list @@ -2369,7 +2367,10 @@ def interp( if kwargs is None: kwargs = {} coords = either_dict_or_kwargs(coords, coords_kwargs, "interp") - indexers = OrderedDict(self._validate_indexers(coords)) + indexers = OrderedDict( + (k, v.to_index_variable() if isinstance(v, Variable) and v.ndim == 1 else v) + for k, v in self._validate_indexers(coords) + ) obj = self if assume_sorted else self.sortby([k for k in coords]) diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 01e92bdd7be..9ba3eecc5a0 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -4672,3 +4672,14 @@ class MyArray(DataArray): pass assert str(e.value) == "MyArray must explicitly define __slots__" + + +def test_weakref(): + """Classes with __slots__ are incompatible with the weakref module unless they + explicitly state __weakref__ among their slots + """ + from weakref import ref + + a = DataArray(1) + r = ref(a) + assert r() is a diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 7d2b11d02c9..f02990a1be9 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -5786,3 +5786,14 @@ class MyDS(Dataset): pass assert str(e.value) == "MyDS must explicitly define __slots__" + + +def test_weakref(): + """Classes with __slots__ are incompatible with the weakref module unless they + explicitly state __weakref__ among their slots + """ + from weakref import ref + + ds = Dataset() + r = ref(ds) + assert r() is ds