Skip to content

Commit

Permalink
Backport PR pandas-dev#56594 on branch 2.2.x (DEPR: the method is_anc…
Browse files Browse the repository at this point in the history
…hored() for offsets) (pandas-dev#56813)

Backport PR pandas-dev#56594: DEPR: the method is_anchored() for offsets

Co-authored-by: Natalia Mokeeva <[email protected]>
  • Loading branch information
meeseeksmachine and natmokval authored Jan 10, 2024
1 parent 24ea67f commit 922a671
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 33 deletions.
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v2.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -665,11 +665,13 @@ Other Deprecations
- Deprecated :func:`pd.core.internals.api.make_block`, use public APIs instead (:issue:`40226`)
- 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`)
- 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`)
- Deprecated :meth:`DateOffset.is_anchored`, use ``obj.n == 1`` for non-Tick subclasses (for Tick this was always False) (:issue:`55388`)
- Deprecated :meth:`DatetimeArray.__init__` and :meth:`TimedeltaArray.__init__`, use :func:`array` instead (:issue:`55623`)
- Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`)
- Deprecated :meth:`Series.ravel`, the underlying array is already 1D, so ravel is not necessary (:issue:`52511`)
- 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`)
- Deprecated :meth:`Series.view`, use :meth:`Series.astype` instead to change the dtype (:issue:`20251`)
- Deprecated :meth:`offsets.Tick.is_anchored`, use ``False`` instead (:issue:`55388`)
- Deprecated ``core.internals`` members ``Block``, ``ExtensionBlock``, and ``DatetimeTZBlock``, use public APIs instead (:issue:`55139`)
- Deprecated ``year``, ``month``, ``quarter``, ``day``, ``hour``, ``minute``, and ``second`` keywords in the :class:`PeriodIndex` constructor, use :meth:`PeriodIndex.from_fields` instead (:issue:`55960`)
- Deprecated accepting a type as an argument in :meth:`Index.view`, call without any arguments instead (:issue:`55709`)
Expand Down
54 changes: 52 additions & 2 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -756,18 +756,27 @@ cdef class BaseOffset:
raise ValueError(f"{self} is a non-fixed frequency")

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

.. deprecated:: 2.2.0
is_anchored is deprecated and will be removed in a future version.
Use ``obj.n == 1`` instead.

Examples
--------
>>> pd.DateOffset().is_anchored()
True
>>> pd.DateOffset(2).is_anchored()
False
"""
warnings.warn(
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
f"in a future version, please use \'obj.n == 1\' instead.",
FutureWarning,
stacklevel=find_stack_level(),
)
return self.n == 1

# ------------------------------------------------------------------
Expand Down Expand Up @@ -954,6 +963,27 @@ cdef class Tick(SingleConstructorOffset):
return True

def is_anchored(self) -> bool:
# GH#55388
"""
Return False.

.. deprecated:: 2.2.0
is_anchored is deprecated and will be removed in a future version.
Use ``False`` instead.

Examples
--------
>>> pd.offsets.Hour().is_anchored()
False
>>> pd.offsets.Hour(2).is_anchored()
False
"""
warnings.warn(
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
f"in a future version, please use False instead.",
FutureWarning,
stacklevel=find_stack_level(),
)
return False

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

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

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

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

@apply_wraps
Expand Down Expand Up @@ -3597,6 +3641,12 @@ cdef class FY5253Mixin(SingleConstructorOffset):
self.variation = state.pop("variation")

def is_anchored(self) -> bool:
warnings.warn(
f"{type(self).__name__}.is_anchored is deprecated and will be removed "
f"in a future version, please use \'obj.n == 1\' instead.",
FutureWarning,
stacklevel=find_stack_level(),
)
return (
self.n == 1 and self.startingMonth is not None and self.weekday is not None
)
Expand Down
4 changes: 1 addition & 3 deletions pandas/tests/indexes/interval/test_interval_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ def test_constructor_timestamp(self, closed, name, freq, periods, tz):
tm.assert_index_equal(result, expected)

# GH 20976: linspace behavior defined from start/end/periods
if not breaks.freq.is_anchored() and tz is None:
# matches expected only for non-anchored offsets and tz naive
# (anchored/DST transitions cause unequal spacing in expected)
if not breaks.freq.n == 1 and tz is None:
result = interval_range(
start=start, end=end, periods=periods, name=name, closed=closed
)
Expand Down
19 changes: 13 additions & 6 deletions pandas/tests/tseries/offsets/test_business_quarter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import pytest

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

def test_is_anchored(self):
assert BQuarterBegin(startingMonth=1).is_anchored()
assert BQuarterBegin().is_anchored()
assert not BQuarterBegin(2, startingMonth=1).is_anchored()
msg = "BQuarterBegin.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert BQuarterBegin(startingMonth=1).is_anchored()
assert BQuarterBegin().is_anchored()
assert not BQuarterBegin(2, startingMonth=1).is_anchored()

def test_offset_corner_case(self):
# corner
Expand Down Expand Up @@ -177,9 +181,12 @@ def test_repr(self):
assert repr(BQuarterEnd(startingMonth=1)) == expected

def test_is_anchored(self):
assert BQuarterEnd(startingMonth=1).is_anchored()
assert BQuarterEnd().is_anchored()
assert not BQuarterEnd(2, startingMonth=1).is_anchored()
msg = "BQuarterEnd.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert BQuarterEnd(startingMonth=1).is_anchored()
assert BQuarterEnd().is_anchored()
assert not BQuarterEnd(2, startingMonth=1).is_anchored()

def test_offset_corner_case(self):
# corner
Expand Down
22 changes: 13 additions & 9 deletions pandas/tests/tseries/offsets/test_fiscal.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pytest

from pandas import Timestamp
import pandas._testing as tm
from pandas.tests.tseries.offsets.common import (
WeekDay,
assert_is_on_offset,
Expand Down Expand Up @@ -295,15 +296,18 @@ def test_apply(self):

class TestFY5253LastOfMonthQuarter:
def test_is_anchored(self):
assert makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
).is_anchored()
assert makeFY5253LastOfMonthQuarter(
weekday=WeekDay.SAT, startingMonth=3, qtr_with_extra_week=4
).is_anchored()
assert not makeFY5253LastOfMonthQuarter(
2, startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
).is_anchored()
msg = "FY5253Quarter.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
).is_anchored()
assert makeFY5253LastOfMonthQuarter(
weekday=WeekDay.SAT, startingMonth=3, qtr_with_extra_week=4
).is_anchored()
assert not makeFY5253LastOfMonthQuarter(
2, startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
).is_anchored()

def test_equality(self):
assert makeFY5253LastOfMonthQuarter(
Expand Down
7 changes: 5 additions & 2 deletions pandas/tests/tseries/offsets/test_offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,11 @@ def test_default_constructor(self, dt):
assert (dt + DateOffset(2)) == datetime(2008, 1, 4)

def test_is_anchored(self):
assert not DateOffset(2).is_anchored()
assert DateOffset(1).is_anchored()
msg = "DateOffset.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert not DateOffset(2).is_anchored()
assert DateOffset(1).is_anchored()

def test_copy(self):
assert DateOffset(months=2).copy() == DateOffset(months=2)
Expand Down
19 changes: 13 additions & 6 deletions pandas/tests/tseries/offsets/test_quarter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import pytest

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

def test_is_anchored(self):
assert QuarterBegin(startingMonth=1).is_anchored()
assert QuarterBegin().is_anchored()
assert not QuarterBegin(2, startingMonth=1).is_anchored()
msg = "QuarterBegin.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert QuarterBegin(startingMonth=1).is_anchored()
assert QuarterBegin().is_anchored()
assert not QuarterBegin(2, startingMonth=1).is_anchored()

def test_offset_corner_case(self):
# corner
Expand Down Expand Up @@ -161,9 +165,12 @@ def test_repr(self):
assert repr(QuarterEnd(startingMonth=1)) == expected

def test_is_anchored(self):
assert QuarterEnd(startingMonth=1).is_anchored()
assert QuarterEnd().is_anchored()
assert not QuarterEnd(2, startingMonth=1).is_anchored()
msg = "QuarterEnd.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert QuarterEnd(startingMonth=1).is_anchored()
assert QuarterEnd().is_anchored()
assert not QuarterEnd(2, startingMonth=1).is_anchored()

def test_offset_corner_case(self):
# corner
Expand Down
5 changes: 4 additions & 1 deletion pandas/tests/tseries/offsets/test_ticks.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,10 @@ def test_tick_equalities(cls):

@pytest.mark.parametrize("cls", tick_classes)
def test_tick_offset(cls):
assert not cls().is_anchored()
msg = f"{cls.__name__}.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert not cls().is_anchored()


@pytest.mark.parametrize("cls", tick_classes)
Expand Down
12 changes: 8 additions & 4 deletions pandas/tests/tseries/offsets/test_week.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
WeekOfMonth,
)

import pandas._testing as tm
from pandas.tests.tseries.offsets.common import (
WeekDay,
assert_is_on_offset,
Expand All @@ -42,10 +43,13 @@ def test_corner(self):
Week(weekday=-1)

def test_is_anchored(self):
assert Week(weekday=0).is_anchored()
assert not Week().is_anchored()
assert not Week(2, weekday=2).is_anchored()
assert not Week(2).is_anchored()
msg = "Week.is_anchored is deprecated "

with tm.assert_produces_warning(FutureWarning, match=msg):
assert Week(weekday=0).is_anchored()
assert not Week().is_anchored()
assert not Week(2, weekday=2).is_anchored()
assert not Week(2).is_anchored()

offset_cases = []
# not business week
Expand Down

0 comments on commit 922a671

Please sign in to comment.