Skip to content

Commit e4dedca

Browse files
authored
API: EA._can_hold_na -> EDtype.can_hold_na (#41654)
1 parent de07087 commit e4dedca

File tree

6 files changed

+25
-10
lines changed

6 files changed

+25
-10
lines changed

pandas/core/arrays/base.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from pandas.util._decorators import (
3636
Appender,
3737
Substitution,
38+
cache_readonly,
3839
)
3940
from pandas.util._validators import (
4041
validate_bool_kwarg,
@@ -1273,7 +1274,9 @@ def _concat_same_type(
12731274
# such as take(), reindex(), shift(), etc. In addition, those results
12741275
# will then be of the ExtensionArray subclass rather than an array
12751276
# of objects
1276-
_can_hold_na = True
1277+
@cache_readonly
1278+
def _can_hold_na(self) -> bool:
1279+
return self.dtype._can_hold_na
12771280

12781281
def _reduce(self, name: str, *, skipna: bool = True, **kwargs):
12791282
"""

pandas/core/arrays/categorical.py

-1
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,6 @@ class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMi
353353
# tolist is not actually deprecated, just suppressed in the __dir__
354354
_hidden_attrs = PandasObject._hidden_attrs | frozenset(["tolist"])
355355
_typ = "categorical"
356-
_can_hold_na = True
357356

358357
_dtype: CategoricalDtype
359358

pandas/core/arrays/datetimelike.py

+4
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ class DatetimeLikeArrayMixin(OpsMixin, NDArrayBackedExtensionArray):
159159
_recognized_scalars: tuple[type, ...]
160160
_ndarray: np.ndarray
161161

162+
@cache_readonly
163+
def _can_hold_na(self) -> bool:
164+
return True
165+
162166
def __init__(self, data, dtype: Dtype | None = None, freq=None, copy=False):
163167
raise AbstractMethodError(self)
164168

pandas/core/dtypes/base.py

+7
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,13 @@ def _get_common_dtype(self, dtypes: list[DtypeObj]) -> DtypeObj | None:
367367
else:
368368
return None
369369

370+
@property
371+
def _can_hold_na(self) -> bool:
372+
"""
373+
Can arrays of this dtype hold NA values?
374+
"""
375+
return True
376+
370377

371378
def register_extension_dtype(cls: type[E]) -> type[E]:
372379
"""

pandas/core/internals/blocks.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,15 @@ def is_view(self) -> bool:
175175
return values.base is not None
176176

177177
@final
178-
@property
178+
@cache_readonly
179179
def _can_hold_na(self) -> bool:
180180
"""
181181
Can we store NA values in this Block?
182182
"""
183-
values = self.values
184-
if isinstance(values, np.ndarray):
185-
return values.dtype.kind not in ["b", "i", "u"]
186-
return values._can_hold_na
183+
dtype = self.dtype
184+
if isinstance(dtype, np.dtype):
185+
return dtype.kind not in ["b", "i", "u"]
186+
return dtype._can_hold_na
187187

188188
@final
189189
@cache_readonly

pandas/tests/extension/test_external_block.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
class CustomBlock(ExtensionBlock):
1515

1616
_holder = np.ndarray
17-
# error: Cannot override final attribute "_can_hold_na"
18-
# (previously declared in base class "Block")
19-
_can_hold_na = False # type: ignore[misc]
17+
18+
# Cannot override final attribute "_can_hold_na"
19+
@property # type: ignore[misc]
20+
def _can_hold_na(self) -> bool:
21+
return False
2022

2123

2224
@pytest.fixture

0 commit comments

Comments
 (0)