Skip to content

Commit 3977d73

Browse files
authored
REF: consolidate _validate_fill_logic in np_can_hold_element (#45216)
1 parent b47f1eb commit 3977d73

File tree

3 files changed

+24
-23
lines changed

3 files changed

+24
-23
lines changed

pandas/core/dtypes/cast.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -2239,11 +2239,26 @@ def np_can_hold_element(dtype: np.dtype, element: Any) -> Any:
22392239
casted = element.astype(dtype)
22402240
comp = casted == element
22412241
if comp.all():
2242-
return element
2242+
# Return the casted values bc they can be passed to
2243+
# np.putmask, whereas the raw values cannot.
2244+
# see TestSetitemFloatNDarrayIntoIntegerSeries
2245+
return casted
22432246
raise ValueError
22442247

22452248
# Anything other than integer we cannot hold
22462249
raise ValueError
2250+
elif (
2251+
dtype.kind == "u"
2252+
and isinstance(element, np.ndarray)
2253+
and element.dtype.kind == "i"
2254+
):
2255+
# see test_where_uint64
2256+
casted = element.astype(dtype)
2257+
if (casted == element).all():
2258+
# TODO: faster to check (element >=0).all()? potential
2259+
# itemsize issues there?
2260+
return casted
2261+
raise ValueError
22472262
elif dtype.itemsize < tipo.itemsize:
22482263
if is_integer(element):
22492264
# e.g. test_setitem_series_int8 if we have a python int 1

pandas/core/indexes/base.py

+8
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
find_common_type,
7070
infer_dtype_from,
7171
maybe_cast_pointwise_result,
72+
np_can_hold_element,
7273
)
7374
from pandas.core.dtypes.common import (
7475
ensure_int64,
@@ -4915,6 +4916,13 @@ def _validate_fill_value(self, value):
49154916
TypeError
49164917
If the value cannot be inserted into an array of this dtype.
49174918
"""
4919+
dtype = self.dtype
4920+
if isinstance(dtype, np.dtype) and dtype.kind not in ["m", "M"]:
4921+
try:
4922+
return np_can_hold_element(dtype, value)
4923+
except ValueError as err:
4924+
# re-raise as TypeError for consistency
4925+
raise TypeError from err
49184926
if not can_hold_element(self._values, value):
49194927
raise TypeError
49204928
return value

pandas/core/indexes/numeric.py

-22
Original file line numberDiff line numberDiff line change
@@ -419,18 +419,6 @@ def asi8(self) -> npt.NDArray[np.int64]:
419419
)
420420
return self._values.view(self._default_dtype)
421421

422-
def _validate_fill_value(self, value):
423-
# e.g. np.array([1.0]) we want np.array([1], dtype=self.dtype)
424-
# see TestSetitemFloatNDarrayIntoIntegerSeries
425-
super()._validate_fill_value(value)
426-
if hasattr(value, "dtype") and is_float_dtype(value.dtype):
427-
converted = value.astype(self.dtype)
428-
if (converted == value).all():
429-
# See also: can_hold_element
430-
return converted
431-
raise TypeError
432-
return value
433-
434422

435423
class Int64Index(IntegerIndex):
436424
_index_descr_args = {
@@ -461,16 +449,6 @@ class UInt64Index(IntegerIndex):
461449
_default_dtype = np.dtype(np.uint64)
462450
_dtype_validation_metadata = (is_unsigned_integer_dtype, "unsigned integer")
463451

464-
def _validate_fill_value(self, value):
465-
# e.g. np.array([1]) we want np.array([1], dtype=np.uint64)
466-
# see test_where_uin64
467-
super()._validate_fill_value(value)
468-
if hasattr(value, "dtype") and is_signed_integer_dtype(value.dtype):
469-
if (value >= 0).all():
470-
return value.astype(self.dtype)
471-
raise TypeError
472-
return value
473-
474452

475453
class Float64Index(NumericIndex):
476454
_index_descr_args = {

0 commit comments

Comments
 (0)