Skip to content

Commit f904213

Browse files
authored
REF: consolidate paths for astype (#39900)
1 parent 75609da commit f904213

File tree

9 files changed

+35
-21
lines changed

9 files changed

+35
-21
lines changed

pandas/core/arrays/datetimelike.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
Substitution,
6161
cache_readonly,
6262
)
63+
from pandas.util._exceptions import find_stack_level
6364

6465
from pandas.core.dtypes.common import (
6566
is_categorical_dtype,
@@ -397,12 +398,13 @@ def astype(self, dtype, copy=True):
397398
elif is_integer_dtype(dtype):
398399
# we deliberately ignore int32 vs. int64 here.
399400
# See https://github.com/pandas-dev/pandas/issues/24381 for more.
401+
level = find_stack_level()
400402
warnings.warn(
401403
f"casting {self.dtype} values to int64 with .astype(...) is "
402404
"deprecated and will raise in a future version. "
403405
"Use .view(...) instead.",
404406
FutureWarning,
405-
stacklevel=3,
407+
stacklevel=level,
406408
)
407409

408410
values = self.asi8

pandas/core/arrays/datetimes.py

+4
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,10 @@ def astype(self, dtype, copy=True):
616616
elif is_datetime64_ns_dtype(dtype):
617617
return astype_dt64_to_dt64tz(self, dtype, copy, via_utc=False)
618618

619+
elif self.tz is None and is_datetime64_dtype(dtype) and dtype != self.dtype:
620+
# unit conversion e.g. datetime64[s]
621+
return self._data.astype(dtype)
622+
619623
elif is_period_dtype(dtype):
620624
return self.to_period(freq=dtype.freq)
621625
return dtl.DatetimeLikeArrayMixin.astype(self, dtype, copy)

pandas/core/indexes/extension.py

+4
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ def astype(self, dtype, copy=True):
309309
return self
310310
return self.copy()
311311

312+
if isinstance(dtype, np.dtype) and dtype.kind == "M" and dtype != "M8[ns]":
313+
# For now Datetime supports this by unwrapping ndarray, but DTI doesn't
314+
raise TypeError(f"Cannot cast {type(self._data).__name__} to dtype")
315+
312316
new_values = self._data.astype(dtype, copy=copy)
313317

314318
# pass copy=False because any copying will be done in the

pandas/core/internals/blocks.py

+12
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,18 @@ def astype(self, dtype, copy: bool = False, errors: str = "raise"):
673673

674674
def _astype(self, dtype: DtypeObj, copy: bool) -> ArrayLike:
675675
values = self.values
676+
if values.dtype.kind in ["m", "M"]:
677+
values = self.array_values()
678+
679+
if (
680+
values.dtype.kind in ["m", "M"]
681+
and dtype.kind in ["i", "u"]
682+
and isinstance(dtype, np.dtype)
683+
and dtype.itemsize != 8
684+
):
685+
# TODO(2.0) remove special case once deprecation on DTA/TDA is enforced
686+
msg = rf"cannot astype a datetimelike from [{values.dtype}] to [{dtype}]"
687+
raise TypeError(msg)
676688

677689
if is_datetime64tz_dtype(dtype) and is_datetime64_dtype(values.dtype):
678690
return astype_dt64_to_dt64tz(values, dtype, copy, via_utc=True)

pandas/tests/frame/methods/test_astype.py

+2-10
Original file line numberDiff line numberDiff line change
@@ -432,19 +432,11 @@ def test_astype_to_incorrect_datetimelike(self, unit):
432432
other = f"m8[{unit}]"
433433

434434
df = DataFrame(np.array([[1, 2, 3]], dtype=dtype))
435-
msg = (
436-
fr"cannot astype a datetimelike from \[datetime64\[ns\]\] to "
437-
fr"\[timedelta64\[{unit}\]\]"
438-
fr"|(Cannot cast DatetimeArray to dtype timedelta64\[{unit}\])"
439-
)
435+
msg = fr"Cannot cast DatetimeArray to dtype timedelta64\[{unit}\]"
440436
with pytest.raises(TypeError, match=msg):
441437
df.astype(other)
442438

443-
msg = (
444-
fr"cannot astype a timedelta from \[timedelta64\[ns\]\] to "
445-
fr"\[datetime64\[{unit}\]\]"
446-
fr"|(Cannot cast TimedeltaArray to dtype datetime64\[{unit}\])"
447-
)
439+
msg = fr"Cannot cast TimedeltaArray to dtype datetime64\[{unit}\]"
448440
df = DataFrame(np.array([[1, 2, 3]], dtype=other))
449441
with pytest.raises(TypeError, match=msg):
450442
df.astype(dtype)

pandas/tests/indexes/datetimes/methods/test_astype.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_astype(self):
2929
)
3030
tm.assert_index_equal(result, expected)
3131

32-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
32+
with tm.assert_produces_warning(FutureWarning):
3333
result = idx.astype(int)
3434
expected = Int64Index(
3535
[1463356800000000000] + [-9223372036854775808] * 3,
@@ -39,7 +39,7 @@ def test_astype(self):
3939
tm.assert_index_equal(result, expected)
4040

4141
rng = date_range("1/1/2000", periods=10, name="idx")
42-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
42+
with tm.assert_produces_warning(FutureWarning):
4343
result = rng.astype("i8")
4444
tm.assert_index_equal(result, Index(rng.asi8, name="idx"))
4545
tm.assert_numpy_array_equal(result.values, rng.asi8)
@@ -50,7 +50,7 @@ def test_astype_uint(self):
5050
np.array([946684800000000000, 946771200000000000], dtype="uint64"),
5151
name="idx",
5252
)
53-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
53+
with tm.assert_produces_warning(FutureWarning):
5454
tm.assert_index_equal(arr.astype("uint64"), expected)
5555
tm.assert_index_equal(arr.astype("uint32"), expected)
5656

pandas/tests/indexes/period/methods/test_astype.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def test_astype_conversion(self):
3737
)
3838
tm.assert_index_equal(result, expected)
3939

40-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
40+
with tm.assert_produces_warning(FutureWarning):
4141
result = idx.astype(np.int64)
4242
expected = Int64Index(
4343
[16937] + [-9223372036854775808] * 3, dtype=np.int64, name="idx"
@@ -49,15 +49,15 @@ def test_astype_conversion(self):
4949
tm.assert_index_equal(result, expected)
5050

5151
idx = period_range("1990", "2009", freq="A", name="idx")
52-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
52+
with tm.assert_produces_warning(FutureWarning):
5353
result = idx.astype("i8")
5454
tm.assert_index_equal(result, Index(idx.asi8, name="idx"))
5555
tm.assert_numpy_array_equal(result.values, idx.asi8)
5656

5757
def test_astype_uint(self):
5858
arr = period_range("2000", periods=2, name="idx")
5959
expected = UInt64Index(np.array([10957, 10958], dtype="uint64"), name="idx")
60-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
60+
with tm.assert_produces_warning(FutureWarning):
6161
tm.assert_index_equal(arr.astype("uint64"), expected)
6262
tm.assert_index_equal(arr.astype("uint32"), expected)
6363

pandas/tests/indexes/timedeltas/methods/test_astype.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_astype(self):
5555
)
5656
tm.assert_index_equal(result, expected)
5757

58-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
58+
with tm.assert_produces_warning(FutureWarning):
5959
result = idx.astype(int)
6060
expected = Int64Index(
6161
[100000000000000] + [-9223372036854775808] * 3, dtype=np.int64, name="idx"
@@ -67,7 +67,7 @@ def test_astype(self):
6767
tm.assert_index_equal(result, expected)
6868

6969
rng = timedelta_range("1 days", periods=10)
70-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
70+
with tm.assert_produces_warning(FutureWarning):
7171
result = rng.astype("i8")
7272
tm.assert_index_equal(result, Index(rng.asi8))
7373
tm.assert_numpy_array_equal(rng.asi8, result.values)
@@ -77,7 +77,7 @@ def test_astype_uint(self):
7777
expected = pd.UInt64Index(
7878
np.array([3600000000000, 90000000000000], dtype="uint64")
7979
)
80-
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
80+
with tm.assert_produces_warning(FutureWarning):
8181
tm.assert_index_equal(arr.astype("uint64"), expected)
8282
tm.assert_index_equal(arr.astype("uint32"), expected)
8383

pandas/tests/series/test_constructors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ def test_constructor_dtype_timedelta64(self):
13181318
td.astype("int64")
13191319

13201320
# invalid casting
1321-
msg = r"cannot astype a timedelta from \[timedelta64\[ns\]\] to \[int32\]"
1321+
msg = r"cannot astype a datetimelike from \[timedelta64\[ns\]\] to \[int32\]"
13221322
with pytest.raises(TypeError, match=msg):
13231323
td.astype("int32")
13241324

0 commit comments

Comments
 (0)