From e80cff5c9fe4c75eb6e641d698e998947225212f Mon Sep 17 00:00:00 2001 From: eschalk Date: Sun, 25 Feb 2024 14:07:38 +0100 Subject: [PATCH 01/14] increase plot size --- xarray/core/options.py | 3 +++ xarray/core/variable.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/xarray/core/options.py b/xarray/core/options.py index 18e3484e9c4..f5614104357 100644 --- a/xarray/core/options.py +++ b/xarray/core/options.py @@ -34,6 +34,7 @@ ] class T_Options(TypedDict): + arithmetic_broadcast: bool arithmetic_join: Literal["inner", "outer", "left", "right", "exact"] cmap_divergent: str | Colormap cmap_sequential: str | Colormap @@ -59,6 +60,7 @@ class T_Options(TypedDict): OPTIONS: T_Options = { + "arithmetic_broadcast": True, "arithmetic_join": "inner", "cmap_divergent": "RdBu_r", "cmap_sequential": "viridis", @@ -92,6 +94,7 @@ def _positive_integer(value: int) -> bool: _VALIDATORS = { + "arithmetic_broadcast": lambda value: isinstance(value, bool), "arithmetic_join": _JOIN_OPTIONS.__contains__, "display_max_rows": _positive_integer, "display_values_threshold": _positive_integer, diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 6834931fa11..d9b73b00cba 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2270,6 +2270,9 @@ def _unary_op(self, f, *args, **kwargs): def _binary_op(self, other, f, reflexive=False): if isinstance(other, (xr.DataArray, xr.Dataset)): return NotImplemented + + if not OPTIONS["arithmetic_broadcast"]: + raise ValueError("Arithmetic broadcast is disabled via global option") if reflexive and issubclass(type(self), type(other)): other_data, self_data, dims = _broadcast_compat_data(other, self) else: From 06400c3625a83e4de5b2d2d9a005937dccb4207a Mon Sep 17 00:00:00 2001 From: eschalk Date: Sun, 25 Feb 2024 14:13:12 +0100 Subject: [PATCH 02/14] added old tests --- xarray/tests/__init__.py | 7 +++ xarray/tests/test_dataarray.py | 104 ++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/xarray/tests/__init__.py b/xarray/tests/__init__.py index df0899509cb..2e6e638f5b1 100644 --- a/xarray/tests/__init__.py +++ b/xarray/tests/__init__.py @@ -89,6 +89,13 @@ def _importorskip( has_pynio, requires_pynio = _importorskip("Nio") has_cftime, requires_cftime = _importorskip("cftime") has_dask, requires_dask = _importorskip("dask") +with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + message="The current Dask DataFrame implementation is deprecated.", + category=DeprecationWarning, + ) + has_dask_expr, requires_dask_expr = _importorskip("dask_expr") has_bottleneck, requires_bottleneck = _importorskip("bottleneck") has_rasterio, requires_rasterio = _importorskip("rasterio") has_zarr, requires_zarr = _importorskip("zarr") diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 2829fd7d49c..e8e3eb35784 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -50,7 +50,7 @@ raise_if_dask_computes, requires_bottleneck, requires_cupy, - requires_dask, + requires_dask,requires_dask_expr, requires_iris, requires_numexpr, requires_pint, @@ -3203,6 +3203,106 @@ def test_align_str_dtype(self) -> None: assert_identical(expected_b, actual_b) assert expected_b.x.dtype == actual_b.x.dtype + + @pytest.mark.parametrize("broadcast", [True, False]) + def test_broadcast_on_vs_off_same_dim_same_size(self, broadcast: bool) -> None: + xda = xr.DataArray([1], dims="x") + + aligned_1, aligned_2 = xr.align(xda, xda, join="exact", broadcast=broadcast) + assert_identical(aligned_1, xda) + assert_identical(aligned_2, xda) + + @pytest.mark.parametrize("broadcast", [True, False]) + def test_broadcast_on_vs_off_same_dim_differing_sizes(self: bool) -> None: + xda_1 = xr.DataArray([1], dims="x") + xda_2 = xr.DataArray([1, 2], dims="x") + + with pytest.raises( + ValueError, + match=re.escape( + "cannot reindex or align along dimension 'x' because of " + "conflicting dimension sizes: {1, 2}" + ), + ): + xr.align(xda_1, xda_2, join="exact", broadcast=broadcast) + + def test_broadcast_on_vs_off_differing_dims_same_sizes(self) -> None: + xda_1 = xr.DataArray([1], dims="x1") + xda_2 = xr.DataArray([1], dims="x2") + + aligned_1, aligned_2 = xr.align(xda_1, xda_2, join="exact", broadcast=True) + assert_identical(aligned_1, xda_1) + assert_identical(aligned_2, xda_2) + + with pytest.raises( + ValueError, + match=re.escape( + "cannot align objects with broadcast=False " + "because given objects do not share the same dimension names " + "([('x1',), ('x2',)])" + ), + ): + xr.align(xda_1, xda_2, join="exact", broadcast=False) + + def test_broadcast_on_vs_off_global_option(self) -> None: + xda_1 = xr.DataArray([1], dims="x1") + xda_2 = xr.DataArray([1], dims="x2") + + with xr.set_options(arithmetic_broadcast=True): + expected_xda = xr.DataArray([[1.0]], dims=("x1", "x2")) + actual_xda = xda_1 / xda_2 + assert_identical(expected_xda, actual_xda) + + with xr.set_options(arithmetic_broadcast=False): + with pytest.raises( + ValueError, + match=re.escape( + "cannot align objects with broadcast=False " + "because given objects do not share the same dimension names " + "([('x1',), ('x2',)])" + ), + ): + xda_1 / xda_2 + + def test_broadcast_on_vs_off_differing_dims_differing_sizes(self) -> None: + xda_1 = xr.DataArray([1], dims="x1") + xda_2 = xr.DataArray([1, 2], dims="x2") + + aligned_1, aligned_2 = xr.align(xda_1, xda_2, join="exact", broadcast=True) + assert_identical(aligned_1, xda_1) + assert_identical(aligned_2, xda_2) + + with pytest.raises( + ValueError, + match=re.escape( + "cannot align objects with broadcast=False " + "because given objects do not share the same dimension names " + "([('x1',), ('x2',)])" + ), + ): + xr.align(xda_1, xda_2, join="exact", broadcast=False) + + def test_broadcast_on_vs_off_2d(self) -> None: + xda_1 = xr.DataArray([[1, 2, 3], [4, 5, 6]], dims=("y1", "x1")) + xda_2 = xr.DataArray([[1, 2, 3], [4, 5, 6]], dims=("y2", "x2")) + xda_3 = xr.DataArray([[1, 2, 3], [4, 5, 6]], dims=("y3", "x3")) + + aligned_1, aligned_2, aligned_3 = xr.align( + xda_1, xda_2, xda_3, join="exact", broadcast=True + ) + assert_identical(aligned_1, xda_1) + assert_identical(aligned_2, xda_2) + assert_identical(aligned_3, xda_3) + + with pytest.raises( + ValueError, + match=re.escape( + "cannot align objects with broadcast=False " + "because given objects do not share the same dimension names " + "([('y1', 'x1'), ('y2', 'x2'), ('y3', 'x3')])" + ), + ): + xr.align(xda_1, xda_2, xda_3, join="exact", broadcast=False) def test_broadcast_arrays(self) -> None: x = DataArray([1, 2], coords=[("a", [-1, -2])], name="x") y = DataArray([1, 2], coords=[("b", [3, 4])], name="y") @@ -3380,7 +3480,7 @@ def test_to_dataframe_0length(self) -> None: actual = arr.to_dataframe() assert len(actual) == 0 assert_array_equal(actual.index.names, list("ABC")) - + @requires_dask_expr @requires_dask def test_to_dask_dataframe(self) -> None: arr_np = np.arange(3 * 4).reshape(3, 4) From 049e334d09443cf939e2cb7ec98d225c5a903131 Mon Sep 17 00:00:00 2001 From: eschalk Date: Sun, 25 Feb 2024 14:58:14 +0100 Subject: [PATCH 03/14] Keep relevant test --- xarray/core/variable.py | 2 +- xarray/tests/test_dataarray.py | 90 ++-------------------------------- 2 files changed, 5 insertions(+), 87 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index d9b73b00cba..e21c45fa980 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2272,7 +2272,7 @@ def _binary_op(self, other, f, reflexive=False): return NotImplemented if not OPTIONS["arithmetic_broadcast"]: - raise ValueError("Arithmetic broadcast is disabled via global option") + raise ValueError("arithmetic broadcast is disabled via global option") if reflexive and issubclass(type(self), type(other)): other_data, self_data, dims = _broadcast_compat_data(other, self) else: diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index e8e3eb35784..f0f02809108 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -50,7 +50,8 @@ raise_if_dask_computes, requires_bottleneck, requires_cupy, - requires_dask,requires_dask_expr, + requires_dask, + requires_dask_expr, requires_iris, requires_numexpr, requires_pint, @@ -3203,47 +3204,6 @@ def test_align_str_dtype(self) -> None: assert_identical(expected_b, actual_b) assert expected_b.x.dtype == actual_b.x.dtype - - @pytest.mark.parametrize("broadcast", [True, False]) - def test_broadcast_on_vs_off_same_dim_same_size(self, broadcast: bool) -> None: - xda = xr.DataArray([1], dims="x") - - aligned_1, aligned_2 = xr.align(xda, xda, join="exact", broadcast=broadcast) - assert_identical(aligned_1, xda) - assert_identical(aligned_2, xda) - - @pytest.mark.parametrize("broadcast", [True, False]) - def test_broadcast_on_vs_off_same_dim_differing_sizes(self: bool) -> None: - xda_1 = xr.DataArray([1], dims="x") - xda_2 = xr.DataArray([1, 2], dims="x") - - with pytest.raises( - ValueError, - match=re.escape( - "cannot reindex or align along dimension 'x' because of " - "conflicting dimension sizes: {1, 2}" - ), - ): - xr.align(xda_1, xda_2, join="exact", broadcast=broadcast) - - def test_broadcast_on_vs_off_differing_dims_same_sizes(self) -> None: - xda_1 = xr.DataArray([1], dims="x1") - xda_2 = xr.DataArray([1], dims="x2") - - aligned_1, aligned_2 = xr.align(xda_1, xda_2, join="exact", broadcast=True) - assert_identical(aligned_1, xda_1) - assert_identical(aligned_2, xda_2) - - with pytest.raises( - ValueError, - match=re.escape( - "cannot align objects with broadcast=False " - "because given objects do not share the same dimension names " - "([('x1',), ('x2',)])" - ), - ): - xr.align(xda_1, xda_2, join="exact", broadcast=False) - def test_broadcast_on_vs_off_global_option(self) -> None: xda_1 = xr.DataArray([1], dims="x1") xda_2 = xr.DataArray([1], dims="x2") @@ -3256,53 +3216,10 @@ def test_broadcast_on_vs_off_global_option(self) -> None: with xr.set_options(arithmetic_broadcast=False): with pytest.raises( ValueError, - match=re.escape( - "cannot align objects with broadcast=False " - "because given objects do not share the same dimension names " - "([('x1',), ('x2',)])" - ), + match=re.escape("arithmetic broadcast is disabled via global option"), ): xda_1 / xda_2 - def test_broadcast_on_vs_off_differing_dims_differing_sizes(self) -> None: - xda_1 = xr.DataArray([1], dims="x1") - xda_2 = xr.DataArray([1, 2], dims="x2") - - aligned_1, aligned_2 = xr.align(xda_1, xda_2, join="exact", broadcast=True) - assert_identical(aligned_1, xda_1) - assert_identical(aligned_2, xda_2) - - with pytest.raises( - ValueError, - match=re.escape( - "cannot align objects with broadcast=False " - "because given objects do not share the same dimension names " - "([('x1',), ('x2',)])" - ), - ): - xr.align(xda_1, xda_2, join="exact", broadcast=False) - - def test_broadcast_on_vs_off_2d(self) -> None: - xda_1 = xr.DataArray([[1, 2, 3], [4, 5, 6]], dims=("y1", "x1")) - xda_2 = xr.DataArray([[1, 2, 3], [4, 5, 6]], dims=("y2", "x2")) - xda_3 = xr.DataArray([[1, 2, 3], [4, 5, 6]], dims=("y3", "x3")) - - aligned_1, aligned_2, aligned_3 = xr.align( - xda_1, xda_2, xda_3, join="exact", broadcast=True - ) - assert_identical(aligned_1, xda_1) - assert_identical(aligned_2, xda_2) - assert_identical(aligned_3, xda_3) - - with pytest.raises( - ValueError, - match=re.escape( - "cannot align objects with broadcast=False " - "because given objects do not share the same dimension names " - "([('y1', 'x1'), ('y2', 'x2'), ('y3', 'x3')])" - ), - ): - xr.align(xda_1, xda_2, xda_3, join="exact", broadcast=False) def test_broadcast_arrays(self) -> None: x = DataArray([1, 2], coords=[("a", [-1, -2])], name="x") y = DataArray([1, 2], coords=[("b", [3, 4])], name="y") @@ -3480,6 +3397,7 @@ def test_to_dataframe_0length(self) -> None: actual = arr.to_dataframe() assert len(actual) == 0 assert_array_equal(actual.index.names, list("ABC")) + @requires_dask_expr @requires_dask def test_to_dask_dataframe(self) -> None: From e370046807e0fd15029d73ac4de54ed9a2a4d58e Mon Sep 17 00:00:00 2001 From: eschalk Date: Sun, 25 Feb 2024 15:04:20 +0100 Subject: [PATCH 04/14] what's new --- doc/whats-new.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 9d7eb55071b..d91d58859c9 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -23,6 +23,9 @@ v2024.03.0 (unreleased) New Features ~~~~~~~~~~~~ +- Do not attempt to broadcast when global option ``arithmetic_broadcast=False`` + (:issue:`6806`, :pull:`8784`). + By `Etienne Schalk `_. - Add the ``.oindex`` property to Explicitly Indexed Arrays for orthogonal indexing functionality. (:issue:`8238`, :pull:`8750`) By `Anderson Banihirwe `_. From 99835cc2da86abe89b0aa685a4878642bd52457a Mon Sep 17 00:00:00 2001 From: eschalk Date: Sun, 25 Feb 2024 23:10:46 +0100 Subject: [PATCH 05/14] PR comment --- xarray/core/variable.py | 10 ++++++++-- xarray/tests/test_dataarray.py | 25 +++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index e21c45fa980..14c8c6e8ec4 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2271,8 +2271,6 @@ def _binary_op(self, other, f, reflexive=False): if isinstance(other, (xr.DataArray, xr.Dataset)): return NotImplemented - if not OPTIONS["arithmetic_broadcast"]: - raise ValueError("arithmetic broadcast is disabled via global option") if reflexive and issubclass(type(self), type(other)): other_data, self_data, dims = _broadcast_compat_data(other, self) else: @@ -2867,6 +2865,14 @@ def broadcast_variables(*variables: Variable) -> tuple[Variable, ...]: def _broadcast_compat_data(self, other): + if not OPTIONS["arithmetic_broadcast"]: + if not isinstance(self, Variable): + raise NotImplementedError + if (isinstance(other, Variable) and self.dims != other.dims) or ( + isinstance(other, np.ndarray) and self.ndim != other.ndim + ): + raise ValueError("arithmetic broadcast is disabled via global option") + if all(hasattr(other, attr) for attr in ["dims", "data", "shape", "encoding"]): # `other` satisfies the necessary Variable API for broadcast_variables new_self, new_other = _broadcast_compat_variables(self, other) diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index f0f02809108..e26072df6d8 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -3204,14 +3204,14 @@ def test_align_str_dtype(self) -> None: assert_identical(expected_b, actual_b) assert expected_b.x.dtype == actual_b.x.dtype - def test_broadcast_on_vs_off_global_option(self) -> None: + def test_broadcast_on_vs_off_global_option_different_dims(self) -> None: xda_1 = xr.DataArray([1], dims="x1") xda_2 = xr.DataArray([1], dims="x2") with xr.set_options(arithmetic_broadcast=True): expected_xda = xr.DataArray([[1.0]], dims=("x1", "x2")) actual_xda = xda_1 / xda_2 - assert_identical(expected_xda, actual_xda) + assert_identical(actual_xda, expected_xda) with xr.set_options(arithmetic_broadcast=False): with pytest.raises( @@ -3220,6 +3220,27 @@ def test_broadcast_on_vs_off_global_option(self) -> None: ): xda_1 / xda_2 + @pytest.mark.parametrize("arithmetic_broadcast", [True, False]) + def test_broadcast_on_vs_off_global_option_same_dims( + self, arithmetic_broadcast: bool + ) -> None: + # Ensure that no error is raised when arithmetic broadcasting is disabled, + # when broadcasting is not needed. The two DataArrays have the same + # dimensions of the same size. + xda_1 = xr.DataArray([1], dims="x") + xda_2 = xr.DataArray([1], dims="x") + expected_xda = xr.DataArray([2.0], dims=("x",)) + + with xr.set_options(arithmetic_broadcast=arithmetic_broadcast): + actual_xda = xda_1 + xda_2 + assert_identical(actual_xda, expected_xda) + + actual_xda = xda_1 + np.array([1.0]) + assert_identical(actual_xda, expected_xda) + + actual_xda = np.array([1.0]) + xda_1 + assert_identical(actual_xda, expected_xda) + def test_broadcast_arrays(self) -> None: x = DataArray([1, 2], coords=[("a", [-1, -2])], name="x") y = DataArray([1, 2], coords=[("b", [3, 4])], name="y") From ea30aad1227c496ad048ac93c4ba6277ac966c33 Mon Sep 17 00:00:00 2001 From: eschalk Date: Sun, 25 Feb 2024 23:13:57 +0100 Subject: [PATCH 06/14] remove unnecessary (?) check --- xarray/core/variable.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 14c8c6e8ec4..d711d3e3ed5 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2866,8 +2866,6 @@ def broadcast_variables(*variables: Variable) -> tuple[Variable, ...]: def _broadcast_compat_data(self, other): if not OPTIONS["arithmetic_broadcast"]: - if not isinstance(self, Variable): - raise NotImplementedError if (isinstance(other, Variable) and self.dims != other.dims) or ( isinstance(other, np.ndarray) and self.ndim != other.ndim ): From 054622def92e4449a2f61889e762910e18af2aa4 Mon Sep 17 00:00:00 2001 From: eschalk Date: Sun, 25 Feb 2024 23:35:31 +0100 Subject: [PATCH 07/14] unnecessary line removal --- xarray/core/variable.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index d711d3e3ed5..9612d7690c8 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2270,7 +2270,6 @@ def _unary_op(self, f, *args, **kwargs): def _binary_op(self, other, f, reflexive=False): if isinstance(other, (xr.DataArray, xr.Dataset)): return NotImplemented - if reflexive and issubclass(type(self), type(other)): other_data, self_data, dims = _broadcast_compat_data(other, self) else: From 0cdbd93e29f919986ed284a12062a084549bf1dd Mon Sep 17 00:00:00 2001 From: eschalk Date: Mon, 26 Feb 2024 08:45:54 +0100 Subject: [PATCH 08/14] removal of variable reassignment to avoid type issue --- xarray/tests/test_dataarray.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index e26072df6d8..8a023000d15 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -3232,14 +3232,9 @@ def test_broadcast_on_vs_off_global_option_same_dims( expected_xda = xr.DataArray([2.0], dims=("x",)) with xr.set_options(arithmetic_broadcast=arithmetic_broadcast): - actual_xda = xda_1 + xda_2 - assert_identical(actual_xda, expected_xda) - - actual_xda = xda_1 + np.array([1.0]) - assert_identical(actual_xda, expected_xda) - - actual_xda = np.array([1.0]) + xda_1 - assert_identical(actual_xda, expected_xda) + assert_identical(xda_1 + xda_2, expected_xda) + assert_identical(xda_1 + np.array([1.0]), expected_xda) + assert_identical(np.array([1.0]) + xda_1, expected_xda) def test_broadcast_arrays(self) -> None: x = DataArray([1, 2], coords=[("a", [-1, -2])], name="x") From 9c142fd3a059bcf174709bb5c8e94be21e16fc2c Mon Sep 17 00:00:00 2001 From: Etienne Schalk <45271239+etienneschalk@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:56:19 +0100 Subject: [PATCH 09/14] Update xarray/core/variable.py Co-authored-by: Deepak Cherian --- xarray/core/variable.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 9612d7690c8..a6508f045a8 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2868,7 +2868,8 @@ def _broadcast_compat_data(self, other): if (isinstance(other, Variable) and self.dims != other.dims) or ( isinstance(other, np.ndarray) and self.ndim != other.ndim ): - raise ValueError("arithmetic broadcast is disabled via global option") + raise ValueError("Broadcasting is necessary but automatic broadcasting is disabled via global option " + "`'arithmetic_broadcast'`. Use `xr.set_options(arithmetic_broadcast=True)` to enable automatic broadcasting.") if all(hasattr(other, attr) for attr in ["dims", "data", "shape", "encoding"]): # `other` satisfies the necessary Variable API for broadcast_variables From 7fc72ed8e5268b8efee9569b114a2dea65eeed4b Mon Sep 17 00:00:00 2001 From: Etienne Schalk <45271239+etienneschalk@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:56:29 +0100 Subject: [PATCH 10/14] Update xarray/core/variable.py Co-authored-by: Deepak Cherian --- xarray/core/variable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index a6508f045a8..015230b82a1 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2866,7 +2866,7 @@ def broadcast_variables(*variables: Variable) -> tuple[Variable, ...]: def _broadcast_compat_data(self, other): if not OPTIONS["arithmetic_broadcast"]: if (isinstance(other, Variable) and self.dims != other.dims) or ( - isinstance(other, np.ndarray) and self.ndim != other.ndim + is_duck_array(other) and self.ndim != other.ndim ): raise ValueError("Broadcasting is necessary but automatic broadcasting is disabled via global option " "`'arithmetic_broadcast'`. Use `xr.set_options(arithmetic_broadcast=True)` to enable automatic broadcasting.") From 187bd6aaab1f3a93f70e192c60535b78c9d76ce4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 19:56:48 +0000 Subject: [PATCH 11/14] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/variable.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 015230b82a1..8688ceaa447 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2868,8 +2868,10 @@ def _broadcast_compat_data(self, other): if (isinstance(other, Variable) and self.dims != other.dims) or ( is_duck_array(other) and self.ndim != other.ndim ): - raise ValueError("Broadcasting is necessary but automatic broadcasting is disabled via global option " - "`'arithmetic_broadcast'`. Use `xr.set_options(arithmetic_broadcast=True)` to enable automatic broadcasting.") + raise ValueError( + "Broadcasting is necessary but automatic broadcasting is disabled via global option " + "`'arithmetic_broadcast'`. Use `xr.set_options(arithmetic_broadcast=True)` to enable automatic broadcasting." + ) if all(hasattr(other, attr) for attr in ["dims", "data", "shape", "encoding"]): # `other` satisfies the necessary Variable API for broadcast_variables From fcc81220578abc48fa3b4485e245e935f2628928 Mon Sep 17 00:00:00 2001 From: eschalk Date: Mon, 26 Feb 2024 21:02:53 +0100 Subject: [PATCH 12/14] Update tests --- xarray/core/variable.py | 5 +++-- xarray/tests/test_dataarray.py | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 8688ceaa447..c025f9e004f 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2869,8 +2869,9 @@ def _broadcast_compat_data(self, other): is_duck_array(other) and self.ndim != other.ndim ): raise ValueError( - "Broadcasting is necessary but automatic broadcasting is disabled via global option " - "`'arithmetic_broadcast'`. Use `xr.set_options(arithmetic_broadcast=True)` to enable automatic broadcasting." + "Broadcasting is necessary but automatic broadcasting is disabled via " + "global option `'arithmetic_broadcast'`. " + "Use `xr.set_options(arithmetic_broadcast=True)` to enable automatic broadcasting." ) if all(hasattr(other, attr) for attr in ["dims", "data", "shape", "encoding"]): diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 8a023000d15..5ab20b2c29c 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -3216,7 +3216,11 @@ def test_broadcast_on_vs_off_global_option_different_dims(self) -> None: with xr.set_options(arithmetic_broadcast=False): with pytest.raises( ValueError, - match=re.escape("arithmetic broadcast is disabled via global option"), + match=re.escape( + "Broadcasting is necessary but automatic broadcasting is disabled via " + "global option `'arithmetic_broadcast'`. " + "Use `xr.set_options(arithmetic_broadcast=True)` to enable automatic broadcasting." + ), ): xda_1 / xda_2 From e1f5c27e51f0cbdf9c950006ec539b1b349459c1 Mon Sep 17 00:00:00 2001 From: eschalk Date: Mon, 26 Feb 2024 21:06:51 +0100 Subject: [PATCH 13/14] what's new --- doc/whats-new.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index d91d58859c9..7a89269f8b6 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -25,7 +25,7 @@ New Features - Do not attempt to broadcast when global option ``arithmetic_broadcast=False`` (:issue:`6806`, :pull:`8784`). - By `Etienne Schalk `_. + By `Etienne Schalk `_ and `Deepak Cherian `_. - Add the ``.oindex`` property to Explicitly Indexed Arrays for orthogonal indexing functionality. (:issue:`8238`, :pull:`8750`) By `Anderson Banihirwe `_. From 3186ce69bad12ce26ecaade5933fd61b52ae0d3b Mon Sep 17 00:00:00 2001 From: Deepak Cherian Date: Sun, 3 Mar 2024 15:01:42 -0700 Subject: [PATCH 14/14] Update doc/whats-new.rst --- doc/whats-new.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 7a89269f8b6..1a16be08981 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -23,7 +23,7 @@ v2024.03.0 (unreleased) New Features ~~~~~~~~~~~~ -- Do not attempt to broadcast when global option ``arithmetic_broadcast=False`` +- Do not broadcast in arithmetic operations when global option ``arithmetic_broadcast=False`` (:issue:`6806`, :pull:`8784`). By `Etienne Schalk `_ and `Deepak Cherian `_. - Add the ``.oindex`` property to Explicitly Indexed Arrays for orthogonal indexing functionality. (:issue:`8238`, :pull:`8750`)