55from typing import (
66 TYPE_CHECKING ,
77 Any ,
8- Callable ,
98 List ,
109 Optional ,
1110 Tuple ,
1817import numpy as np
1918
2019from pandas ._libs import (
21- Interval ,
22- Period ,
2320 Timestamp ,
2421 algos as libalgos ,
2522 internals as libinternals ,
10299 PeriodArray ,
103100 TimedeltaArray ,
104101)
102+ from pandas .core .arrays ._mixins import NDArrayBackedExtensionArray
105103from pandas .core .base import PandasObject
106104import pandas .core .common as com
107105import pandas .core .computation .expressions as expressions
122120 Float64Index ,
123121 Index ,
124122 )
125- from pandas .core .arrays ._mixins import NDArrayBackedExtensionArray
126123
127124# comparison is faster than is_object_dtype
128125_dtype_obj = np .dtype ("object" )
@@ -625,9 +622,11 @@ def convert(
625622 """
626623 return [self .copy ()] if copy else [self ]
627624
625+ @final
628626 def _can_hold_element (self , element : Any ) -> bool :
629627 """ require the same dtype as ourselves """
630- raise NotImplementedError ("Implemented on subclasses" )
628+ element = extract_array (element , extract_numpy = True )
629+ return can_hold_element (self .values , element )
631630
632631 @final
633632 def should_store (self , value : ArrayLike ) -> bool :
@@ -1545,7 +1544,7 @@ def setitem(self, indexer, value):
15451544 be a compatible shape.
15461545 """
15471546 if not self ._can_hold_element (value ):
1548- # This is only relevant for DatetimeTZBlock, ObjectValuesExtensionBlock ,
1547+ # This is only relevant for DatetimeTZBlock, PeriodDtype, IntervalDtype ,
15491548 # which has a non-trivial `_can_hold_element`.
15501549 # https://github.com/pandas-dev/pandas/issues/24020
15511550 # Need a dedicated setitem until GH#24020 (type promotion in setitem
@@ -1597,10 +1596,6 @@ def take_nd(
15971596
15981597 return self .make_block_same_class (new_values , new_mgr_locs )
15991598
1600- def _can_hold_element (self , element : Any ) -> bool :
1601- # TODO: We may need to think about pushing this onto the array.
1602- return True
1603-
16041599 def _slice (self , slicer ):
16051600 """
16061601 Return a slice of my values.
@@ -1746,54 +1741,22 @@ def _unstack(self, unstacker, fill_value, new_placement):
17461741 return blocks , mask
17471742
17481743
1749- class HybridMixin :
1750- """
1751- Mixin for Blocks backed (maybe indirectly) by ExtensionArrays.
1752- """
1753-
1754- array_values : Callable
1755-
1756- def _can_hold_element (self , element : Any ) -> bool :
1757- values = self .array_values
1758-
1759- try :
1760- # error: "Callable[..., Any]" has no attribute "_validate_setitem_value"
1761- values ._validate_setitem_value (element ) # type: ignore[attr-defined]
1762- return True
1763- except (ValueError , TypeError ):
1764- return False
1765-
1766-
1767- class ObjectValuesExtensionBlock (HybridMixin , ExtensionBlock ):
1768- """
1769- Block providing backwards-compatibility for `.values`.
1770-
1771- Used by PeriodArray and IntervalArray to ensure that
1772- Series[T].values is an ndarray of objects.
1773- """
1774-
1775- pass
1776-
1777-
17781744class NumericBlock (Block ):
17791745 __slots__ = ()
17801746 is_numeric = True
17811747
1782- def _can_hold_element (self , element : Any ) -> bool :
1783- element = extract_array (element , extract_numpy = True )
1784- if isinstance (element , (IntegerArray , FloatingArray )):
1785- if element ._mask .any ():
1786- return False
1787- return can_hold_element (self .dtype , element )
17881748
1789-
1790- class NDArrayBackedExtensionBlock (HybridMixin , Block ):
1749+ class NDArrayBackedExtensionBlock (Block ):
17911750 """
17921751 Block backed by an NDArrayBackedExtensionArray
17931752 """
17941753
17951754 values : NDArrayBackedExtensionArray
17961755
1756+ @property
1757+ def array_values (self ) -> NDArrayBackedExtensionArray :
1758+ return self .values
1759+
17971760 @property
17981761 def is_view (self ) -> bool :
17991762 """ return a boolean if I am possibly a view """
@@ -1901,10 +1864,6 @@ class DatetimeLikeBlockMixin(NDArrayBackedExtensionBlock):
19011864
19021865 is_numeric = False
19031866
1904- @cache_readonly
1905- def array_values (self ):
1906- return self .values
1907-
19081867
19091868class DatetimeBlock (DatetimeLikeBlockMixin ):
19101869 __slots__ = ()
@@ -1920,7 +1879,6 @@ class DatetimeTZBlock(ExtensionBlock, DatetimeLikeBlockMixin):
19201879 is_numeric = False
19211880
19221881 internal_values = Block .internal_values
1923- _can_hold_element = DatetimeBlock ._can_hold_element
19241882 diff = DatetimeBlock .diff
19251883 where = DatetimeBlock .where
19261884 putmask = DatetimeLikeBlockMixin .putmask
@@ -1983,9 +1941,6 @@ def convert(
19831941 res_values = ensure_block_shape (res_values , self .ndim )
19841942 return [self .make_block (res_values )]
19851943
1986- def _can_hold_element (self , element : Any ) -> bool :
1987- return True
1988-
19891944
19901945class CategoricalBlock (ExtensionBlock ):
19911946 # this Block type is kept for backwards-compatibility
@@ -2052,8 +2007,6 @@ def get_block_type(values, dtype: Optional[Dtype] = None):
20522007 cls = CategoricalBlock
20532008 elif vtype is Timestamp :
20542009 cls = DatetimeTZBlock
2055- elif vtype is Interval or vtype is Period :
2056- cls = ObjectValuesExtensionBlock
20572010 elif isinstance (dtype , ExtensionDtype ):
20582011 # Note: need to be sure PandasArray is unwrapped before we get here
20592012 cls = ExtensionBlock
0 commit comments