Skip to content

Commit 7238b95

Browse files
jbrockmendelznicholls
authored andcommitted
REF: share DTBlock/TDBLok _maybe_coerce_values (pandas-dev#39815)
1 parent b77d3fa commit 7238b95

File tree

1 file changed

+49
-60
lines changed

1 file changed

+49
-60
lines changed

pandas/core/internals/blocks.py

+49-60
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
soft_convert_objects,
3333
)
3434
from pandas.core.dtypes.common import (
35-
DT64NS_DTYPE,
36-
TD64NS_DTYPE,
3735
is_categorical_dtype,
3836
is_datetime64_dtype,
3937
is_datetime64tz_dtype,
@@ -143,7 +141,8 @@ def __init__(self, values, placement, ndim: int):
143141
f"placement implies {len(self.mgr_locs)}"
144142
)
145143

146-
def _maybe_coerce_values(self, values):
144+
@classmethod
145+
def _maybe_coerce_values(cls, values):
147146
"""
148147
Ensure we have correctly-typed values.
149148
@@ -1546,7 +1545,8 @@ def putmask(self, mask, new) -> List[Block]:
15461545
new_values[mask] = new
15471546
return [self.make_block(values=new_values)]
15481547

1549-
def _maybe_coerce_values(self, values):
1548+
@classmethod
1549+
def _maybe_coerce_values(cls, values):
15501550
"""
15511551
Unbox to an extension array.
15521552
@@ -1937,13 +1937,39 @@ def to_native_types(
19371937
class DatetimeLikeBlockMixin(HybridMixin, Block):
19381938
"""Mixin class for DatetimeBlock, DatetimeTZBlock, and TimedeltaBlock."""
19391939

1940-
@property
1941-
def _holder(self):
1942-
return DatetimeArray
1940+
_dtype: np.dtype
1941+
_holder: Type[Union[DatetimeArray, TimedeltaArray]]
19431942

1944-
@property
1945-
def fill_value(self):
1946-
return np.datetime64("NaT", "ns")
1943+
@classmethod
1944+
def _maybe_coerce_values(cls, values):
1945+
"""
1946+
Input validation for values passed to __init__. Ensure that
1947+
we have nanosecond datetime64/timedelta64, coercing if necessary.
1948+
1949+
Parameters
1950+
----------
1951+
values : array-like
1952+
Must be convertible to datetime64/timedelta64
1953+
1954+
Returns
1955+
-------
1956+
values : ndarray[datetime64ns/timedelta64ns]
1957+
1958+
Overridden by DatetimeTZBlock.
1959+
"""
1960+
if values.dtype != cls._dtype:
1961+
# non-nano we will convert to nano
1962+
if values.dtype.kind != cls._dtype.kind:
1963+
# caller is responsible for ensuring td64/dt64 dtype
1964+
raise TypeError(values.dtype) # pragma: no cover
1965+
1966+
values = cls._holder._from_sequence(values)._data
1967+
1968+
if isinstance(values, cls._holder):
1969+
values = values._data
1970+
1971+
assert isinstance(values, np.ndarray), type(values)
1972+
return values
19471973

19481974
def get_values(self, dtype: Optional[DtypeObj] = None) -> np.ndarray:
19491975
"""
@@ -2039,36 +2065,14 @@ def where(self, other, cond, errors="raise", axis: int = 0) -> List[Block]:
20392065
class DatetimeBlock(DatetimeLikeBlockMixin):
20402066
__slots__ = ()
20412067
is_datetime = True
2068+
fill_value = np.datetime64("NaT", "ns")
2069+
_dtype = fill_value.dtype
2070+
_holder = DatetimeArray
20422071

20432072
@property
20442073
def _can_hold_na(self):
20452074
return True
20462075

2047-
def _maybe_coerce_values(self, values):
2048-
"""
2049-
Input validation for values passed to __init__. Ensure that
2050-
we have datetime64ns, coercing if necessary.
2051-
2052-
Parameters
2053-
----------
2054-
values : array-like
2055-
Must be convertible to datetime64
2056-
2057-
Returns
2058-
-------
2059-
values : ndarray[datetime64ns]
2060-
2061-
Overridden by DatetimeTZBlock.
2062-
"""
2063-
if values.dtype != DT64NS_DTYPE:
2064-
values = conversion.ensure_datetime64ns(values)
2065-
2066-
if isinstance(values, DatetimeArray):
2067-
values = values._data
2068-
2069-
assert isinstance(values, np.ndarray), type(values)
2070-
return values
2071-
20722076
def set_inplace(self, locs, values):
20732077
"""
20742078
See Block.set.__doc__
@@ -2087,6 +2091,8 @@ class DatetimeTZBlock(ExtensionBlock, DatetimeBlock):
20872091
is_datetimetz = True
20882092
is_extension = True
20892093

2094+
_holder = DatetimeArray
2095+
20902096
internal_values = Block.internal_values
20912097
_can_hold_element = DatetimeBlock._can_hold_element
20922098
to_native_types = DatetimeBlock.to_native_types
@@ -2097,11 +2103,8 @@ class DatetimeTZBlock(ExtensionBlock, DatetimeBlock):
20972103

20982104
array_values = ExtensionBlock.array_values
20992105

2100-
@property
2101-
def _holder(self):
2102-
return DatetimeArray
2103-
2104-
def _maybe_coerce_values(self, values):
2106+
@classmethod
2107+
def _maybe_coerce_values(cls, values):
21052108
"""
21062109
Input validation for values passed to __init__. Ensure that
21072110
we have datetime64TZ, coercing if necessary.
@@ -2115,8 +2118,8 @@ def _maybe_coerce_values(self, values):
21152118
-------
21162119
values : DatetimeArray
21172120
"""
2118-
if not isinstance(values, self._holder):
2119-
values = self._holder(values)
2121+
if not isinstance(values, cls._holder):
2122+
values = cls._holder(values)
21202123

21212124
if values.tz is None:
21222125
raise ValueError("cannot create a DatetimeTZBlock without a tz")
@@ -2207,24 +2210,9 @@ class TimeDeltaBlock(DatetimeLikeBlockMixin):
22072210
is_timedelta = True
22082211
_can_hold_na = True
22092212
is_numeric = False
2213+
_holder = TimedeltaArray
22102214
fill_value = np.timedelta64("NaT", "ns")
2211-
2212-
def _maybe_coerce_values(self, values):
2213-
if values.dtype != TD64NS_DTYPE:
2214-
# non-nano we will convert to nano
2215-
if values.dtype.kind != "m":
2216-
# caller is responsible for ensuring timedelta64 dtype
2217-
raise TypeError(values.dtype) # pragma: no cover
2218-
2219-
values = TimedeltaArray._from_sequence(values)._data
2220-
if isinstance(values, TimedeltaArray):
2221-
values = values._data
2222-
assert isinstance(values, np.ndarray), type(values)
2223-
return values
2224-
2225-
@property
2226-
def _holder(self):
2227-
return TimedeltaArray
2215+
_dtype = fill_value.dtype
22282216

22292217
def fillna(
22302218
self, value, limit=None, inplace: bool = False, downcast=None
@@ -2240,7 +2228,8 @@ class ObjectBlock(Block):
22402228
is_object = True
22412229
_can_hold_na = True
22422230

2243-
def _maybe_coerce_values(self, values):
2231+
@classmethod
2232+
def _maybe_coerce_values(cls, values):
22442233
if issubclass(values.dtype.type, str):
22452234
values = np.array(values, dtype=object)
22462235
return values

0 commit comments

Comments
 (0)