diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 2a50ebd959ace..68069a2e9482c 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -906,13 +906,10 @@ def astype(self, dtype, copy=True): if is_dtype_equal(self.dtype, dtype): return self.copy() if copy else self - elif is_categorical_dtype(dtype): - from pandas.core.indexes.category import CategoricalIndex - - return CategoricalIndex(self, name=self.name, dtype=dtype, copy=copy) - - elif is_extension_array_dtype(dtype): - return Index(np.asarray(self), name=self.name, dtype=dtype, copy=copy) + elif isinstance(dtype, ExtensionDtype): + cls = dtype.construct_array_type() + new_values = cls._from_sequence(self, dtype=dtype, copy=False) + return Index(new_values, dtype=dtype, copy=copy, name=self.name) try: casted = self._values.astype(dtype, copy=copy) diff --git a/pandas/core/indexes/extension.py b/pandas/core/indexes/extension.py index 83998a2792a8a..066fa1f547328 100644 --- a/pandas/core/indexes/extension.py +++ b/pandas/core/indexes/extension.py @@ -18,6 +18,7 @@ cache_readonly, doc, ) +from pandas.util._exceptions import rewrite_exception from pandas.core.dtypes.cast import ( find_common_type, @@ -365,11 +366,17 @@ def astype(self, dtype, copy: bool = True) -> Index: return self return self.copy() - if isinstance(dtype, np.dtype) and dtype.kind == "M" and dtype != "M8[ns]": + if ( + isinstance(self.dtype, np.dtype) + and isinstance(dtype, np.dtype) + and dtype.kind == "M" + and dtype != "M8[ns]" + ): # For now Datetime supports this by unwrapping ndarray, but DTI doesn't - raise TypeError(f"Cannot cast {type(self._data).__name__} to dtype") + raise TypeError(f"Cannot cast {type(self).__name__} to dtype") - new_values = self._data.astype(dtype, copy=copy) + with rewrite_exception(type(self._data).__name__, type(self).__name__): + new_values = self._data.astype(dtype, copy=copy) # pass copy=False because any copying will be done in the # _data.astype call above diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 894abb0fb1776..61f3d62320a6e 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -422,12 +422,6 @@ def __reduce__(self): d.update(self._get_attributes_dict()) return _new_IntervalIndex, (type(self), d), None - @Appender(Index.astype.__doc__) - def astype(self, dtype, copy: bool = True): - with rewrite_exception("IntervalArray", type(self).__name__): - new_values = self._values.astype(dtype, copy=copy) - return Index(new_values, dtype=new_values.dtype, name=self.name) - @property def inferred_type(self) -> str: """Return a string of the type inferred from the values""" diff --git a/pandas/tests/indexes/datetimes/methods/test_astype.py b/pandas/tests/indexes/datetimes/methods/test_astype.py index 24387267cd5c4..3e329818540c3 100644 --- a/pandas/tests/indexes/datetimes/methods/test_astype.py +++ b/pandas/tests/indexes/datetimes/methods/test_astype.py @@ -223,7 +223,7 @@ def test_astype_object_with_nat(self): def test_astype_raises(self, dtype): # GH 13149, GH 13209 idx = DatetimeIndex(["2016-05-16", "NaT", NaT, np.NaN]) - msg = "Cannot cast DatetimeArray to dtype" + msg = "Cannot cast DatetimeIndex to dtype" with pytest.raises(TypeError, match=msg): idx.astype(dtype) diff --git a/pandas/tests/indexes/period/methods/test_astype.py b/pandas/tests/indexes/period/methods/test_astype.py index 73439d349bebd..74f627478a29c 100644 --- a/pandas/tests/indexes/period/methods/test_astype.py +++ b/pandas/tests/indexes/period/methods/test_astype.py @@ -21,7 +21,7 @@ class TestPeriodIndexAsType: def test_astype_raises(self, dtype): # GH#13149, GH#13209 idx = PeriodIndex(["2016-05-16", "NaT", NaT, np.NaN], freq="D") - msg = "Cannot cast PeriodArray to dtype" + msg = "Cannot cast PeriodIndex to dtype" with pytest.raises(TypeError, match=msg): idx.astype(dtype) diff --git a/pandas/tests/indexes/period/test_constructors.py b/pandas/tests/indexes/period/test_constructors.py index 54e61b35eb70f..e372fd007630a 100644 --- a/pandas/tests/indexes/period/test_constructors.py +++ b/pandas/tests/indexes/period/test_constructors.py @@ -538,7 +538,7 @@ def setup_method(self, method): self.series = Series(period_range("2000-01-01", periods=10, freq="D")) def test_constructor_cant_cast_period(self): - msg = "Cannot cast PeriodArray to dtype float64" + msg = "Cannot cast PeriodIndex to dtype float64" with pytest.raises(TypeError, match=msg): Series(period_range("2000-01-01", periods=10, freq="D"), dtype=float) diff --git a/pandas/tests/indexes/timedeltas/methods/test_astype.py b/pandas/tests/indexes/timedeltas/methods/test_astype.py index c2c7a1f32ae6e..fbe66bf78dbeb 100644 --- a/pandas/tests/indexes/timedeltas/methods/test_astype.py +++ b/pandas/tests/indexes/timedeltas/methods/test_astype.py @@ -101,7 +101,7 @@ def test_astype_timedelta64(self): def test_astype_raises(self, dtype): # GH 13149, GH 13209 idx = TimedeltaIndex([1e14, "NaT", NaT, np.NaN]) - msg = "Cannot cast TimedeltaArray to dtype" + msg = "Cannot cast TimedeltaIndex to dtype" with pytest.raises(TypeError, match=msg): idx.astype(dtype)