Skip to content

REF: implement _with_freq, use _from_sequence less #32849

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

Merged
merged 1 commit into from
Mar 22, 2020
Merged
Show file tree
Hide file tree
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
32 changes: 30 additions & 2 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,34 @@ def floor(self, freq, ambiguous="raise", nonexistent="raise"):
def ceil(self, freq, ambiguous="raise", nonexistent="raise"):
return self._round(freq, RoundTo.PLUS_INFTY, ambiguous, nonexistent)

def _with_freq(self, freq):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional[Union[Dateoffset, str]]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returns Union[DTA,TDI,PA] (but I think we have a type for this)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just tried this and it looks like its going to turn into a yak-shaving event, prefer to do that separately

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kk, followup if you can

"""
Helper to set our freq in-place, returning self to allow method chaining.

Parameters
----------
freq : DateOffset, None, or "infer"

Returns
-------
self
"""
# GH#29843
if freq is None:
# Always valid
pass
elif len(self) == 0 and isinstance(freq, DateOffset):
# Always valid. In the TimedeltaArray case, we assume this
# is a Tick offset.
pass
else:
# As an internal method, we can ensure this assertion always holds
assert freq == "infer"
freq = frequencies.to_offset(self.inferred_freq)

self._freq = freq
return self


class DatetimeLikeArrayMixin(ExtensionOpsMixin, AttributesMixin, ExtensionArray):
"""
Expand Down Expand Up @@ -1157,7 +1185,7 @@ def _add_timedeltalike_scalar(self, other):
if new_freq is not None:
# fastpath that doesnt require inference
return type(self)(new_values, dtype=self.dtype, freq=new_freq)
return type(self)._from_sequence(new_values, dtype=self.dtype, freq="infer")
return type(self)(new_values, dtype=self.dtype)._with_freq("infer")

def _add_timedelta_arraylike(self, other):
"""
Expand Down Expand Up @@ -1187,7 +1215,7 @@ def _add_timedelta_arraylike(self, other):
mask = (self._isnan) | (other._isnan)
new_values[mask] = iNaT

return type(self)._from_sequence(new_values, dtype=self.dtype, freq="infer")
return type(self)(new_values, dtype=self.dtype)._with_freq("infer")

def _add_nat(self):
"""
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ def _add_offset(self, offset):
# GH#30336 _from_sequence won't be able to infer self.tz
return type(self)._from_sequence(result).tz_localize(self.tz)

return type(self)._from_sequence(result, freq="infer")
return type(self)._from_sequence(result)._with_freq("infer")

def _sub_datetimelike_scalar(self, other):
# subtract a datetime from myself, yielding a ndarray[timedelta64[ns]]
Expand Down Expand Up @@ -1031,7 +1031,7 @@ def normalize(self):
new_values[not_null] = new_values[not_null] - adjustment
else:
new_values = conversion.normalize_i8_timestamps(self.asi8, self.tz)
return type(self)._from_sequence(new_values, freq="infer").tz_localize(self.tz)
return type(self)(new_values)._with_freq("infer").tz_localize(self.tz)

def to_period(self, freq=None):
"""
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/arrays/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ def _from_sequence(
validate_dtype_freq(scalars.dtype, freq)
if copy:
scalars = scalars.copy()
assert isinstance(scalars, PeriodArray) # for mypy
return scalars

periods = np.asarray(scalars, dtype=object)
Expand Down Expand Up @@ -452,7 +453,7 @@ def to_timestamp(self, freq=None, how="start"):
new_data = self.asfreq(freq, how=how)

new_data = libperiod.periodarr_to_dt64arr(new_data.asi8, base)
return DatetimeArray._from_sequence(new_data, freq="infer")
return DatetimeArray(new_data)._with_freq("infer")

# --------------------------------------------------------------------

Expand Down
16 changes: 2 additions & 14 deletions pandas/core/indexes/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
from pandas.core.ops import get_op_result_name
from pandas.core.tools.timedeltas import to_timedelta

from pandas.tseries.frequencies import DateOffset, to_offset
from pandas.tseries.frequencies import DateOffset

_index_doc_kwargs = dict(ibase._index_doc_kwargs)

Expand Down Expand Up @@ -623,19 +623,7 @@ def _set_freq(self, freq):
freq : DateOffset, None, or "infer"
"""
# GH#29843
if freq is None:
# Always valid
pass
elif len(self) == 0 and isinstance(freq, DateOffset):
# Always valid. In the TimedeltaIndex case, we assume this
# is a Tick offset.
pass
else:
# As an internal method, we can ensure this assertion always holds
assert freq == "infer"
freq = to_offset(self.inferred_freq)

self._data._freq = freq
self._data._with_freq(freq)

def _shallow_copy(self, values=None, name: Label = lib.no_default):
name = self.name if name is lib.no_default else name
Expand Down