Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TYP: offsets #30897

Merged
merged 7 commits into from
Jan 10, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 45 additions & 45 deletions pandas/tseries/offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def apply_index(self, i):
"applied vectorized"
)

def is_anchored(self):
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.
return self.n == 1
Expand All @@ -378,7 +378,7 @@ def onOffset(self, dt):
)
return self.is_on_offset(dt)

def isAnchored(self):
def isAnchored(self) -> bool:
warnings.warn(
"isAnchored is a deprecated, use is_anchored instead",
FutureWarning,
Expand All @@ -389,7 +389,7 @@ def isAnchored(self):
# TODO: Combine this with BusinessMixin version by defining a whitelisted
# set of attributes on each object rather than the existing behavior of
# iterating over internal ``__dict__``
def _repr_attrs(self):
def _repr_attrs(self) -> str:
exclude = {"n", "inc", "normalize"}
attrs = []
for attr in sorted(self.__dict__):
Expand All @@ -405,7 +405,7 @@ def _repr_attrs(self):
return out

@property
def name(self):
def name(self) -> str:
return self.rule_code

def rollback(self, dt):
Expand Down Expand Up @@ -452,15 +452,15 @@ def is_on_offset(self, dt):

# way to get around weirdness with rule_code
@property
def _prefix(self):
def _prefix(self) -> str:
raise NotImplementedError("Prefix not defined")

@property
def rule_code(self):
def rule_code(self) -> str:
return self._prefix

@cache_readonly
def freqstr(self):
def freqstr(self) -> str:
try:
code = self.rule_code
except NotImplementedError:
Expand All @@ -480,7 +480,7 @@ def freqstr(self):

return fstr

def _offset_str(self):
def _offset_str(self) -> str:
return ""

@property
Expand Down Expand Up @@ -529,11 +529,11 @@ def offset(self):
# Alias for backward compat
return self._offset

def _repr_attrs(self):
def _repr_attrs(self) -> str:
if self.offset:
attrs = [f"offset={repr(self.offset)}"]
else:
attrs = None
attrs = []
out = ""
if attrs:
out += ": " + ", ".join(attrs)
Expand All @@ -553,7 +553,7 @@ def __init__(self, n=1, normalize=False, offset=timedelta(0)):
BaseOffset.__init__(self, n, normalize)
object.__setattr__(self, "_offset", offset)

def _offset_str(self):
def _offset_str(self) -> str:
def get_str(td):
off_str = ""
if td.days > 0:
Expand Down Expand Up @@ -649,7 +649,7 @@ def apply_index(self, i):
result = shifted.to_timestamp() + time
return result

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
return dt.weekday() < 5
Expand Down Expand Up @@ -1087,7 +1087,7 @@ def apply(self, other):
def apply_index(self, i):
raise NotImplementedError

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
day64 = _to_dt64(dt, "datetime64[D]")
Expand Down Expand Up @@ -1134,14 +1134,14 @@ class MonthOffset(SingleConstructorOffset):
__init__ = BaseOffset.__init__

@property
def name(self):
def name(self) -> str:
if self.is_anchored:
return self.rule_code
else:
month = ccalendar.MONTH_ALIASES[self.n]
return f"{self.code_rule}-{month}"

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
return dt.day == self._get_offset_day(dt)
Expand Down Expand Up @@ -1333,7 +1333,7 @@ def _from_name(cls, suffix=None):
return cls(day_of_month=suffix)

@property
def rule_code(self):
def rule_code(self) -> str:
suffix = f"-{self.day_of_month}"
return self._prefix + suffix

Expand Down Expand Up @@ -1429,7 +1429,7 @@ class SemiMonthEnd(SemiMonthOffset):
_prefix = "SM"
_min_day_of_month = 1

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
days_in_month = ccalendar.get_days_in_month(dt.year, dt.month)
Expand Down Expand Up @@ -1487,7 +1487,7 @@ class SemiMonthBegin(SemiMonthOffset):

_prefix = "SMS"

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
return dt.day in (1, self.day_of_month)
Expand Down Expand Up @@ -1556,7 +1556,7 @@ def __init__(self, n=1, normalize=False, weekday=None):
if self.weekday < 0 or self.weekday > 6:
raise ValueError(f"Day must be 0<=day<=6, got {self.weekday}")

def is_anchored(self):
def is_anchored(self) -> bool:
return self.n == 1 and self.weekday is not None

@apply_wraps
Expand Down Expand Up @@ -1632,15 +1632,15 @@ def _end_apply_index(self, dtindex):

return base + off + Timedelta(1, "ns") - Timedelta(1, "D")

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
elif self.weekday is None:
return True
return dt.weekday() == self.weekday

@property
def rule_code(self):
def rule_code(self) -> str:
suffix = ""
if self.weekday is not None:
weekday = ccalendar.int_to_weekday[self.weekday]
Expand Down Expand Up @@ -1717,7 +1717,7 @@ def __init__(self, n=1, normalize=False, week=0, weekday=0):
if self.week < 0 or self.week > 3:
raise ValueError(f"Week must be 0<=week<=3, got {self.week}")

def _get_offset_day(self, other):
def _get_offset_day(self, other: datetime) -> int:
"""
Find the day in the same month as other that has the same
weekday as self.weekday and is the self.week'th such day in the month.
Expand All @@ -1736,7 +1736,7 @@ def _get_offset_day(self, other):
return 1 + shift_days + self.week * 7

@property
def rule_code(self):
def rule_code(self) -> str:
weekday = ccalendar.int_to_weekday.get(self.weekday, "")
return f"{self._prefix}-{self.week + 1}{weekday}"

Expand Down Expand Up @@ -1785,7 +1785,7 @@ def __init__(self, n=1, normalize=False, weekday=0):
if self.weekday < 0 or self.weekday > 6:
raise ValueError(f"Day must be 0<=day<=6, got {self.weekday}")

def _get_offset_day(self, other):
def _get_offset_day(self, other: datetime) -> int:
"""
Find the day in the same month as other that has the same
weekday as self.weekday and is the last such day in the month.
Expand All @@ -1805,7 +1805,7 @@ def _get_offset_day(self, other):
return dim - shift_days

@property
def rule_code(self):
def rule_code(self) -> str:
weekday = ccalendar.int_to_weekday.get(self.weekday, "")
return f"{self._prefix}-{weekday}"

Expand Down Expand Up @@ -1842,7 +1842,7 @@ def __init__(self, n=1, normalize=False, startingMonth=None):
startingMonth = self._default_startingMonth
object.__setattr__(self, "startingMonth", startingMonth)

def is_anchored(self):
def is_anchored(self) -> bool:
return self.n == 1 and self.startingMonth is not None

@classmethod
Expand All @@ -1856,7 +1856,7 @@ def _from_name(cls, suffix=None):
return cls(**kwargs)

@property
def rule_code(self):
def rule_code(self) -> str:
month = ccalendar.MONTH_ALIASES[self.startingMonth]
return f"{self._prefix}-{month}"

Expand All @@ -1874,7 +1874,7 @@ def apply(self, other):
months = qtrs * 3 - months_since
return shift_month(other, months, self._day_opt)

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
mod_month = (dt.month - self.startingMonth) % 3
Expand Down Expand Up @@ -1953,7 +1953,7 @@ class YearOffset(DateOffset):
_adjust_dst = True
_attributes = frozenset(["n", "normalize", "month"])

def _get_offset_day(self, other):
def _get_offset_day(self, other: datetime) -> int:
# override BaseOffset method to use self.month instead of other.month
# TODO: there may be a more performant way to do this
return liboffsets.get_day_of_month(
Expand All @@ -1977,7 +1977,7 @@ def apply_index(self, dtindex):
shifted, freq=dtindex.freq, dtype=dtindex.dtype
)

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
return dt.month == self.month and dt.day == self._get_offset_day(dt)
Expand All @@ -1999,7 +1999,7 @@ def _from_name(cls, suffix=None):
return cls(**kwargs)

@property
def rule_code(self):
def rule_code(self) -> str:
month = ccalendar.MONTH_ALIASES[self.month]
return f"{self._prefix}-{month}"

Expand Down Expand Up @@ -2117,12 +2117,12 @@ def __init__(
if self.variation not in ["nearest", "last"]:
raise ValueError(f"{self.variation} is not a valid variation")

def is_anchored(self):
def is_anchored(self) -> bool:
return (
self.n == 1 and self.startingMonth is not None and self.weekday is not None
)

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
dt = datetime(dt.year, dt.month, dt.day)
Expand Down Expand Up @@ -2217,18 +2217,18 @@ def get_year_end(self, dt):
return target_date + timedelta(days_forward - 7)

@property
def rule_code(self):
def rule_code(self) -> str:
prefix = self._prefix
suffix = self.get_rule_code_suffix()
return f"{prefix}-{suffix}"

def _get_suffix_prefix(self):
def _get_suffix_prefix(self) -> str:
if self.variation == "nearest":
return "N"
else:
return "L"

def get_rule_code_suffix(self):
def get_rule_code_suffix(self) -> str:
prefix = self._get_suffix_prefix()
month = ccalendar.MONTH_ALIASES[self.startingMonth]
weekday = ccalendar.int_to_weekday[self.weekday]
Expand Down Expand Up @@ -2346,7 +2346,7 @@ def _offset(self):
variation=self.variation,
)

def is_anchored(self):
def is_anchored(self) -> bool:
return self.n == 1 and self._offset.is_anchored()

def _rollback_to_year(self, other):
Expand Down Expand Up @@ -2434,7 +2434,7 @@ def get_weeks(self, dt):

return ret

def year_has_extra_week(self, dt):
def year_has_extra_week(self, dt: datetime) -> bool:
# Avoid round-down errors --> normalize to get
# e.g. '370D' instead of '360D23H'
norm = Timestamp(dt).normalize().tz_localize(None)
Expand All @@ -2445,7 +2445,7 @@ def year_has_extra_week(self, dt):
assert weeks_in_year in [52, 53], weeks_in_year
return weeks_in_year == 53

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
if self._offset.is_on_offset(dt):
Expand All @@ -2463,7 +2463,7 @@ def is_on_offset(self, dt):
return False

@property
def rule_code(self):
def rule_code(self) -> str:
suffix = self._offset.get_rule_code_suffix()
qtr = self.qtr_with_extra_week
return f"{self._prefix}-{suffix}-{qtr}"
Expand Down Expand Up @@ -2516,7 +2516,7 @@ def apply(self, other):
)
return new

def is_on_offset(self, dt):
def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt):
return False
return date(dt.year, dt.month, dt.day) == easter(dt.year)
Expand Down Expand Up @@ -2596,7 +2596,7 @@ def __eq__(self, other: Any) -> bool:

# This is identical to DateOffset.__hash__, but has to be redefined here
# for Python 3, because we've redefined __eq__.
def __hash__(self):
def __hash__(self) -> int:
return hash(self._params)

def __ne__(self, other):
Expand All @@ -2617,7 +2617,7 @@ def __ne__(self, other):
return True

@property
def delta(self):
def delta(self) -> Timedelta:
return self.n * self._inc

@property
Expand Down Expand Up @@ -2648,11 +2648,11 @@ def apply(self, other):

raise ApplyTypeError(f"Unhandled type: {type(other).__name__}")

def is_anchored(self):
def is_anchored(self) -> bool:
return False


def _delta_to_tick(delta):
def _delta_to_tick(delta: timedelta) -> Tick:
if delta.microseconds == 0 and getattr(delta, "nanoseconds", 0) == 0:
# nanoseconds only for pd.Timedelta
if delta.seconds == 0:
Expand Down