From ab51981b13300fdc10d81308bd5a293b8e729838 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Sat, 22 Jan 2022 01:22:29 +0000 Subject: [PATCH] Backport PR #45519: EA interface: rename ExtensionArray._hasnans to ._hasna (#45543) --- pandas/core/arrays/base.py | 11 +++++++---- pandas/core/arrays/datetimelike.py | 6 +++--- pandas/core/arrays/datetimes.py | 4 ++-- pandas/core/arrays/period.py | 10 +++++----- pandas/core/arrays/timedeltas.py | 4 ++-- pandas/core/indexes/datetimelike.py | 2 +- pandas/tests/extension/base/constructors.py | 5 +++++ 7 files changed, 25 insertions(+), 17 deletions(-) diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index c16c404d56295..d955d8e583f1c 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -427,7 +427,7 @@ def __contains__(self, item: object) -> bool | np.bool_: if not self._can_hold_na: return False elif item is self.dtype.na_value or isinstance(item, self.dtype.type): - return self._hasnans + return self._hasna else: return False else: @@ -606,7 +606,7 @@ def isna(self) -> np.ndarray | ExtensionArraySupportsAnyAll: raise AbstractMethodError(self) @property - def _hasnans(self) -> bool: + def _hasna(self) -> bool: # GH#22680 """ Equivalent to `self.isna().any()`. @@ -698,7 +698,7 @@ def argmin(self, skipna: bool = True) -> int: ExtensionArray.argmax """ validate_bool_kwarg(skipna, "skipna") - if not skipna and self._hasnans: + if not skipna and self._hasna: raise NotImplementedError return nargminmax(self, "argmin") @@ -722,7 +722,7 @@ def argmax(self, skipna: bool = True) -> int: ExtensionArray.argmin """ validate_bool_kwarg(skipna, "skipna") - if not skipna and self._hasnans: + if not skipna and self._hasna: raise NotImplementedError return nargminmax(self, "argmax") @@ -1534,6 +1534,9 @@ def _empty(cls, shape: Shape, dtype: ExtensionDtype): ExtensionDtype.empty ExtensionDtype.empty is the 'official' public version of this API. """ + # Implementer note: while ExtensionDtype.empty is the public way to + # call this method, it is still required to implement this `_empty` + # method as well (it is called internally in pandas) obj = cls._from_sequence([], dtype=dtype) taker = np.broadcast_to(np.intp(-1), shape) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index c752e0ddca88e..c845d9c8cdbde 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -841,7 +841,7 @@ def _isnan(self) -> npt.NDArray[np.bool_]: return self.asi8 == iNaT @property # NB: override with cache_readonly in immutable subclasses - def _hasnans(self) -> bool: + def _hasna(self) -> bool: """ return if I have any nans; enables various perf speedups """ @@ -866,7 +866,7 @@ def _maybe_mask_results( This is an internal routine. """ - if self._hasnans: + if self._hasna: if convert: result = result.astype(convert) if fill_value is None: @@ -1125,7 +1125,7 @@ def _add_timedelta_arraylike(self, other): new_values = checked_add_with_arr( self_i8, other_i8, arr_mask=self._isnan, b_mask=other._isnan ) - if self._hasnans or other._hasnans: + if self._hasna or other._hasna: mask = self._isnan | other._isnan np.putmask(new_values, mask, iNaT) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 03808b214b048..00d5f113e16e0 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -738,7 +738,7 @@ def _sub_datetime_arraylike(self, other): other_i8 = other.asi8 arr_mask = self._isnan | other._isnan new_values = checked_add_with_arr(self_i8, -other_i8, arr_mask=arr_mask) - if self._hasnans or other._hasnans: + if self._hasna or other._hasna: np.putmask(new_values, arr_mask, iNaT) return new_values.view("timedelta64[ns]") @@ -1356,7 +1356,7 @@ def isocalendar(self) -> DataFrame: iso_calendar_df = DataFrame( sarray, columns=["year", "week", "day"], dtype="UInt32" ) - if self._hasnans: + if self._hasna: iso_calendar_df.iloc[self._isnan] = None return iso_calendar_df diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 487b51735bd4e..04cc70b7efa6a 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -548,7 +548,7 @@ def _time_shift(self, periods: int, freq=None) -> PeriodArray: f"{type(self).__name__}._time_shift" ) values = self.asi8 + periods * self.freq.n - if self._hasnans: + if self._hasna: values[self._isnan] = iNaT return type(self)(values, freq=self.freq) @@ -618,7 +618,7 @@ def asfreq(self, freq=None, how: str = "E") -> PeriodArray: new_data = period_asfreq_arr(ordinal, base1, base2, end) - if self._hasnans: + if self._hasna: new_data[self._isnan] = iNaT return type(self)(new_data, freq=freq) @@ -645,7 +645,7 @@ def _format_native_types( else: formatter = lambda dt: str(dt) - if self._hasnans: + if self._hasna: mask = self._isnan values[mask] = na_rep imask = ~mask @@ -712,7 +712,7 @@ def _sub_period(self, other): new_data = asi8 - other.ordinal new_data = np.array([self.freq * x for x in new_data]) - if self._hasnans: + if self._hasna: new_data[self._isnan] = NaT return new_data @@ -739,7 +739,7 @@ def _sub_period_array(self, other): ) new_values = np.array([self.freq.base * x for x in new_values]) - if self._hasnans or other._hasnans: + if self._hasna or other._hasna: mask = self._isnan | other._isnan new_values[mask] = NaT return new_values diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 79387cc2584da..6ea24359c01b1 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -82,7 +82,7 @@ def _field_accessor(name: str, alias: str, docstring: str): def f(self) -> np.ndarray: values = self.asi8 result = get_timedelta_field(values, alias) - if self._hasnans: + if self._hasna: result = self._maybe_mask_results( result, fill_value=None, convert="float64" ) @@ -911,7 +911,7 @@ def components(self) -> DataFrame: "microseconds", "nanoseconds", ] - hasnans = self._hasnans + hasnans = self._hasna if hasnans: def f(x): diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 589b92f392ca8..8e94d72752b33 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -96,7 +96,7 @@ class DatetimeIndexOpsMixin(NDArrayBackedExtensionIndex): hasnans = cast( bool, cache_readonly( - DatetimeLikeArrayMixin._hasnans.fget # type: ignore[attr-defined] + DatetimeLikeArrayMixin._hasna.fget # type: ignore[attr-defined] ), ) diff --git a/pandas/tests/extension/base/constructors.py b/pandas/tests/extension/base/constructors.py index c86054aed7e4d..b9f8f8512a995 100644 --- a/pandas/tests/extension/base/constructors.py +++ b/pandas/tests/extension/base/constructors.py @@ -135,3 +135,8 @@ def test_empty(self, dtype): assert isinstance(result2, cls) assert result2.dtype == dtype assert result2.shape == (4,) + + result2 = dtype.empty(4) + assert isinstance(result2, cls) + assert result2.dtype == dtype + assert result2.shape == (4,)