Skip to content

REF: cosmetic differences between DTA/TDA/PA comparison methods #30720

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
Jan 6, 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
19 changes: 14 additions & 5 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@
_INT64_DTYPE,
_NS_DTYPE,
is_categorical_dtype,
is_datetime64_any_dtype,
is_datetime64_dtype,
is_datetime64_ns_dtype,
is_datetime64tz_dtype,
is_dtype_equal,
is_extension_array_dtype,
is_float_dtype,
is_list_like,
is_object_dtype,
is_period_dtype,
is_string_dtype,
Expand Down Expand Up @@ -148,17 +150,22 @@ def wrapper(self, other):
# string that cannot be parsed to Timestamp
return invalid_comparison(self, other, op)

if isinstance(other, (datetime, np.datetime64)):
other = Timestamp(other)
if isinstance(other, self._recognized_scalars) or other is NaT:
other = self._scalar_type(other)
self._assert_tzawareness_compat(other)

result = op(self.asi8, other.value)
other_i8 = other.value

result = op(self.view("i8"), other_i8)
if isna(other):
result.fill(nat_result)
elif lib.is_scalar(other) or np.ndim(other) == 0:

elif not is_list_like(other):
return invalid_comparison(self, other, op)

elif len(other) != len(self):
raise ValueError("Lengths must match")

else:
if isinstance(other, list):
other = np.array(other)
Expand All @@ -178,7 +185,7 @@ def wrapper(self, other):
)
o_mask = isna(other)

elif not (is_datetime64_dtype(other) or is_datetime64tz_dtype(other)):
elif not cls._is_recognized_dtype(other.dtype):
# e.g. is_timedelta64_dtype(other)
return invalid_comparison(self, other, op)

Expand Down Expand Up @@ -239,6 +246,8 @@ class DatetimeArray(dtl.DatetimeLikeArrayMixin, dtl.TimelikeOps, dtl.DatelikeOps

_typ = "datetimearray"
_scalar_type = Timestamp
_recognized_scalars = (datetime, np.datetime64)
_is_recognized_dtype = is_datetime64_any_dtype

# define my properties & methods for delegation
_bool_ops = [
Expand Down
23 changes: 13 additions & 10 deletions pandas/core/arrays/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,6 @@ def _period_array_cmp(cls, op):
def wrapper(self, other):
ordinal_op = getattr(self.asi8, opname)

if is_list_like(other) and len(other) != len(self):
raise ValueError("Lengths must match")

if isinstance(other, str):
try:
other = self._scalar_from_string(other)
Expand All @@ -90,18 +87,22 @@ def wrapper(self, other):
other = Period(other, freq=self.freq)
result = ordinal_op(other.ordinal)

if isinstance(other, Period):
if isinstance(other, self._recognized_scalars) or other is NaT:
other = self._scalar_type(other)
self._check_compatible_with(other)

result = ordinal_op(other.ordinal)
other_i8 = self._unbox_scalar(other)

elif other is NaT:
result = np.empty(len(self.asi8), dtype=bool)
result.fill(nat_result)
result = op(self.view("i8"), other_i8)
if isna(other):
result.fill(nat_result)

elif not is_list_like(other):
return invalid_comparison(self, other, op)

elif len(other) != len(self):
raise ValueError("Lengths must match")

else:
if isinstance(other, list):
# TODO: could use pd.Index to do inference?
Expand All @@ -117,7 +118,7 @@ def wrapper(self, other):
)
o_mask = isna(other)

elif not is_period_dtype(other):
elif not cls._is_recognized_dtype(other.dtype):
# e.g. is_timedelta64_dtype(other)
return invalid_comparison(self, other, op)

Expand All @@ -126,7 +127,7 @@ def wrapper(self, other):

self._check_compatible_with(other)

result = ordinal_op(other.asi8)
result = op(self.view("i8"), other.view("i8"))
o_mask = other._isnan

if o_mask.any():
Expand Down Expand Up @@ -195,6 +196,8 @@ class PeriodArray(dtl.DatetimeLikeArrayMixin, dtl.DatelikeOps):
__array_priority__ = 1000
_typ = "periodarray" # ABCPeriodArray
_scalar_type = Period
_recognized_scalars = (Period,)
_is_recognized_dtype = is_period_dtype

# Names others delegate to us
_other_ops: List[str] = []
Expand Down
16 changes: 12 additions & 4 deletions pandas/core/arrays/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,13 @@ def wrapper(self, other):
# failed to parse as timedelta
return invalid_comparison(self, other, op)

if _is_convertible_to_td(other) or other is NaT:
other = Timedelta(other)
if isinstance(other, self._recognized_scalars) or other is NaT:
other = self._scalar_type(other)
self._check_compatible_with(other)

other_i8 = self._unbox_scalar(other)

result = op(self.view("i8"), other.value)
result = op(self.view("i8"), other_i8)
if isna(other):
result.fill(nat_result)

Expand All @@ -116,13 +119,15 @@ def wrapper(self, other):
)
o_mask = isna(other)

elif not is_timedelta64_dtype(other):
elif not cls._is_recognized_dtype(other.dtype):
# e.g. other is datetimearray
return invalid_comparison(self, other, op)

else:
other = type(self)._from_sequence(other)

self._check_compatible_with(other)

result = op(self.view("i8"), other.view("i8"))
o_mask = other._isnan

Expand Down Expand Up @@ -172,6 +177,9 @@ class TimedeltaArray(dtl.DatetimeLikeArrayMixin, dtl.TimelikeOps):

_typ = "timedeltaarray"
_scalar_type = Timedelta
_recognized_scalars = (timedelta, np.timedelta64, Tick)
Copy link
Contributor

Choose a reason for hiding this comment

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

at some point can u add some comments for each of the properties / methods here (and in all the subclasses)

eg it seems obvious was _is_recognized_scalar is now in this PR but best to have some comments

Copy link
Member Author

Choose a reason for hiding this comment

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

will comment in the next pass

_is_recognized_dtype = is_timedelta64_dtype

__array_priority__ = 1000
# define my properties & methods for delegation
_other_ops: List[str] = []
Expand Down