diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 6239ddf9442e7..3f26d09a54a76 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -180,6 +180,7 @@ Removal of prior version deprecations/changes - Removed argument ``how`` from :meth:`PeriodIndex.astype`, use :meth:`PeriodIndex.to_timestamp` instead (:issue:`37982`) - Removed argument ``try_cast`` from :meth:`DataFrame.mask`, :meth:`DataFrame.where`, :meth:`Series.mask` and :meth:`Series.where` (:issue:`38836`) - Removed argument ``is_copy`` from :meth:`DataFrame.take` and :meth:`Series.take` (:issue:`30615`) +- Removed argument ``kind`` from :meth:`Index.get_slice_bound`, :meth:`Index.slice_indexer` and :meth:`Index.slice_locs` (:issue:`41378`) - Disallow passing non-round floats to :class:`Timestamp` with ``unit="M"`` or ``unit="Y"`` (:issue:`47266`) - Remove keywords ``convert_float`` and ``mangle_dupe_cols`` from :func:`read_excel` (:issue:`41176`) - Disallow passing non-keyword arguments to :func:`read_excel` except ``io`` and ``sheet_name`` (:issue:`34418`) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 7d680688f4731..4e513dcc8b551 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -6471,7 +6471,6 @@ def slice_indexer( start: Hashable | None = None, end: Hashable | None = None, step: int | None = None, - kind=no_default, ) -> slice: """ Compute the slice indexer for input labels and step. @@ -6485,9 +6484,6 @@ def slice_indexer( end : label, default None If None, defaults to the end. step : int, default None - kind : str, default None - - .. deprecated:: 1.4.0 Returns ------- @@ -6514,8 +6510,6 @@ def slice_indexer( >>> idx.slice_indexer(start='b', end=('c', 'g')) slice(1, 3, None) """ - self._deprecated_arg(kind, "kind", "slice_indexer") - start_slice, end_slice = self.slice_locs(start, end, step=step) # return a slice @@ -6550,7 +6544,7 @@ def _validate_indexer(self, form: str_t, key, kind: str_t) -> None: if key is not None and not is_integer(key): self._raise_invalid_indexer(form, key) - def _maybe_cast_slice_bound(self, label, side: str_t, kind=no_default): + def _maybe_cast_slice_bound(self, label, side: str_t): """ This function should be overloaded in subclasses that allow non-trivial casting on label-slice bounds, e.g. datetime-like indices allowing @@ -6560,9 +6554,6 @@ def _maybe_cast_slice_bound(self, label, side: str_t, kind=no_default): ---------- label : object side : {'left', 'right'} - kind : {'loc', 'getitem'} or None - - .. deprecated:: 1.3.0 Returns ------- @@ -6572,8 +6563,6 @@ def _maybe_cast_slice_bound(self, label, side: str_t, kind=no_default): ----- Value of `side` parameter should be validated in caller. """ - assert kind in ["loc", "getitem", None, no_default] - self._deprecated_arg(kind, "kind", "_maybe_cast_slice_bound") # We are a plain index here (sub-class override this method if they # wish to have special treatment for floats/ints, e.g. Float64Index and @@ -6598,9 +6587,7 @@ def _searchsorted_monotonic(self, label, side: Literal["left", "right"] = "left" raise ValueError("index must be monotonic increasing or decreasing") - def get_slice_bound( - self, label, side: Literal["left", "right"], kind=no_default - ) -> int: + def get_slice_bound(self, label, side: Literal["left", "right"]) -> int: """ Calculate slice bound that corresponds to given label. @@ -6611,17 +6598,12 @@ def get_slice_bound( ---------- label : object side : {'left', 'right'} - kind : {'loc', 'getitem'} or None - - .. deprecated:: 1.4.0 Returns ------- int Index of label. """ - assert kind in ["loc", "getitem", None, no_default] - self._deprecated_arg(kind, "kind", "get_slice_bound") if side not in ("left", "right"): raise ValueError( @@ -6667,9 +6649,7 @@ def get_slice_bound( else: return slc - def slice_locs( - self, start=None, end=None, step=None, kind=no_default - ) -> tuple[int, int]: + def slice_locs(self, start=None, end=None, step=None) -> tuple[int, int]: """ Compute slice locations for input labels. @@ -6681,9 +6661,6 @@ def slice_locs( If None, defaults to the end. step : int, defaults None If None, defaults to 1. - kind : {'loc', 'getitem'} or None - - .. deprecated:: 1.4.0 Returns ------- @@ -6703,7 +6680,6 @@ def slice_locs( >>> idx.slice_locs(start='b', end='c') (1, 3) """ - self._deprecated_arg(kind, "kind", "slice_locs") inc = step is None or step >= 0 if not inc: diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 3cf3e50a24c3f..c6c8695ab01da 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -290,7 +290,7 @@ def _partial_date_slice( # try to find the dates return (lhs_mask & rhs_mask).nonzero()[0] - def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): + def _maybe_cast_slice_bound(self, label, side: str): """ If label is a string, cast it to scalar type according to resolution. @@ -298,7 +298,6 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): ---------- label : object side : {'left', 'right'} - kind : {'loc', 'getitem'} or None Returns ------- @@ -308,9 +307,6 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): ----- Value of `side` parameter should be validated in caller. """ - assert kind in ["loc", "getitem", None, lib.no_default] - self._deprecated_arg(kind, "kind", "_maybe_cast_slice_bound") - if isinstance(label, str): try: parsed, reso = self._parse_with_reso(label) diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index b08a0d3a60526..32a4b87e9cb33 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -714,7 +714,7 @@ def _maybe_cast_for_get_loc(self, key) -> Timestamp: return key @doc(DatetimeTimedeltaMixin._maybe_cast_slice_bound) - def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): + def _maybe_cast_slice_bound(self, label, side: str): # GH#42855 handle date here instead of get_slice_bound if isinstance(label, date) and not isinstance(label, datetime): @@ -722,11 +722,11 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): # https://github.com/pandas-dev/pandas/issues/31501 label = Timestamp(label).to_pydatetime() - label = super()._maybe_cast_slice_bound(label, side, kind=kind) + label = super()._maybe_cast_slice_bound(label, side) self._deprecate_mismatched_indexing(label) return self._maybe_cast_for_get_loc(label) - def slice_indexer(self, start=None, end=None, step=None, kind=lib.no_default): + def slice_indexer(self, start=None, end=None, step=None): """ Return indexer for specified label slice. Index.slice_indexer, customized to handle time slicing. @@ -740,8 +740,6 @@ def slice_indexer(self, start=None, end=None, step=None, kind=lib.no_default): value-based selection in non-monotonic cases. """ - self._deprecated_arg(kind, "kind", "slice_indexer") - # For historical reasons DatetimeIndex supports slices between two # instances of datetime.time as if it were applying a slice mask to # an array of (self.hour, self.minute, self.seconds, self.microsecond). @@ -764,7 +762,7 @@ def check_str_or_none(point) -> bool: or check_str_or_none(end) or self.is_monotonic_increasing ): - return Index.slice_indexer(self, start, end, step, kind=kind) + return Index.slice_indexer(self, start, end, step) mask = np.array(True) deprecation_mask = np.array(True) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 3eb3226328a61..8507280a6cc8d 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -786,8 +786,7 @@ def _should_fallback_to_positional(self) -> bool: # ExtensionDtype]" has no attribute "subtype" return self.dtype.subtype.kind in ["m", "M"] # type: ignore[union-attr] - def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): - self._deprecated_arg(kind, "kind", "_maybe_cast_slice_bound") + def _maybe_cast_slice_bound(self, label, side: str): return getattr(self, side)._maybe_cast_slice_bound(label, side) def _is_comparable_dtype(self, dtype: DtypeObj) -> bool: diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 59a0179f93c10..4f8586a4bba13 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -2627,7 +2627,6 @@ def get_slice_bound( self, label: Hashable | Sequence[Hashable], side: Literal["left", "right"], - kind=lib.no_default, ) -> int: """ For an ordered MultiIndex, compute slice bound @@ -2640,9 +2639,6 @@ def get_slice_bound( ---------- label : object or tuple of objects side : {'left', 'right'} - kind : {'loc', 'getitem', None} - - .. deprecated:: 1.4.0 Returns ------- @@ -2675,15 +2671,11 @@ def get_slice_bound( MultiIndex.get_locs : Get location for a label/slice/list/mask or a sequence of such. """ - self._deprecated_arg(kind, "kind", "get_slice_bound") - if not isinstance(label, tuple): label = (label,) return self._partial_tup_index(label, side=side) - def slice_locs( - self, start=None, end=None, step=None, kind=lib.no_default - ) -> tuple[int, int]: + def slice_locs(self, start=None, end=None, step=None) -> tuple[int, int]: """ For an ordered MultiIndex, compute the slice locations for input labels. @@ -2700,9 +2692,6 @@ def slice_locs( If None, defaults to the end step : int or None Slice step - kind : string, optional, defaults None - - .. deprecated:: 1.4.0 Returns ------- @@ -2737,7 +2726,6 @@ def slice_locs( MultiIndex.get_locs : Get location for a label/slice/list/mask or a sequence of such. """ - self._deprecated_arg(kind, "kind", "slice_locs") # This function adds nothing to its parent implementation (the magic # happens in get_slice_bound method), but it adds meaningful doc. return super().slice_locs(start, end, step) diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index f0f6dfe4eb147..2cb814be6472c 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -233,10 +233,7 @@ def _convert_slice_indexer(self, key: slice, kind: str, is_frame: bool = False): return super()._convert_slice_indexer(key, kind=kind, is_frame=is_frame) @doc(Index._maybe_cast_slice_bound) - def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): - assert kind in ["loc", "getitem", None, lib.no_default] - self._deprecated_arg(kind, "kind", "_maybe_cast_slice_bound") - + def _maybe_cast_slice_bound(self, label, side: str): # we will try to coerce to integers return self._maybe_cast_indexer(label) diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index d67bcfdc78261..a09b987496a40 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -8,10 +8,7 @@ import numpy as np -from pandas._libs import ( - index as libindex, - lib, -) +from pandas._libs import index as libindex from pandas._libs.tslibs import ( BaseOffset, NaT, @@ -474,11 +471,11 @@ def _cast_partial_indexing_scalar(self, label): return key @doc(DatetimeIndexOpsMixin._maybe_cast_slice_bound) - def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): + def _maybe_cast_slice_bound(self, label, side: str): if isinstance(label, datetime): label = self._cast_partial_indexing_scalar(label) - return super()._maybe_cast_slice_bound(label, side, kind=kind) + return super()._maybe_cast_slice_bound(label, side) def _parsed_string_to_bounds(self, reso: Resolution, parsed: datetime): iv = Period(parsed, freq=reso.attr_abbrev) diff --git a/pandas/tests/indexes/base_class/test_indexing.py b/pandas/tests/indexes/base_class/test_indexing.py index 770fa3f6e5dc1..070fec47b90e6 100644 --- a/pandas/tests/indexes/base_class/test_indexing.py +++ b/pandas/tests/indexes/base_class/test_indexing.py @@ -10,23 +10,19 @@ class TestGetSliceBounds: - @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @pytest.mark.parametrize("side, expected", [("left", 4), ("right", 5)]) - def test_get_slice_bounds_within(self, kind, side, expected): + def test_get_slice_bounds_within(self, side, expected): index = Index(list("abcdef")) - with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): - result = index.get_slice_bound("e", kind=kind, side=side) + result = index.get_slice_bound("e", side=side) assert result == expected - @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @pytest.mark.parametrize("side", ["left", "right"]) @pytest.mark.parametrize( "data, bound, expected", [(list("abcdef"), "x", 6), (list("bcdefg"), "a", 0)] ) - def test_get_slice_bounds_outside(self, kind, side, expected, data, bound): + def test_get_slice_bounds_outside(self, side, expected, data, bound): index = Index(data) - with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): - result = index.get_slice_bound(bound, kind=kind, side=side) + result = index.get_slice_bound(bound, side=side) assert result == expected def test_get_slice_bounds_invalid_side(self): diff --git a/pandas/tests/indexes/datetimes/test_indexing.py b/pandas/tests/indexes/datetimes/test_indexing.py index 5c8724a2a1c22..87bf0199b2528 100644 --- a/pandas/tests/indexes/datetimes/test_indexing.py +++ b/pandas/tests/indexes/datetimes/test_indexing.py @@ -712,10 +712,9 @@ def test_maybe_cast_slice_duplicate_monotonic(self): class TestGetSliceBounds: @pytest.mark.parametrize("box", [date, datetime, Timestamp]) - @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @pytest.mark.parametrize("side, expected", [("left", 4), ("right", 5)]) def test_get_slice_bounds_datetime_within( - self, box, kind, side, expected, tz_aware_fixture + self, box, side, expected, tz_aware_fixture ): # GH 35690 tz = tz_aware_fixture @@ -725,15 +724,14 @@ def test_get_slice_bounds_datetime_within( warn = None if tz is None else FutureWarning with tm.assert_produces_warning(warn): # GH#36148 will require tzawareness-compat - result = index.get_slice_bound(key, kind=kind, side=side) + result = index.get_slice_bound(key, side=side) assert result == expected @pytest.mark.parametrize("box", [datetime, Timestamp]) - @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @pytest.mark.parametrize("side", ["left", "right"]) @pytest.mark.parametrize("year, expected", [(1999, 0), (2020, 30)]) def test_get_slice_bounds_datetime_outside( - self, box, kind, side, year, expected, tz_aware_fixture + self, box, side, year, expected, tz_aware_fixture ): # GH 35690 tz = tz_aware_fixture @@ -743,12 +741,11 @@ def test_get_slice_bounds_datetime_outside( warn = None if tz is None else FutureWarning with tm.assert_produces_warning(warn): # GH#36148 will require tzawareness-compat - result = index.get_slice_bound(key, kind=kind, side=side) + result = index.get_slice_bound(key, side=side) assert result == expected @pytest.mark.parametrize("box", [datetime, Timestamp]) - @pytest.mark.parametrize("kind", ["getitem", "loc", None]) - def test_slice_datetime_locs(self, box, kind, tz_aware_fixture): + def test_slice_datetime_locs(self, box, tz_aware_fixture): # GH 34077 tz = tz_aware_fixture index = DatetimeIndex(["2010-01-01", "2010-01-03"]).tz_localize(tz) diff --git a/pandas/tests/indexes/multi/test_indexing.py b/pandas/tests/indexes/multi/test_indexing.py index 7519a3e10811d..fce3da6dd6aee 100644 --- a/pandas/tests/indexes/multi/test_indexing.py +++ b/pandas/tests/indexes/multi/test_indexing.py @@ -841,8 +841,7 @@ def test_timestamp_multiindex_indexer(): def test_get_slice_bound_with_missing_value(index_arr, expected, target, algo): # issue 19132 idx = MultiIndex.from_arrays(index_arr) - with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): - result = idx.get_slice_bound(target, side=algo, kind="loc") + result = idx.get_slice_bound(target, side=algo) assert result == expected diff --git a/pandas/tests/indexes/numeric/test_indexing.py b/pandas/tests/indexes/numeric/test_indexing.py index 1c4cbd21a988e..0c2c5e0b903bc 100644 --- a/pandas/tests/indexes/numeric/test_indexing.py +++ b/pandas/tests/indexes/numeric/test_indexing.py @@ -576,20 +576,15 @@ def test_slice_locs_na_raises(self): class TestGetSliceBounds: - @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @pytest.mark.parametrize("side, expected", [("left", 4), ("right", 5)]) - def test_get_slice_bounds_within(self, kind, side, expected): + def test_get_slice_bounds_within(self, side, expected): index = Index(range(6)) - with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): - - result = index.get_slice_bound(4, kind=kind, side=side) + result = index.get_slice_bound(4, side=side) assert result == expected - @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @pytest.mark.parametrize("side", ["left", "right"]) @pytest.mark.parametrize("bound, expected", [(-1, 0), (10, 6)]) - def test_get_slice_bounds_outside(self, kind, side, expected, bound): + def test_get_slice_bounds_outside(self, side, expected, bound): index = Index(range(6)) - with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): - result = index.get_slice_bound(bound, kind=kind, side=side) + result = index.get_slice_bound(bound, side=side) assert result == expected diff --git a/pandas/tests/indexes/test_indexing.py b/pandas/tests/indexes/test_indexing.py index a0cb6691cb6a0..2b7c5745e0c67 100644 --- a/pandas/tests/indexes/test_indexing.py +++ b/pandas/tests/indexes/test_indexing.py @@ -297,19 +297,6 @@ def test_getitem_deprecated_float(idx): assert result == expected -def test_maybe_cast_slice_bound_kind_deprecated(index): - if not len(index): - return - - with tm.assert_produces_warning(FutureWarning): - # passed as keyword - index._maybe_cast_slice_bound(index[0], "left", kind="loc") - - with tm.assert_produces_warning(FutureWarning): - # pass as positional - index._maybe_cast_slice_bound(index[0], "left", "loc") - - @pytest.mark.parametrize( "idx,target,expected", [