5
5
from typing import (
6
6
TYPE_CHECKING ,
7
7
Any ,
8
- Callable ,
9
8
List ,
10
9
Optional ,
11
10
Tuple ,
18
17
import numpy as np
19
18
20
19
from pandas ._libs import (
21
- Interval ,
22
- Period ,
23
20
Timestamp ,
24
21
algos as libalgos ,
25
22
internals as libinternals ,
102
99
PeriodArray ,
103
100
TimedeltaArray ,
104
101
)
102
+ from pandas .core .arrays ._mixins import NDArrayBackedExtensionArray
105
103
from pandas .core .base import PandasObject
106
104
import pandas .core .common as com
107
105
import pandas .core .computation .expressions as expressions
122
120
Float64Index ,
123
121
Index ,
124
122
)
125
- from pandas .core .arrays ._mixins import NDArrayBackedExtensionArray
126
123
127
124
# comparison is faster than is_object_dtype
128
125
_dtype_obj = np .dtype ("object" )
@@ -625,9 +622,11 @@ def convert(
625
622
"""
626
623
return [self .copy ()] if copy else [self ]
627
624
625
+ @final
628
626
def _can_hold_element (self , element : Any ) -> bool :
629
627
""" 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 )
631
630
632
631
@final
633
632
def should_store (self , value : ArrayLike ) -> bool :
@@ -1545,7 +1544,7 @@ def setitem(self, indexer, value):
1545
1544
be a compatible shape.
1546
1545
"""
1547
1546
if not self ._can_hold_element (value ):
1548
- # This is only relevant for DatetimeTZBlock, ObjectValuesExtensionBlock ,
1547
+ # This is only relevant for DatetimeTZBlock, PeriodDtype, IntervalDtype ,
1549
1548
# which has a non-trivial `_can_hold_element`.
1550
1549
# https://github.com/pandas-dev/pandas/issues/24020
1551
1550
# Need a dedicated setitem until GH#24020 (type promotion in setitem
@@ -1597,10 +1596,6 @@ def take_nd(
1597
1596
1598
1597
return self .make_block_same_class (new_values , new_mgr_locs )
1599
1598
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
-
1604
1599
def _slice (self , slicer ):
1605
1600
"""
1606
1601
Return a slice of my values.
@@ -1746,54 +1741,22 @@ def _unstack(self, unstacker, fill_value, new_placement):
1746
1741
return blocks , mask
1747
1742
1748
1743
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
-
1778
1744
class NumericBlock (Block ):
1779
1745
__slots__ = ()
1780
1746
is_numeric = True
1781
1747
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 )
1788
1748
1789
-
1790
- class NDArrayBackedExtensionBlock (HybridMixin , Block ):
1749
+ class NDArrayBackedExtensionBlock (Block ):
1791
1750
"""
1792
1751
Block backed by an NDArrayBackedExtensionArray
1793
1752
"""
1794
1753
1795
1754
values : NDArrayBackedExtensionArray
1796
1755
1756
+ @property
1757
+ def array_values (self ) -> NDArrayBackedExtensionArray :
1758
+ return self .values
1759
+
1797
1760
@property
1798
1761
def is_view (self ) -> bool :
1799
1762
""" return a boolean if I am possibly a view """
@@ -1901,10 +1864,6 @@ class DatetimeLikeBlockMixin(NDArrayBackedExtensionBlock):
1901
1864
1902
1865
is_numeric = False
1903
1866
1904
- @cache_readonly
1905
- def array_values (self ):
1906
- return self .values
1907
-
1908
1867
1909
1868
class DatetimeBlock (DatetimeLikeBlockMixin ):
1910
1869
__slots__ = ()
@@ -1920,7 +1879,6 @@ class DatetimeTZBlock(ExtensionBlock, DatetimeLikeBlockMixin):
1920
1879
is_numeric = False
1921
1880
1922
1881
internal_values = Block .internal_values
1923
- _can_hold_element = DatetimeBlock ._can_hold_element
1924
1882
diff = DatetimeBlock .diff
1925
1883
where = DatetimeBlock .where
1926
1884
putmask = DatetimeLikeBlockMixin .putmask
@@ -1983,9 +1941,6 @@ def convert(
1983
1941
res_values = ensure_block_shape (res_values , self .ndim )
1984
1942
return [self .make_block (res_values )]
1985
1943
1986
- def _can_hold_element (self , element : Any ) -> bool :
1987
- return True
1988
-
1989
1944
1990
1945
class CategoricalBlock (ExtensionBlock ):
1991
1946
# this Block type is kept for backwards-compatibility
@@ -2052,8 +2007,6 @@ def get_block_type(values, dtype: Optional[Dtype] = None):
2052
2007
cls = CategoricalBlock
2053
2008
elif vtype is Timestamp :
2054
2009
cls = DatetimeTZBlock
2055
- elif vtype is Interval or vtype is Period :
2056
- cls = ObjectValuesExtensionBlock
2057
2010
elif isinstance (dtype , ExtensionDtype ):
2058
2011
# Note: need to be sure PandasArray is unwrapped before we get here
2059
2012
cls = ExtensionBlock
0 commit comments