From 04d71b6b039c4ef74392b47b1f87e903988b8657 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 7 Jul 2022 17:50:51 +0200 Subject: [PATCH 1/6] DEPR: Deprecate set_closed and add set_incluive --- doc/redirects.csv | 1 + doc/source/reference/arrays.rst | 1 + doc/source/reference/indexing.rst | 2 +- pandas/core/arrays/interval.py | 60 +++++++++++++++++-- pandas/core/indexes/interval.py | 2 +- pandas/tests/arrays/interval/test_interval.py | 23 +++---- .../tests/indexes/interval/test_interval.py | 12 ++-- 7 files changed, 73 insertions(+), 28 deletions(-) diff --git a/doc/redirects.csv b/doc/redirects.csv index 173e670e30f0e..90ddf6c4dc582 100644 --- a/doc/redirects.csv +++ b/doc/redirects.csv @@ -761,6 +761,7 @@ generated/pandas.IntervalIndex.mid,../reference/api/pandas.IntervalIndex.mid generated/pandas.IntervalIndex.overlaps,../reference/api/pandas.IntervalIndex.overlaps generated/pandas.IntervalIndex.right,../reference/api/pandas.IntervalIndex.right generated/pandas.IntervalIndex.set_closed,../reference/api/pandas.IntervalIndex.set_closed +generated/pandas.IntervalIndex.set_inclusive,../reference/api/pandas.IntervalIndex.set_inclusive generated/pandas.IntervalIndex.to_tuples,../reference/api/pandas.IntervalIndex.to_tuples generated/pandas.IntervalIndex.values,../reference/api/pandas.IntervalIndex.values generated/pandas.Interval.left,../reference/api/pandas.Interval.left diff --git a/doc/source/reference/arrays.rst b/doc/source/reference/arrays.rst index 0d8444841fcae..cd0ce581519a8 100644 --- a/doc/source/reference/arrays.rst +++ b/doc/source/reference/arrays.rst @@ -352,6 +352,7 @@ A collection of intervals may be stored in an :class:`arrays.IntervalArray`. arrays.IntervalArray.contains arrays.IntervalArray.overlaps arrays.IntervalArray.set_closed + arrays.IntervalArray.set_inclusive arrays.IntervalArray.to_tuples diff --git a/doc/source/reference/indexing.rst b/doc/source/reference/indexing.rst index 89a9a0a92ef08..e40f1b041a0cf 100644 --- a/doc/source/reference/indexing.rst +++ b/doc/source/reference/indexing.rst @@ -250,7 +250,7 @@ IntervalIndex components IntervalIndex.is_overlapping IntervalIndex.get_loc IntervalIndex.get_indexer - IntervalIndex.set_closed + IntervalIndex.set_inclusive IntervalIndex.contains IntervalIndex.overlaps IntervalIndex.to_tuples diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index 56aae3039f7d6..9a6ddb388b626 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -155,7 +155,7 @@ from_breaks contains overlaps -set_closed +set_inclusive to_tuples %(extra_methods)s\ @@ -1385,9 +1385,11 @@ def closed(self) -> IntervalClosedType: Return an %(klass)s identical to the current one, but closed on the specified side. + .. deprecated:: 1.5.0 + Parameters ---------- - inclusive : {'left', 'right', 'both', 'neither'} + closed : {'left', 'right', 'both', 'neither'} Whether the intervals are closed on the left-side, right-side, both or neither. @@ -1420,8 +1422,58 @@ def closed(self) -> IntervalClosedType: ), } ) - @deprecate_kwarg(old_arg_name="closed", new_arg_name="inclusive") - def set_closed( + def set_closed(self: IntervalArrayT, closed: IntervalClosedType) -> IntervalArrayT: + warnings.warn( + "set_closed is deprecated and will be removed in a future version. " + "Use set_inclusive instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) + return self.set_inclusive(closed) + + _interval_shared_docs["set_inclusive"] = textwrap.dedent( + """ + Return an %(klass)s identical to the current one, but closed on the + specified side. + + .. versionadded:: 1.5 + + Parameters + ---------- + inclusive : {'left', 'right', 'both', 'neither'} + Whether the intervals are closed on the left-side, right-side, both + or neither. + + Returns + ------- + new_index : %(klass)s + + %(examples)s\ + """ + ) + + @Appender( + _interval_shared_docs["set_inclusive"] + % { + "klass": "IntervalArray", + "examples": textwrap.dedent( + """\ + Examples + -------- + >>> index = pd.arrays.IntervalArray.from_breaks(range(4), "right") + >>> index + + [(0, 1], (1, 2], (2, 3]] + Length: 3, dtype: interval[int64, right] + >>> index.set_inclusive('both') + + [[0, 1], [1, 2], [2, 3]] + Length: 3, dtype: interval[int64, both] + """ + ), + } + ) + def set_inclusive( self: IntervalArrayT, inclusive: IntervalClosedType ) -> IntervalArrayT: if inclusive not in VALID_CLOSED: diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 5f48be921f7c6..b1f839daa694d 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -179,7 +179,7 @@ def _new_IntervalIndex(cls, d): ), } ) -@inherit_names(["set_closed", "to_tuples"], IntervalArray, wrap=True) +@inherit_names(["set_closed", "set_inclusive", "to_tuples"], IntervalArray, wrap=True) @inherit_names( [ "__array__", diff --git a/pandas/tests/arrays/interval/test_interval.py b/pandas/tests/arrays/interval/test_interval.py index 7ca86408a7f59..073e6b6119b14 100644 --- a/pandas/tests/arrays/interval/test_interval.py +++ b/pandas/tests/arrays/interval/test_interval.py @@ -60,12 +60,12 @@ def test_is_empty(self, constructor, left, right, closed): class TestMethods: - @pytest.mark.parametrize("new_closed", ["left", "right", "both", "neither"]) - def test_set_closed(self, closed, new_closed): + @pytest.mark.parametrize("new_inclusive", ["left", "right", "both", "neither"]) + def test_set_inclusive(self, closed, new_inclusive): # GH 21670 array = IntervalArray.from_breaks(range(10), inclusive=closed) - result = array.set_closed(new_closed) - expected = IntervalArray.from_breaks(range(10), inclusive=new_closed) + result = array.set_inclusive(new_inclusive) + expected = IntervalArray.from_breaks(range(10), inclusive=new_inclusive) tm.assert_extension_array_equal(result, expected) @pytest.mark.parametrize( @@ -134,10 +134,10 @@ def test_set_na(self, left_right_dtypes): tm.assert_extension_array_equal(result, expected) - def test_setitem_mismatched_closed(self): + def test_setitem_mismatched_inclusive(self): arr = IntervalArray.from_breaks(range(4), "right") orig = arr.copy() - other = arr.set_closed("both") + other = arr.set_inclusive("both") msg = "'value.inclusive' is 'both', expected 'right'" with pytest.raises(ValueError, match=msg): @@ -488,17 +488,8 @@ def test_from_arrays_deprecation(): IntervalArray.from_arrays([0, 1, 2], [1, 2, 3], closed="right") -def test_set_closed_deprecated_closed(): +def test_set_closed_deprecated(): # GH#40245 array = IntervalArray.from_breaks(range(10)) with tm.assert_produces_warning(FutureWarning): array.set_closed(closed="both") - - -def test_set_closed_both_provided_deprecation(): - # GH#40245 - array = IntervalArray.from_breaks(range(10)) - msg = "Can only specify 'closed' or 'inclusive', not both." - with pytest.raises(TypeError, match=msg): - with tm.assert_produces_warning(FutureWarning): - array.set_closed(inclusive="both", closed="both") diff --git a/pandas/tests/indexes/interval/test_interval.py b/pandas/tests/indexes/interval/test_interval.py index 90497780311de..5bf29093152d8 100644 --- a/pandas/tests/indexes/interval/test_interval.py +++ b/pandas/tests/indexes/interval/test_interval.py @@ -871,21 +871,21 @@ def test_nbytes(self): expected = 64 # 4 * 8 * 2 assert result == expected - @pytest.mark.parametrize("new_closed", ["left", "right", "both", "neither"]) - def test_set_closed(self, name, closed, new_closed): + @pytest.mark.parametrize("new_inclusive", ["left", "right", "both", "neither"]) + def test_set_inclusive(self, name, closed, new_inclusive): # GH 21670 index = interval_range(0, 5, inclusive=closed, name=name) - result = index.set_closed(new_closed) - expected = interval_range(0, 5, inclusive=new_closed, name=name) + result = index.set_inclusive(new_inclusive) + expected = interval_range(0, 5, inclusive=new_inclusive, name=name) tm.assert_index_equal(result, expected) @pytest.mark.parametrize("bad_inclusive", ["foo", 10, "LEFT", True, False]) - def test_set_closed_errors(self, bad_inclusive): + def test_set_inclusive_errors(self, bad_inclusive): # GH 21670 index = interval_range(0, 5) msg = f"invalid option for 'inclusive': {bad_inclusive}" with pytest.raises(ValueError, match=msg): - index.set_closed(bad_inclusive) + index.set_inclusive(bad_inclusive) def test_is_all_dates(self): # GH 23576 From 15ec59031f0a1ed90aa0a5e01fc218e42072cd1c Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Fri, 8 Jul 2022 13:36:23 +0200 Subject: [PATCH 2/6] Remove set closed --- doc/source/reference/arrays.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/source/reference/arrays.rst b/doc/source/reference/arrays.rst index cd0ce581519a8..545e505f7f027 100644 --- a/doc/source/reference/arrays.rst +++ b/doc/source/reference/arrays.rst @@ -351,7 +351,6 @@ A collection of intervals may be stored in an :class:`arrays.IntervalArray`. arrays.IntervalArray.from_breaks arrays.IntervalArray.contains arrays.IntervalArray.overlaps - arrays.IntervalArray.set_closed arrays.IntervalArray.set_inclusive arrays.IntervalArray.to_tuples From c42f40c668a55d56fb557b11d7258004b6f6d4ca Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Fri, 8 Jul 2022 13:42:06 +0200 Subject: [PATCH 3/6] Revert "Remove set closed" This reverts commit 15ec59031f0a1ed90aa0a5e01fc218e42072cd1c. --- doc/source/reference/arrays.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/reference/arrays.rst b/doc/source/reference/arrays.rst index 545e505f7f027..cd0ce581519a8 100644 --- a/doc/source/reference/arrays.rst +++ b/doc/source/reference/arrays.rst @@ -351,6 +351,7 @@ A collection of intervals may be stored in an :class:`arrays.IntervalArray`. arrays.IntervalArray.from_breaks arrays.IntervalArray.contains arrays.IntervalArray.overlaps + arrays.IntervalArray.set_closed arrays.IntervalArray.set_inclusive arrays.IntervalArray.to_tuples From c2088ec2e4a55e0c98c498192997b5fc6010a3d2 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Fri, 8 Jul 2022 13:42:42 +0200 Subject: [PATCH 4/6] Add set closed --- doc/source/reference/indexing.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/reference/indexing.rst b/doc/source/reference/indexing.rst index e40f1b041a0cf..589a339a1ca60 100644 --- a/doc/source/reference/indexing.rst +++ b/doc/source/reference/indexing.rst @@ -250,6 +250,7 @@ IntervalIndex components IntervalIndex.is_overlapping IntervalIndex.get_loc IntervalIndex.get_indexer + IntervalIndex.set_closed IntervalIndex.set_inclusive IntervalIndex.contains IntervalIndex.overlaps From 1b543cad81e01529c81023c801ba7d6264e3f951 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Fri, 8 Jul 2022 14:39:22 +0200 Subject: [PATCH 5/6] Add set closed --- pandas/core/arrays/interval.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index 9a6ddb388b626..9685c4db51b67 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -155,6 +155,7 @@ from_breaks contains overlaps +set_closed set_inclusive to_tuples %(extra_methods)s\ From 8e78a6435c4ff2d894068f638858ddf01ae7467d Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Fri, 8 Jul 2022 19:41:41 +0200 Subject: [PATCH 6/6] Add whatsnew --- doc/source/whatsnew/v1.5.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 0b450fab53137..c9c523e7a2415 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -762,7 +762,7 @@ Other Deprecations - Deprecated the ``closed`` argument in :class:`IntervalIndex` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) - Deprecated the ``closed`` argument in :class:`IntervalDtype` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) - Deprecated the ``closed`` argument in :class:`.IntervalArray` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) -- Deprecated the ``closed`` argument in :class:`IntervalTree` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) +- Deprecated :meth:`.IntervalArray.set_closed` and :meth:`.IntervalIndex.set_closed` in favor of ``set_inclusive``; In a future version ``set_closed`` will get removed (:issue:`40245`) - Deprecated the ``closed`` argument in :class:`ArrowInterval` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) - Deprecated allowing ``unit="M"`` or ``unit="Y"`` in :class:`Timestamp` constructor with a non-round float value (:issue:`47267`) - Deprecated the ``display.column_space`` global configuration option (:issue:`7576`)