Skip to content

Commit 922a671

Browse files
Backport PR pandas-dev#56594 on branch 2.2.x (DEPR: the method is_anchored() for offsets) (pandas-dev#56813)
Backport PR pandas-dev#56594: DEPR: the method is_anchored() for offsets Co-authored-by: Natalia Mokeeva <[email protected]>
1 parent 24ea67f commit 922a671

File tree

9 files changed

+111
-33
lines changed

9 files changed

+111
-33
lines changed

doc/source/whatsnew/v2.2.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -665,11 +665,13 @@ Other Deprecations
665665
- Deprecated :func:`pd.core.internals.api.make_block`, use public APIs instead (:issue:`40226`)
666666
- Deprecated :func:`read_gbq` and :meth:`DataFrame.to_gbq`. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`)
667667
- Deprecated :meth:`.DataFrameGroupBy.fillna` and :meth:`.SeriesGroupBy.fillna`; use :meth:`.DataFrameGroupBy.ffill`, :meth:`.DataFrameGroupBy.bfill` for forward and backward filling or :meth:`.DataFrame.fillna` to fill with a single value (or the Series equivalents) (:issue:`55718`)
668+
- Deprecated :meth:`DateOffset.is_anchored`, use ``obj.n == 1`` for non-Tick subclasses (for Tick this was always False) (:issue:`55388`)
668669
- Deprecated :meth:`DatetimeArray.__init__` and :meth:`TimedeltaArray.__init__`, use :func:`array` instead (:issue:`55623`)
669670
- Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`)
670671
- Deprecated :meth:`Series.ravel`, the underlying array is already 1D, so ravel is not necessary (:issue:`52511`)
671672
- Deprecated :meth:`Series.resample` and :meth:`DataFrame.resample` with a :class:`PeriodIndex` (and the 'convention' keyword), convert to :class:`DatetimeIndex` (with ``.to_timestamp()``) before resampling instead (:issue:`53481`)
672673
- Deprecated :meth:`Series.view`, use :meth:`Series.astype` instead to change the dtype (:issue:`20251`)
674+
- Deprecated :meth:`offsets.Tick.is_anchored`, use ``False`` instead (:issue:`55388`)
673675
- Deprecated ``core.internals`` members ``Block``, ``ExtensionBlock``, and ``DatetimeTZBlock``, use public APIs instead (:issue:`55139`)
674676
- Deprecated ``year``, ``month``, ``quarter``, ``day``, ``hour``, ``minute``, and ``second`` keywords in the :class:`PeriodIndex` constructor, use :meth:`PeriodIndex.from_fields` instead (:issue:`55960`)
675677
- Deprecated accepting a type as an argument in :meth:`Index.view`, call without any arguments instead (:issue:`55709`)

pandas/_libs/tslibs/offsets.pyx

+52-2
Original file line numberDiff line numberDiff line change
@@ -756,18 +756,27 @@ cdef class BaseOffset:
756756
raise ValueError(f"{self} is a non-fixed frequency")
757757

758758
def is_anchored(self) -> bool:
759-
# TODO: Does this make sense for the general case? It would help
760-
# if there were a canonical docstring for what is_anchored means.
759+
# GH#55388
761760
"""
762761
Return boolean whether the frequency is a unit frequency (n=1).
763762

763+
.. deprecated:: 2.2.0
764+
is_anchored is deprecated and will be removed in a future version.
765+
Use ``obj.n == 1`` instead.
766+
764767
Examples
765768
--------
766769
>>> pd.DateOffset().is_anchored()
767770
True
768771
>>> pd.DateOffset(2).is_anchored()
769772
False
770773
"""
774+
warnings.warn(
775+
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
776+
f"in a future version, please use \'obj.n == 1\' instead.",
777+
FutureWarning,
778+
stacklevel=find_stack_level(),
779+
)
771780
return self.n == 1
772781

773782
# ------------------------------------------------------------------
@@ -954,6 +963,27 @@ cdef class Tick(SingleConstructorOffset):
954963
return True
955964

956965
def is_anchored(self) -> bool:
966+
# GH#55388
967+
"""
968+
Return False.
969+
970+
.. deprecated:: 2.2.0
971+
is_anchored is deprecated and will be removed in a future version.
972+
Use ``False`` instead.
973+
974+
Examples
975+
--------
976+
>>> pd.offsets.Hour().is_anchored()
977+
False
978+
>>> pd.offsets.Hour(2).is_anchored()
979+
False
980+
"""
981+
warnings.warn(
982+
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
983+
f"in a future version, please use False instead.",
984+
FutureWarning,
985+
stacklevel=find_stack_level(),
986+
)
957987
return False
958988

959989
# This is identical to BaseOffset.__hash__, but has to be redefined here
@@ -2663,6 +2693,13 @@ cdef class QuarterOffset(SingleConstructorOffset):
26632693
return f"{self._prefix}-{month}"
26642694

26652695
def is_anchored(self) -> bool:
2696+
warnings.warn(
2697+
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
2698+
f"in a future version, please use \'obj.n == 1 "
2699+
f"and obj.startingMonth is not None\' instead.",
2700+
FutureWarning,
2701+
stacklevel=find_stack_level(),
2702+
)
26662703
return self.n == 1 and self.startingMonth is not None
26672704

26682705
def is_on_offset(self, dt: datetime) -> bool:
@@ -3308,6 +3345,13 @@ cdef class Week(SingleConstructorOffset):
33083345
self._cache = state.pop("_cache", {})
33093346

33103347
def is_anchored(self) -> bool:
3348+
warnings.warn(
3349+
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
3350+
f"in a future version, please use \'obj.n == 1 "
3351+
f"and obj.weekday is not None\' instead.",
3352+
FutureWarning,
3353+
stacklevel=find_stack_level(),
3354+
)
33113355
return self.n == 1 and self.weekday is not None
33123356

33133357
@apply_wraps
@@ -3597,6 +3641,12 @@ cdef class FY5253Mixin(SingleConstructorOffset):
35973641
self.variation = state.pop("variation")
35983642

35993643
def is_anchored(self) -> bool:
3644+
warnings.warn(
3645+
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
3646+
f"in a future version, please use \'obj.n == 1\' instead.",
3647+
FutureWarning,
3648+
stacklevel=find_stack_level(),
3649+
)
36003650
return (
36013651
self.n == 1 and self.startingMonth is not None and self.weekday is not None
36023652
)

pandas/tests/indexes/interval/test_interval_range.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,7 @@ def test_constructor_timestamp(self, closed, name, freq, periods, tz):
8484
tm.assert_index_equal(result, expected)
8585

8686
# GH 20976: linspace behavior defined from start/end/periods
87-
if not breaks.freq.is_anchored() and tz is None:
88-
# matches expected only for non-anchored offsets and tz naive
89-
# (anchored/DST transitions cause unequal spacing in expected)
87+
if not breaks.freq.n == 1 and tz is None:
9088
result = interval_range(
9189
start=start, end=end, periods=periods, name=name, closed=closed
9290
)

pandas/tests/tseries/offsets/test_business_quarter.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import pytest
1111

12+
import pandas._testing as tm
1213
from pandas.tests.tseries.offsets.common import (
1314
assert_is_on_offset,
1415
assert_offset_equal,
@@ -54,9 +55,12 @@ def test_repr(self):
5455
assert repr(BQuarterBegin(startingMonth=1)) == expected
5556

5657
def test_is_anchored(self):
57-
assert BQuarterBegin(startingMonth=1).is_anchored()
58-
assert BQuarterBegin().is_anchored()
59-
assert not BQuarterBegin(2, startingMonth=1).is_anchored()
58+
msg = "BQuarterBegin.is_anchored is deprecated "
59+
60+
with tm.assert_produces_warning(FutureWarning, match=msg):
61+
assert BQuarterBegin(startingMonth=1).is_anchored()
62+
assert BQuarterBegin().is_anchored()
63+
assert not BQuarterBegin(2, startingMonth=1).is_anchored()
6064

6165
def test_offset_corner_case(self):
6266
# corner
@@ -177,9 +181,12 @@ def test_repr(self):
177181
assert repr(BQuarterEnd(startingMonth=1)) == expected
178182

179183
def test_is_anchored(self):
180-
assert BQuarterEnd(startingMonth=1).is_anchored()
181-
assert BQuarterEnd().is_anchored()
182-
assert not BQuarterEnd(2, startingMonth=1).is_anchored()
184+
msg = "BQuarterEnd.is_anchored is deprecated "
185+
186+
with tm.assert_produces_warning(FutureWarning, match=msg):
187+
assert BQuarterEnd(startingMonth=1).is_anchored()
188+
assert BQuarterEnd().is_anchored()
189+
assert not BQuarterEnd(2, startingMonth=1).is_anchored()
183190

184191
def test_offset_corner_case(self):
185192
# corner

pandas/tests/tseries/offsets/test_fiscal.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import pytest
88

99
from pandas import Timestamp
10+
import pandas._testing as tm
1011
from pandas.tests.tseries.offsets.common import (
1112
WeekDay,
1213
assert_is_on_offset,
@@ -295,15 +296,18 @@ def test_apply(self):
295296

296297
class TestFY5253LastOfMonthQuarter:
297298
def test_is_anchored(self):
298-
assert makeFY5253LastOfMonthQuarter(
299-
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
300-
).is_anchored()
301-
assert makeFY5253LastOfMonthQuarter(
302-
weekday=WeekDay.SAT, startingMonth=3, qtr_with_extra_week=4
303-
).is_anchored()
304-
assert not makeFY5253LastOfMonthQuarter(
305-
2, startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
306-
).is_anchored()
299+
msg = "FY5253Quarter.is_anchored is deprecated "
300+
301+
with tm.assert_produces_warning(FutureWarning, match=msg):
302+
assert makeFY5253LastOfMonthQuarter(
303+
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
304+
).is_anchored()
305+
assert makeFY5253LastOfMonthQuarter(
306+
weekday=WeekDay.SAT, startingMonth=3, qtr_with_extra_week=4
307+
).is_anchored()
308+
assert not makeFY5253LastOfMonthQuarter(
309+
2, startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
310+
).is_anchored()
307311

308312
def test_equality(self):
309313
assert makeFY5253LastOfMonthQuarter(

pandas/tests/tseries/offsets/test_offsets.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -625,8 +625,11 @@ def test_default_constructor(self, dt):
625625
assert (dt + DateOffset(2)) == datetime(2008, 1, 4)
626626

627627
def test_is_anchored(self):
628-
assert not DateOffset(2).is_anchored()
629-
assert DateOffset(1).is_anchored()
628+
msg = "DateOffset.is_anchored is deprecated "
629+
630+
with tm.assert_produces_warning(FutureWarning, match=msg):
631+
assert not DateOffset(2).is_anchored()
632+
assert DateOffset(1).is_anchored()
630633

631634
def test_copy(self):
632635
assert DateOffset(months=2).copy() == DateOffset(months=2)

pandas/tests/tseries/offsets/test_quarter.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import pytest
1111

12+
import pandas._testing as tm
1213
from pandas.tests.tseries.offsets.common import (
1314
assert_is_on_offset,
1415
assert_offset_equal,
@@ -53,9 +54,12 @@ def test_repr(self):
5354
assert repr(QuarterBegin(startingMonth=1)) == expected
5455

5556
def test_is_anchored(self):
56-
assert QuarterBegin(startingMonth=1).is_anchored()
57-
assert QuarterBegin().is_anchored()
58-
assert not QuarterBegin(2, startingMonth=1).is_anchored()
57+
msg = "QuarterBegin.is_anchored is deprecated "
58+
59+
with tm.assert_produces_warning(FutureWarning, match=msg):
60+
assert QuarterBegin(startingMonth=1).is_anchored()
61+
assert QuarterBegin().is_anchored()
62+
assert not QuarterBegin(2, startingMonth=1).is_anchored()
5963

6064
def test_offset_corner_case(self):
6165
# corner
@@ -161,9 +165,12 @@ def test_repr(self):
161165
assert repr(QuarterEnd(startingMonth=1)) == expected
162166

163167
def test_is_anchored(self):
164-
assert QuarterEnd(startingMonth=1).is_anchored()
165-
assert QuarterEnd().is_anchored()
166-
assert not QuarterEnd(2, startingMonth=1).is_anchored()
168+
msg = "QuarterEnd.is_anchored is deprecated "
169+
170+
with tm.assert_produces_warning(FutureWarning, match=msg):
171+
assert QuarterEnd(startingMonth=1).is_anchored()
172+
assert QuarterEnd().is_anchored()
173+
assert not QuarterEnd(2, startingMonth=1).is_anchored()
167174

168175
def test_offset_corner_case(self):
169176
# corner

pandas/tests/tseries/offsets/test_ticks.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,10 @@ def test_tick_equalities(cls):
339339

340340
@pytest.mark.parametrize("cls", tick_classes)
341341
def test_tick_offset(cls):
342-
assert not cls().is_anchored()
342+
msg = f"{cls.__name__}.is_anchored is deprecated "
343+
344+
with tm.assert_produces_warning(FutureWarning, match=msg):
345+
assert not cls().is_anchored()
343346

344347

345348
@pytest.mark.parametrize("cls", tick_classes)

pandas/tests/tseries/offsets/test_week.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
WeekOfMonth,
2222
)
2323

24+
import pandas._testing as tm
2425
from pandas.tests.tseries.offsets.common import (
2526
WeekDay,
2627
assert_is_on_offset,
@@ -42,10 +43,13 @@ def test_corner(self):
4243
Week(weekday=-1)
4344

4445
def test_is_anchored(self):
45-
assert Week(weekday=0).is_anchored()
46-
assert not Week().is_anchored()
47-
assert not Week(2, weekday=2).is_anchored()
48-
assert not Week(2).is_anchored()
46+
msg = "Week.is_anchored is deprecated "
47+
48+
with tm.assert_produces_warning(FutureWarning, match=msg):
49+
assert Week(weekday=0).is_anchored()
50+
assert not Week().is_anchored()
51+
assert not Week(2, weekday=2).is_anchored()
52+
assert not Week(2).is_anchored()
4953

5054
offset_cases = []
5155
# not business week

0 commit comments

Comments
 (0)