From 0fa036639e78160bf4afd162acb08d818c841e9a Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 20 Jul 2026 10:03:59 +0100 Subject: [PATCH 1/6] Disable bottleneck by default --- xarray/core/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/options.py b/xarray/core/options.py index b43e4ff3b09..d7955025812 100644 --- a/xarray/core/options.py +++ b/xarray/core/options.py @@ -103,7 +103,7 @@ class T_Options(TypedDict): "keep_attrs": "default", "netcdf_engine_order": ("netcdf4", "h5netcdf", "scipy"), "warn_for_unclosed_files": False, - "use_bottleneck": True, + "use_bottleneck": False, "use_flox": True, "use_new_combine_kwarg_defaults": False, "use_numbagg": True, From 3383123cd0ae105fdfed4473547fb4391ee69eb4 Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 20 Jul 2026 10:07:29 +0100 Subject: [PATCH 2/6] Document disabling bottleneck --- doc/whats-new.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index f6618e060c7..e787fc00c75 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -30,6 +30,8 @@ Bug Fixes differ from the dtype returned by the matching numpy-backed bottleneck path, notably ``object`` instead of ``float64`` for boolean inputs. By `Matthew Rocklin `_. +- Disable using bottleneck by default, as certain operations are less numerically + stable than the equivalent numpy functions. Documentation From 34b16a6cf74356ef23d1d633b76154cc4271f77f Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 20 Jul 2026 10:45:49 +0100 Subject: [PATCH 3/6] Ignore use_bottleneck option for rank() method --- xarray/core/dataset.py | 8 +++----- xarray/core/variable.py | 7 ++----- xarray/tests/test_dataset.py | 6 ------ xarray/tests/test_variable.py | 6 ------ 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index d7c16e0b3c8..5806236c7b8 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -100,6 +100,7 @@ is_duck_dask_array, is_scalar, maybe_wrap_array, + module_available, parse_dims_as_set, ) from xarray.core.variable import ( @@ -8447,11 +8448,8 @@ def rank( ranked : Dataset Variables that do not depend on `dim` are dropped. """ - if not OPTIONS["use_bottleneck"]: - raise RuntimeError( - "rank requires bottleneck to be enabled." - " Call `xr.set_options(use_bottleneck=True)` to enable it." - ) + if not module_available("bottleneck"): + raise ImportError("rank requires bottleneck to be installed.") if dim not in self.dims: raise ValueError( diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 1b5e0d4ff69..1ea86254d35 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2093,11 +2093,8 @@ def rank(self, dim, pct=False): Dataset.rank, DataArray.rank """ # This could / should arguably be implemented at the DataArray & Dataset level - if not OPTIONS["use_bottleneck"]: - raise RuntimeError( - "rank requires bottleneck to be enabled." - " Call `xr.set_options(use_bottleneck=True)` to enable it." - ) + if not module_available("bottleneck"): + raise ImportError("rank requires bottleneck to be installed.") import bottleneck as bn diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index d1934ebbaa5..a7178bba512 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -6518,12 +6518,6 @@ def test_rank(self) -> None: ): x.rank("invalid_dim") - def test_rank_use_bottleneck(self) -> None: - ds = Dataset({"a": ("x", [0, np.nan, 2]), "b": ("y", [4, 6, 3, 4])}) - with xr.set_options(use_bottleneck=False): - with pytest.raises(RuntimeError): - ds.rank("x") - def test_count(self) -> None: ds = Dataset({"x": ("a", [np.nan, 1]), "y": 0, "z": np.nan}) expected = Dataset({"x": 1, "y": 1, "z": 0}) diff --git a/xarray/tests/test_variable.py b/xarray/tests/test_variable.py index b493d943bb2..c2bc73f70b9 100644 --- a/xarray/tests/test_variable.py +++ b/xarray/tests/test_variable.py @@ -2018,12 +2018,6 @@ def test_rank_dask(self): ): v.rank("x") - def test_rank_use_bottleneck(self): - v = Variable(["x"], [3.0, 1.0, np.nan, 2.0, 4.0]) - with set_options(use_bottleneck=False): - with pytest.raises(RuntimeError): - v.rank("x") - @requires_bottleneck def test_rank(self): import bottleneck as bn From 8fe6daed5942ae4e9534e2cb9b5b8960d13b886c Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 20 Jul 2026 11:36:35 +0100 Subject: [PATCH 4/6] Re-enable bottleneck for rolling tests --- xarray/tests/test_rolling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/tests/test_rolling.py b/xarray/tests/test_rolling.py index 05f65d24507..26068cdb098 100644 --- a/xarray/tests/test_rolling.py +++ b/xarray/tests/test_rolling.py @@ -460,7 +460,7 @@ def test_rolling_bottleneck_dask_dtype_matches_numpy( .rolling(t=72, min_periods=72, center=center) ) - with set_options(use_numbagg=False): + with set_options(use_numbagg=False, use_bottleneck=True): expected = getattr(unchunked, name)() actual = getattr(chunked, name)() actual_block = actual.data.blocks[0, 0].compute() From 0235c957578bdfaf7ad5ef78e09d0eafd98ae021 Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 20 Jul 2026 11:37:12 +0100 Subject: [PATCH 5/6] Add name to release note Co-authored-by: Justus Magin --- doc/whats-new.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index e787fc00c75..35ba95c81fb 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -32,6 +32,7 @@ Bug Fixes By `Matthew Rocklin `_. - Disable using bottleneck by default, as certain operations are less numerically stable than the equivalent numpy functions. + By `Thomas Kluyver `_. Documentation From 8b45624a2bf8787bd055b1bc67a90932766099c0 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Mon, 27 Jul 2026 21:55:43 +0200 Subject: [PATCH 6/6] move to breaking changes [skip-ci] (since technically this is changing the trade-off between speed and accuracy) --- doc/whats-new.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 35ba95c81fb..880dea3381a 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -17,7 +17,9 @@ New Features Breaking Changes ~~~~~~~~~~~~~~~~ - +- Disable using bottleneck by default, as certain operations are less numerically + stable than the equivalent numpy functions. + By `Thomas Kluyver `_. Deprecations ~~~~~~~~~~~~ @@ -30,9 +32,6 @@ Bug Fixes differ from the dtype returned by the matching numpy-backed bottleneck path, notably ``object`` instead of ``float64`` for boolean inputs. By `Matthew Rocklin `_. -- Disable using bottleneck by default, as certain operations are less numerically - stable than the equivalent numpy functions. - By `Thomas Kluyver `_. Documentation