diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index 16474dd83a1f5c..7395f9d2dcb9e5 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -160,6 +160,8 @@ Deprecations - Deprecated treating ``numpy.datetime64`` objects as UTC times when passed to the :class:`Timestamp` constructor along with a timezone. In a future version, these will be treated as wall-times. To retain the old behavior, use ``Timestamp(dt64).tz_localize("UTC").tz_convert(tz)`` (:issue:`24559`) - Deprecated ignoring missing labels when indexing with a sequence of labels on a level of a MultiIndex (:issue:`42351`) - Creating an empty Series without a dtype will now raise a more visible ``FutureWarning`` instead of a ``DeprecationWarning`` (:issue:`30017`) +- Deprecated the 'kind' argument in :meth:`Index.get_slice_bound`, :meth:`Index.slice_indexer`, :meth:`Index.slice_locs`; in a future version passing 'kind' will raise (:issue:`42857`) +- .. --------------------------------------------------------------------------- diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 54271f0f9b4920..1c94baf74b60be 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -5839,7 +5839,7 @@ def slice_indexer( start: Hashable | None = None, end: Hashable | None = None, step: int | None = None, - kind: str_t | None = None, + kind=no_default, ) -> slice: """ Compute the slice indexer for input labels and step. @@ -5855,6 +5855,8 @@ def slice_indexer( step : int, default None kind : str, default None + .. deprecated:: 1.4.0 + Returns ------- indexer : slice @@ -5880,6 +5882,8 @@ 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 @@ -5928,6 +5932,8 @@ def _maybe_cast_slice_bound(self, label, side: str_t, kind=no_default): side : {'left', 'right'} kind : {'loc', 'getitem'} or None + .. deprecated:: 1.3.0 + Returns ------- label : object @@ -5962,7 +5968,7 @@ def _searchsorted_monotonic(self, label, side: str_t = "left"): raise ValueError("index must be monotonic increasing or decreasing") - def get_slice_bound(self, label, side: str_t, kind=None) -> int: + def get_slice_bound(self, label, side: str_t, kind=no_default) -> int: """ Calculate slice bound that corresponds to given label. @@ -5975,12 +5981,15 @@ def get_slice_bound(self, label, side: str_t, kind=None) -> int: side : {'left', 'right'} kind : {'loc', 'getitem'} or None + .. deprecated:: 1.4.0 + Returns ------- int Index of label. """ - assert kind in ["loc", "getitem", None] + assert kind in ["loc", "getitem", None, no_default] + self._deprecated_arg(kind, "kind", "get_slice_bound") if side not in ("left", "right"): raise ValueError( @@ -6030,7 +6039,7 @@ def get_slice_bound(self, label, side: str_t, kind=None) -> int: else: return slc - def slice_locs(self, start=None, end=None, step=None, kind=None): + def slice_locs(self, start=None, end=None, step=None, kind=no_default): """ Compute slice locations for input labels. @@ -6044,6 +6053,8 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): If None, defaults to 1. kind : {'loc', 'getitem'} or None + .. deprecated:: 1.4.0 + Returns ------- start, end : int @@ -6062,6 +6073,7 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): >>> 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/datetimes.py b/pandas/core/indexes/datetimes.py index 9712a5d95a234e..348598c1309eba 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -729,7 +729,7 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default): return self._maybe_cast_for_get_loc(label) - def slice_indexer(self, start=None, end=None, step=None, kind=None): + def slice_indexer(self, start=None, end=None, step=None, kind=lib.no_default): """ Return indexer for specified label slice. Index.slice_indexer, customized to handle time slicing. @@ -743,6 +743,8 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): 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). diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index b4e8a763d12109..e5aa8e95e23dea 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -2586,7 +2586,7 @@ def _get_indexer_level_0(self, target) -> np.ndarray: return ci.get_indexer_for(target) def get_slice_bound( - self, label: Hashable | Sequence[Hashable], side: str, kind: str | None = None + self, label: Hashable | Sequence[Hashable], side: str, kind=lib.no_default ) -> int: """ For an ordered MultiIndex, compute slice bound @@ -2601,6 +2601,8 @@ def get_slice_bound( side : {'left', 'right'} kind : {'loc', 'getitem', None} + .. deprecated:: 1.4.0 + Returns ------- int @@ -2632,11 +2634,13 @@ 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=None): + def slice_locs(self, start=None, end=None, step=None, kind=lib.no_default): """ For an ordered MultiIndex, compute the slice locations for input labels. @@ -2655,6 +2659,8 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): Slice step kind : string, optional, defaults None + .. deprecated:: 1.4.0 + Returns ------- (start, end) : (int, int) @@ -2688,6 +2694,7 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): 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 bb9a2688f0485f..d31f6d6a252f37 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -244,7 +244,7 @@ def _convert_slice_indexer(self, key: slice, kind: str): # We always treat __getitem__ slicing as label-based # translate to locations - return self.slice_indexer(key.start, key.stop, key.step, kind=kind) + return self.slice_indexer(key.start, key.stop, key.step) return super()._convert_slice_indexer(key, kind=kind) diff --git a/pandas/tests/indexes/base_class/test_indexing.py b/pandas/tests/indexes/base_class/test_indexing.py index fd04a820037b95..654f5a89f18282 100644 --- a/pandas/tests/indexes/base_class/test_indexing.py +++ b/pandas/tests/indexes/base_class/test_indexing.py @@ -10,7 +10,8 @@ class TestGetSliceBounds: @pytest.mark.parametrize("side, expected", [("left", 4), ("right", 5)]) def test_get_slice_bounds_within(self, kind, side, expected): index = Index(list("abcdef")) - result = index.get_slice_bound("e", kind=kind, side=side) + with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): + result = index.get_slice_bound("e", kind=kind, side=side) assert result == expected @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @@ -20,12 +21,13 @@ def test_get_slice_bounds_within(self, kind, side, expected): ) def test_get_slice_bounds_outside(self, kind, side, expected, data, bound): index = Index(data) - result = index.get_slice_bound(bound, kind=kind, side=side) + with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): + result = index.get_slice_bound(bound, kind=kind, side=side) assert result == expected def test_get_slice_bounds_invalid_side(self): with pytest.raises(ValueError, match="Invalid value for side kwarg"): - Index([]).get_slice_bound("a", kind=None, side="middle") + Index([]).get_slice_bound("a", side="middle") class TestGetIndexerNonUnique: diff --git a/pandas/tests/indexes/multi/test_indexing.py b/pandas/tests/indexes/multi/test_indexing.py index d2afc76076dc0c..e142cbf89f1bd0 100644 --- a/pandas/tests/indexes/multi/test_indexing.py +++ b/pandas/tests/indexes/multi/test_indexing.py @@ -820,7 +820,8 @@ 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) - result = idx.get_slice_bound(target, side=algo, kind="loc") + with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): + result = idx.get_slice_bound(target, side=algo, kind="loc") assert result == expected diff --git a/pandas/tests/indexes/numeric/test_indexing.py b/pandas/tests/indexes/numeric/test_indexing.py index e6b418868dbebf..8f113491dad60c 100644 --- a/pandas/tests/indexes/numeric/test_indexing.py +++ b/pandas/tests/indexes/numeric/test_indexing.py @@ -545,7 +545,9 @@ class TestGetSliceBounds: @pytest.mark.parametrize("side, expected", [("left", 4), ("right", 5)]) def test_get_slice_bounds_within(self, kind, side, expected): index = Index(range(6)) - result = index.get_slice_bound(4, kind=kind, side=side) + with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): + + result = index.get_slice_bound(4, kind=kind, side=side) assert result == expected @pytest.mark.parametrize("kind", ["getitem", "loc", None]) @@ -553,5 +555,6 @@ def test_get_slice_bounds_within(self, kind, side, expected): @pytest.mark.parametrize("bound, expected", [(-1, 0), (10, 6)]) def test_get_slice_bounds_outside(self, kind, side, expected, bound): index = Index(range(6)) - result = index.get_slice_bound(bound, kind=kind, side=side) + with tm.assert_produces_warning(FutureWarning, match="'kind' argument"): + result = index.get_slice_bound(bound, kind=kind, side=side) assert result == expected