Skip to content

Commit c64cc46

Browse files
authored
BUG: PandasArray.astype use astype_nansafe (#51174)
1 parent 15e258a commit c64cc46

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

pandas/core/arrays/numpy_.py

+16
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616
)
1717
from pandas.compat.numpy import function as nv
1818

19+
from pandas.core.dtypes.astype import astype_array
1920
from pandas.core.dtypes.cast import construct_1d_object_array_from_listlike
21+
from pandas.core.dtypes.common import (
22+
is_dtype_equal,
23+
pandas_dtype,
24+
)
2025
from pandas.core.dtypes.dtypes import PandasDtype
2126
from pandas.core.dtypes.missing import isna
2227

@@ -185,6 +190,17 @@ def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
185190
# ------------------------------------------------------------------------
186191
# Pandas ExtensionArray Interface
187192

193+
def astype(self, dtype, copy: bool = True):
194+
dtype = pandas_dtype(dtype)
195+
196+
if is_dtype_equal(dtype, self.dtype):
197+
if copy:
198+
return self.copy()
199+
return self
200+
201+
result = astype_array(self._ndarray, dtype=dtype, copy=copy)
202+
return result
203+
188204
def isna(self) -> np.ndarray:
189205
return isna(self._ndarray)
190206

pandas/core/arrays/string_.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,8 @@ def astype(self, dtype, copy: bool = True):
454454
values = arr.astype(dtype.numpy_dtype)
455455
return FloatingArray(values, mask, copy=False)
456456
elif isinstance(dtype, ExtensionDtype):
457-
return super().astype(dtype, copy=copy)
457+
# Skip the PandasArray.astype method
458+
return ExtensionArray.astype(self, dtype, copy)
458459
elif np.issubdtype(dtype, np.floating):
459460
arr = self._ndarray.copy()
460461
mask = self.isna()

pandas/tests/extension/test_numpy.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,7 @@ def assert_series_equal(cls, left, right, *args, **kwargs):
190190

191191

192192
class TestCasting(BaseNumPyTests, base.BaseCastingTests):
193-
@skip_nested
194-
def test_astype_str(self, data):
195-
# ValueError: setting an array element with a sequence
196-
super().test_astype_str(data)
193+
pass
197194

198195

199196
class TestConstructors(BaseNumPyTests, base.BaseConstructorsTests):

pandas/tests/series/methods/test_astype.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -352,14 +352,25 @@ def test_astype_cast_object_int_fail(self, dtype):
352352
def test_astype_float_to_uint_negatives_raise(
353353
self, float_numpy_dtype, any_unsigned_int_numpy_dtype
354354
):
355-
# GH#45151
356-
# TODO: same for EA float/uint dtypes
355+
# GH#45151 We don't cast negative numbers to nonsense values
356+
# TODO: same for EA float/uint dtypes, signed integers?
357357
arr = np.arange(5).astype(float_numpy_dtype) - 3 # includes negatives
358358
ser = Series(arr)
359359

360-
with pytest.raises(ValueError, match="losslessly"):
360+
msg = "Cannot losslessly cast from .* to .*"
361+
with pytest.raises(ValueError, match=msg):
361362
ser.astype(any_unsigned_int_numpy_dtype)
362363

364+
with pytest.raises(ValueError, match=msg):
365+
ser.to_frame().astype(any_unsigned_int_numpy_dtype)
366+
367+
with pytest.raises(ValueError, match=msg):
368+
# We currently catch and re-raise in Index.astype
369+
Index(ser).astype(any_unsigned_int_numpy_dtype)
370+
371+
with pytest.raises(ValueError, match=msg):
372+
ser.array.astype(any_unsigned_int_numpy_dtype)
373+
363374
def test_astype_cast_object_int(self):
364375
arr = Series(["1", "2", "3", "4"], dtype=object)
365376
result = arr.astype(int)

0 commit comments

Comments
 (0)