Skip to content

Commit 06dac44

Browse files
authored
CLN: Index methods incorrectly assuming object dtype (#45767)
1 parent 71f5a74 commit 06dac44

File tree

5 files changed

+29
-39
lines changed

5 files changed

+29
-39
lines changed

pandas/core/indexes/base.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,6 @@ def _outer_indexer(
391391
_comparables: list[str] = ["name"]
392392
_attributes: list[str] = ["name"]
393393
_is_numeric_dtype: bool = False
394-
_can_hold_na: bool = True
395394
_can_hold_strings: bool = True
396395

397396
# Whether this index is a NumericIndex, but not a Int64Index, Float64Index,
@@ -2206,6 +2205,20 @@ def _get_grouper_for_level(self, mapper, *, level=None):
22062205
# --------------------------------------------------------------------
22072206
# Introspection Methods
22082207

2208+
@cache_readonly
2209+
@final
2210+
def _can_hold_na(self) -> bool:
2211+
if isinstance(self.dtype, ExtensionDtype):
2212+
if isinstance(self.dtype, IntervalDtype):
2213+
# FIXME(GH#45720): this is inaccurate for integer-backed
2214+
# IntervalArray, but without it other.categories.take raises
2215+
# in IntervalArray._cmp_method
2216+
return True
2217+
return self.dtype._can_hold_na
2218+
if self.dtype.kind in ["i", "u", "b"]:
2219+
return False
2220+
return True
2221+
22092222
@final
22102223
@property
22112224
def is_monotonic(self) -> bool:
@@ -2662,10 +2675,21 @@ def inferred_type(self) -> str_t:
26622675
return lib.infer_dtype(self._values, skipna=False)
26632676

26642677
@cache_readonly
2678+
@final
26652679
def _is_all_dates(self) -> bool:
26662680
"""
26672681
Whether or not the index values only consist of dates.
26682682
"""
2683+
2684+
if needs_i8_conversion(self.dtype):
2685+
return True
2686+
elif self.dtype != _dtype_obj:
2687+
# TODO(ExtensionIndex): 3rd party EA might override?
2688+
# Note: this includes IntervalIndex, even when the left/right
2689+
# contain datetime-like objects.
2690+
return False
2691+
elif self._is_multi:
2692+
return False
26692693
return is_datetime_array(ensure_object(self._values))
26702694

26712695
@cache_readonly
@@ -6159,6 +6183,10 @@ def _is_comparable_dtype(self, dtype: DtypeObj) -> bool:
61596183
"""
61606184
Can we compare values of the given dtype to our own?
61616185
"""
6186+
if self.dtype.kind == "b":
6187+
return dtype.kind == "b"
6188+
elif is_numeric_dtype(self.dtype):
6189+
return is_numeric_dtype(dtype)
61626190
return True
61636191

61646192
@final

pandas/core/indexes/datetimelike.py

-6
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ class DatetimeIndexOpsMixin(NDArrayBackedExtensionIndex):
100100
),
101101
)
102102

103-
@property
104-
def _is_all_dates(self) -> bool:
105-
return True
106-
107103
# ------------------------------------------------------------------------
108104

109105
def equals(self, other: Any) -> bool:
@@ -151,8 +147,6 @@ def __contains__(self, key: Any) -> bool:
151147
return False
152148
return True
153149

154-
_can_hold_na = True
155-
156150
def _convert_tolerance(self, tolerance, target):
157151
tolerance = np.asarray(to_timedelta(tolerance).to_numpy())
158152
return super()._convert_tolerance(tolerance, target)

pandas/core/indexes/interval.py

-8
Original file line numberDiff line numberDiff line change
@@ -897,14 +897,6 @@ def _intersection_non_unique(self, other: IntervalIndex) -> IntervalIndex:
897897

898898
# --------------------------------------------------------------------
899899

900-
@property
901-
def _is_all_dates(self) -> bool:
902-
"""
903-
This is False even when left/right contain datetime-like objects,
904-
as the check is done on the Interval itself
905-
"""
906-
return False
907-
908900
def _get_engine_target(self) -> np.ndarray:
909901
# Note: we _could_ use libjoin functions by either casting to object
910902
# dtype or constructing tuples (faster than constructing Intervals)

pandas/core/indexes/multi.py

-4
Original file line numberDiff line numberDiff line change
@@ -1841,10 +1841,6 @@ def to_flat_index(self) -> Index:
18411841
"""
18421842
return Index(self._values, tupleize_cols=False)
18431843

1844-
@property
1845-
def _is_all_dates(self) -> bool:
1846-
return False
1847-
18481844
def is_lexsorted(self) -> bool:
18491845
warnings.warn(
18501846
"MultiIndex.is_lexsorted is deprecated as a public function, "

pandas/core/indexes/numeric.py

-20
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
)
1515
from pandas._typing import (
1616
Dtype,
17-
DtypeObj,
1817
npt,
1918
)
2019
from pandas.util._decorators import (
@@ -91,14 +90,6 @@ class NumericIndex(Index):
9190
_can_hold_strings = False
9291
_is_backward_compat_public_numeric_index: bool = True
9392

94-
# error: Signature of "_can_hold_na" incompatible with supertype "Index"
95-
@cache_readonly
96-
def _can_hold_na(self) -> bool: # type: ignore[override]
97-
if is_float_dtype(self.dtype):
98-
return True
99-
else:
100-
return False
101-
10293
_engine_types: dict[np.dtype, type[libindex.IndexEngine]] = {
10394
np.dtype(np.int8): libindex.Int8Engine,
10495
np.dtype(np.int16): libindex.Int16Engine,
@@ -268,10 +259,6 @@ def _convert_tolerance(self, tolerance, target):
268259
)
269260
return tolerance
270261

271-
def _is_comparable_dtype(self, dtype: DtypeObj) -> bool:
272-
# If we ever have BoolIndex or ComplexIndex, this may need to be tightened
273-
return is_numeric_dtype(dtype)
274-
275262
@classmethod
276263
def _assert_safe_casting(cls, data: np.ndarray, subarr: np.ndarray) -> None:
277264
"""
@@ -284,13 +271,6 @@ def _assert_safe_casting(cls, data: np.ndarray, subarr: np.ndarray) -> None:
284271
if not np.array_equal(data, subarr):
285272
raise TypeError("Unsafe NumPy casting, you must explicitly cast")
286273

287-
@property
288-
def _is_all_dates(self) -> bool:
289-
"""
290-
Checks that all the labels are datetime objects.
291-
"""
292-
return False
293-
294274
def _format_native_types(
295275
self, *, na_rep="", float_format=None, decimal=".", quoting=None, **kwargs
296276
):

0 commit comments

Comments
 (0)