diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 91d272d212d..dfb90560006 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -55,6 +55,10 @@ New Features Breaking Changes ~~~~~~~~~~~~~~~~ +- Passing keyword-only arguments of :py:meth:`Dataset.groupby`, + :py:meth:`DataArray.groupby`, :py:meth:`Dataset.resample` and + :py:meth:`DataArray.resample` positionally, deprecated since v2024.07.0, now + raises a ``TypeError`` (:issue:`11721`, :pull:`11744`). - The ``DataArray.dt.weekofyear`` and ``DataArray.dt.week`` accessors, deprecated since v0.16.2, have been removed. Use ``DataArray.dt.isocalendar().week`` instead (:issue:`11721`, :pull:`11742`). @@ -120,6 +124,11 @@ Breaking Changes Deprecations ~~~~~~~~~~~~ +- Passing any argument after ``bins`` positionally to + :py:meth:`Dataset.groupby_bins` and :py:meth:`DataArray.groupby_bins` is + deprecated. It was meant to be deprecated in v2024.07.0, but the warning never + fired (:issue:`11721`, :pull:`11744`). + By `Mohansree Vijayakumar `_. - ``reset_encoding`` of :py:class:`Dataset`, :py:class:`DataArray` and :py:class:`Variable` now emits a ``FutureWarning`` instead of a ``UserWarning``, like the other deprecations, and gives the right version (2023.10). diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 4a186bbbae8..081df7e2d99 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -7140,7 +7140,6 @@ def interp_calendar( """ return interp_calendar(self, target, dim=dim) - @_deprecate_positional_args("v2024.07.0") def groupby( self, group: GroupInput = None, @@ -7284,11 +7283,12 @@ def groupby( ) return DataArrayGroupBy(self, rgroupers, restore_coord_dims=restore_coord_dims) - @_deprecate_positional_args("v2024.07.0") + @_deprecate_positional_args("v2026.10.0") def groupby_bins( self, group: Hashable | DataArray | IndexVariable, bins: Bins, + *, right: bool = True, labels: ArrayLike | Literal[False] | None = None, precision: int = 3, @@ -7712,7 +7712,6 @@ def coarsen( coord_func=coord_func, ) - @_deprecate_positional_args("v2024.07.0") def resample( self, indexer: Mapping[Hashable, ResampleCompatible | Resampler] | None = None, diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 9d16ea366b1..8c98d9eb15d 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -10318,7 +10318,6 @@ def interp_calendar( """ return interp_calendar(self, target, dim=dim) - @_deprecate_positional_args("v2024.07.0") def groupby( self, group: GroupInput = None, @@ -10431,11 +10430,12 @@ def groupby( return DatasetGroupBy(self, rgroupers, restore_coord_dims=restore_coord_dims) - @_deprecate_positional_args("v2024.07.0") + @_deprecate_positional_args("v2026.10.0") def groupby_bins( self, group: Hashable | DataArray | IndexVariable, bins: Bins, + *, right: bool = True, labels: ArrayLike | None = None, precision: int = 3, @@ -10704,7 +10704,6 @@ def coarsen( coord_func=coord_func, ) - @_deprecate_positional_args("v2024.07.0") def resample( self, indexer: Mapping[Any, ResampleCompatible | Resampler] | None = None, diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index 6485367ffe6..28974547989 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -3069,17 +3069,37 @@ def test_multiple_groupers_string(as_dataset) -> None: actual = obj.groupby(("labels1", "labels2")).mean() assert_identical(expected, actual) - # Passes `"labels2"` to squeeze; will raise an error around kwargs rather than the - # warning & type error in the future - with pytest.warns(FutureWarning): - with pytest.raises(TypeError): - obj.groupby("labels1", "labels2") # type: ignore[arg-type, call-arg] + with pytest.raises(TypeError, match=r"positional argument"): + obj.groupby("labels1", "labels2") # type: ignore[arg-type, call-arg] with pytest.raises(ValueError): obj.groupby("labels1", foo="bar") # type: ignore[arg-type] with pytest.raises(ValueError): obj.groupby("labels1", foo=UniqueGrouper()) +@pytest.mark.parametrize("as_dataset", [True, False]) +def test_keyword_only_args(as_dataset: bool) -> None: + obj: DataArray | Dataset = DataArray( + [1, 2, 3], + dims="time", + coords={"time": pd.date_range("2000-01-01", periods=3)}, + name="foo", + ) + if as_dataset: + obj = obj.to_dataset() + + with pytest.raises(TypeError, match=r"positional argument"): + obj.groupby("time", False) # type: ignore[call-arg] + with pytest.raises(TypeError, match=r"positional argument"): + obj.resample({"time": "D"}, True) # type: ignore[call-arg] + + obj = obj.assign_coords(x=("time", [1, 2, 3])) + expected = obj.groupby_bins("x", [0, 2, 4], right=False).sum() + with pytest.warns(FutureWarning, match=r"Passing 'right' as positional"): + actual = obj.groupby_bins("x", [0, 2, 4], False).sum() # type: ignore[call-arg] + assert_identical(expected, actual) + + @pytest.mark.parametrize("shuffle", [True, False]) @pytest.mark.parametrize("use_flox", [True, False]) def test_multiple_groupers(use_flox: bool, shuffle: bool) -> None: