Skip to content

Commit 900c44c

Browse files
committed
deprecate is_anchored, fix tests
1 parent 8ce6740 commit 900c44c

File tree

3 files changed

+96
-42
lines changed

3 files changed

+96
-42
lines changed

pandas/_libs/tslibs/offsets.pyx

+90-39
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,12 @@ cdef class BaseOffset:
768768
>>> pd.DateOffset(2).is_anchored()
769769
False
770770
"""
771+
warnings.warn(
772+
f"{type(self).__name__}.is_anchored() is deprecated and will be removed "
773+
f"in a future version, please use {type(self).__name__}.n == 1 instead.",
774+
FutureWarning,
775+
stacklevel=find_stack_level(),
776+
)
771777
return self.n == 1
772778

773779
# ------------------------------------------------------------------
@@ -954,6 +960,12 @@ cdef class Tick(SingleConstructorOffset):
954960
return True
955961

956962
def is_anchored(self) -> bool:
963+
warnings.warn(
964+
f"{type(self).__name__}.is_anchored() is deprecated and will be removed "
965+
f"in a future version, please use False instead.",
966+
FutureWarning,
967+
stacklevel=find_stack_level(),
968+
)
957969
return False
958970

959971
# This is identical to BaseOffset.__hash__, but has to be redefined here
@@ -1766,7 +1778,7 @@ cdef class BusinessDay(BusinessMixin):
17661778
s -= hrs * 3600
17671779
mts = int(s / 60)
17681780
if mts != 0:
1769-
off_str += str(mts) + "Min"
1781+
off_str += str(mts) + "min"
17701782
s -= mts * 60
17711783
if s != 0:
17721784
off_str += str(s) + "s"
@@ -2663,6 +2675,13 @@ cdef class QuarterOffset(SingleConstructorOffset):
26632675
return f"{self._prefix}-{month}"
26642676

26652677
def is_anchored(self) -> bool:
2678+
warnings.warn(
2679+
f"{type(self).__name__}.is_anchored() is deprecated and will be removed "
2680+
f"in a future version, please use {type(self).__name__}.n == 1 "
2681+
f" and {type(self).__name__}.startingMonth is not None instead.",
2682+
FutureWarning,
2683+
stacklevel=find_stack_level(),
2684+
)
26662685
return self.n == 1 and self.startingMonth is not None
26672686

26682687
def is_on_offset(self, dt: datetime) -> bool:
@@ -3308,6 +3327,13 @@ cdef class Week(SingleConstructorOffset):
33083327
self._cache = state.pop("_cache", {})
33093328

33103329
def is_anchored(self) -> bool:
3330+
warnings.warn(
3331+
f"{type(self).__name__}.is_anchored() is deprecated and will be removed "
3332+
f"in a future version, please use {type(self).__name__}.n == 1 "
3333+
f" and {type(self).__name__}.weekday is not None instead.",
3334+
FutureWarning,
3335+
stacklevel=find_stack_level(),
3336+
)
33113337
return self.n == 1 and self.weekday is not None
33123338

33133339
@apply_wraps
@@ -3597,6 +3623,12 @@ cdef class FY5253Mixin(SingleConstructorOffset):
35973623
self.variation = state.pop("variation")
35983624

35993625
def is_anchored(self) -> bool:
3626+
warnings.warn(
3627+
f"{type(self).__name__}.is_anchored() is deprecated and will be removed "
3628+
f"in a future version, please use {type(self).__name__}.n == 1 instead.",
3629+
FutureWarning,
3630+
stacklevel=find_stack_level(),
3631+
)
36003632
return (
36013633
self.n == 1 and self.startingMonth is not None and self.weekday is not None
36023634
)
@@ -4654,36 +4686,13 @@ _lite_rule_alias = {
46544686
"BYE": "BYE-DEC", # BYearEnd(month=12),
46554687
"BYS": "BYS-JAN", # BYearBegin(month=1),
46564688

4657-
"Min": "min",
46584689
"min": "min",
46594690
"ms": "ms",
46604691
"us": "us",
46614692
"ns": "ns",
46624693
}
46634694

4664-
_dont_uppercase = {
4665-
"h",
4666-
"bh",
4667-
"cbh",
4668-
"MS",
4669-
"ms",
4670-
"s",
4671-
"me",
4672-
"qe",
4673-
"qe-dec",
4674-
"qe-jan",
4675-
"qe-feb",
4676-
"qe-mar",
4677-
"qe-apr",
4678-
"qe-may",
4679-
"qe-jun",
4680-
"qe-jul",
4681-
"qe-aug",
4682-
"qe-sep",
4683-
"qe-oct",
4684-
"qe-nov",
4685-
"ye",
4686-
}
4695+
_dont_uppercase = {"h", "bh", "cbh", "MS", "ms", "s"}
46874696

46884697

46894698
INVALID_FREQ_ERR_MSG = "Invalid frequency: {0}"
@@ -4702,7 +4711,29 @@ def _get_offset(name: str) -> BaseOffset:
47024711
--------
47034712
_get_offset('EOM') --> BMonthEnd(1)
47044713
"""
4705-
if name.lower() not in _dont_uppercase:
4714+
if (
4715+
name not in _lite_rule_alias
4716+
and (name.upper() in _lite_rule_alias)
4717+
and name != "ms"
4718+
):
4719+
warnings.warn(
4720+
f"\'{name}\' is deprecated and will be removed "
4721+
f"in a future version, please use \'{name.upper()}\' instead.",
4722+
FutureWarning,
4723+
stacklevel=find_stack_level(),
4724+
)
4725+
elif (
4726+
name not in _lite_rule_alias
4727+
and (name.lower() in _lite_rule_alias)
4728+
and name != "MS"
4729+
):
4730+
warnings.warn(
4731+
f"\'{name}\' is deprecated and will be removed "
4732+
f"in a future version, please use \'{name.lower()}\' instead.",
4733+
FutureWarning,
4734+
stacklevel=find_stack_level(),
4735+
)
4736+
if name not in _dont_uppercase:
47064737
name = name.upper()
47074738
name = _lite_rule_alias.get(name, name)
47084739
name = _lite_rule_alias.get(name.lower(), name)
@@ -4795,40 +4826,60 @@ cpdef to_offset(freq, bint is_period=False):
47954826

47964827
tups = zip(split[0::4], split[1::4], split[2::4])
47974828
for n, (sep, stride, name) in enumerate(tups):
4798-
if is_period is False and name in c_OFFSET_DEPR_FREQSTR:
4829+
if is_period is False and name.upper() in c_OFFSET_DEPR_FREQSTR:
47994830
warnings.warn(
48004831
f"\'{name}\' is deprecated and will be removed "
48014832
f"in a future version, please use "
4802-
f"\'{c_OFFSET_DEPR_FREQSTR.get(name)}\' instead.",
4833+
f"\'{c_OFFSET_DEPR_FREQSTR.get(name.upper())}\' instead.",
48034834
FutureWarning,
48044835
stacklevel=find_stack_level(),
48054836
)
4806-
name = c_OFFSET_DEPR_FREQSTR[name]
4807-
if is_period is True and name in c_REVERSE_OFFSET_DEPR_FREQSTR:
4808-
if name.startswith("Y"):
4837+
name = c_OFFSET_DEPR_FREQSTR[name.upper()]
4838+
elif (is_period is False and
4839+
name != name.upper() and
4840+
name.upper() in c_REVERSE_OFFSET_DEPR_FREQSTR):
4841+
warnings.warn(
4842+
f"\'{name}\' is deprecated and will be removed "
4843+
f"in a future version, please use "
4844+
f"\'{name.upper()}\' instead.",
4845+
FutureWarning,
4846+
stacklevel=find_stack_level(),
4847+
)
4848+
name = name.upper()
4849+
if is_period is True and name.upper() in c_REVERSE_OFFSET_DEPR_FREQSTR:
4850+
if name.upper().startswith("Y"):
48094851
raise ValueError(
4810-
f"for Period, please use \'Y{name[2:]}\' "
4852+
f"for Period, please use \'Y{name.upper()[2:]}\' "
48114853
f"instead of \'{name}\'"
48124854
)
4813-
if (name.startswith("B") or
4814-
name.startswith("S") or name.startswith("C")):
4855+
if (name.upper().startswith("B") or
4856+
name.upper().startswith("S") or
4857+
name.upper().startswith("C")):
48154858
raise ValueError(INVALID_FREQ_ERR_MSG.format(name))
48164859
else:
48174860
raise ValueError(
48184861
f"for Period, please use "
4819-
f"\'{c_REVERSE_OFFSET_DEPR_FREQSTR.get(name)}\' "
4862+
f"\'{c_REVERSE_OFFSET_DEPR_FREQSTR.get(name.upper())}\' "
48204863
f"instead of \'{name}\'"
48214864
)
4822-
elif is_period is True and name in c_OFFSET_DEPR_FREQSTR:
4823-
if name.startswith("A"):
4865+
elif is_period is True and name.upper() in c_OFFSET_DEPR_FREQSTR:
4866+
if name.upper().startswith("A"):
48244867
warnings.warn(
48254868
f"\'{name}\' is deprecated and will be removed in a future "
4826-
f"version, please use \'{c_DEPR_ABBREVS.get(name)}\' "
4869+
f"version, please use "
4870+
f"\'{c_DEPR_ABBREVS.get(name.upper())}\' instead.",
4871+
FutureWarning,
4872+
stacklevel=find_stack_level(),
4873+
)
4874+
if name.upper() != name:
4875+
warnings.warn(
4876+
f"\'{name}\' is deprecated and will be removed in "
4877+
f"a future version, please use \'{name.upper()}\' "
48274878
f"instead.",
48284879
FutureWarning,
48294880
stacklevel=find_stack_level(),
48304881
)
4831-
name = c_OFFSET_DEPR_FREQSTR.get(name)
4882+
name = c_OFFSET_DEPR_FREQSTR.get(name.upper())
48324883

48334884
if sep != "" and not sep.isspace():
48344885
raise ValueError("separator must be spaces")

pandas/tests/indexes/interval/test_interval_range.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +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:
87+
if not breaks.freq.n == 1 and tz is None:
8888
# matches expected only for non-anchored offsets and tz naive
8989
# (anchored/DST transitions cause unequal spacing in expected)
9090
result = interval_range(

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+
DateOffset(2).is_anchored()
632+
DateOffset(1).is_anchored()
630633

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

0 commit comments

Comments
 (0)