Skip to content

Commit 86b9628

Browse files
authored
REF: remove unreachable maybe_cast_to_datetime cases (#49548)
1 parent d82adf0 commit 86b9628

File tree

3 files changed

+56
-58
lines changed

3 files changed

+56
-58
lines changed

pandas/_libs/lib.pyi

+13
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ def map_infer(
6565
convert: bool = ...,
6666
ignore_na: bool = ...,
6767
) -> np.ndarray: ...
68+
@overload # all convert_foo False -> only convert numeric
69+
def maybe_convert_objects(
70+
objects: npt.NDArray[np.object_],
71+
*,
72+
try_float: bool = ...,
73+
safe: bool = ...,
74+
convert_datetime: Literal[False] = ...,
75+
convert_timedelta: Literal[False] = ...,
76+
convert_period: Literal[False] = ...,
77+
convert_interval: Literal[False] = ...,
78+
convert_to_nullable_integer: Literal[False] = ...,
79+
dtype_if_all_nat: DtypeObj | None = ...,
80+
) -> npt.NDArray[np.object_ | np.number]: ...
6881
@overload # both convert_datetime and convert_to_nullable_integer False -> np.ndarray
6982
def maybe_convert_objects(
7083
objects: npt.NDArray[np.object_],

pandas/core/dtypes/cast.py

+32-56
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
from pandas.util._exceptions import find_stack_level
5050
from pandas.util._validators import validate_bool_kwarg
5151

52-
from pandas.core.dtypes.astype import astype_nansafe
5352
from pandas.core.dtypes.common import (
5453
DT64NS_DTYPE,
5554
TD64NS_DTYPE,
@@ -311,6 +310,7 @@ def maybe_downcast_to_dtype(result: ArrayLike, dtype: str | np.dtype) -> ArrayLi
311310
result = array_to_timedelta64(result)
312311

313312
elif dtype == np.dtype("M8[ns]") and result.dtype == _dtype_obj:
313+
result = cast(np.ndarray, result)
314314
return np.asarray(maybe_cast_to_datetime(result, dtype=dtype))
315315

316316
return result
@@ -1234,82 +1234,58 @@ def maybe_infer_to_datetimelike(
12341234

12351235

12361236
def maybe_cast_to_datetime(
1237-
value: ExtensionArray | np.ndarray | list, dtype: np.dtype | None
1237+
value: np.ndarray | list, dtype: np.dtype
12381238
) -> ExtensionArray | np.ndarray:
12391239
"""
12401240
try to cast the array/value to a datetimelike dtype, converting float
12411241
nan to iNaT
12421242
1243-
We allow a list *only* when dtype is not None.
1244-
1245-
Caller is responsible for handling ExtensionDtype cases.
1243+
Caller is responsible for handling ExtensionDtype cases and non dt64/td64
1244+
cases.
12461245
"""
12471246
from pandas.core.arrays.datetimes import sequence_to_datetimes
12481247
from pandas.core.arrays.timedeltas import TimedeltaArray
12491248

1249+
assert dtype.kind in ["m", "M"]
12501250
if not is_list_like(value):
12511251
raise TypeError("value must be listlike")
12521252

12531253
if is_timedelta64_dtype(dtype):
12541254
# TODO: _from_sequence would raise ValueError in cases where
12551255
# _ensure_nanosecond_dtype raises TypeError
1256-
dtype = cast(np.dtype, dtype)
12571256
# Incompatible types in assignment (expression has type "Union[dtype[Any],
12581257
# ExtensionDtype]", variable has type "Optional[dtype[Any]]")
12591258
dtype = _ensure_nanosecond_dtype(dtype) # type: ignore[assignment]
12601259
res = TimedeltaArray._from_sequence(value, dtype=dtype)
12611260
return res
12621261

1263-
if dtype is not None:
1264-
is_datetime64 = is_datetime64_dtype(dtype)
1265-
1266-
vdtype = getattr(value, "dtype", None)
1267-
1268-
if is_datetime64:
1269-
# Incompatible types in assignment (expression has type
1270-
# "Union[dtype[Any], ExtensionDtype]", variable has type
1271-
# "Optional[dtype[Any]]")
1272-
dtype = _ensure_nanosecond_dtype(dtype) # type: ignore[assignment]
1273-
1274-
value = np.array(value, copy=False)
1275-
1276-
# we have an array of datetime or timedeltas & nulls
1277-
if value.size or not is_dtype_equal(value.dtype, dtype):
1278-
_disallow_mismatched_datetimelike(value, dtype)
1279-
1280-
dta = sequence_to_datetimes(value)
1281-
# GH 25843: Remove tz information since the dtype
1282-
# didn't specify one
1283-
1284-
if dta.tz is not None:
1285-
raise ValueError(
1286-
"Cannot convert timezone-aware data to "
1287-
"timezone-naive dtype. Use "
1288-
"pd.Series(values).dt.tz_localize(None) instead."
1289-
)
1290-
1291-
# TODO(2.0): Do this astype in sequence_to_datetimes to
1292-
# avoid potential extra copy?
1293-
dta = dta.astype(dtype, copy=False)
1294-
value = dta
1295-
1296-
elif getattr(vdtype, "kind", None) in ["m", "M"]:
1297-
# we are already datetimelike and want to coerce to non-datetimelike;
1298-
# astype_nansafe will raise for anything other than object, then upcast.
1299-
# see test_datetimelike_values_with_object_dtype
1300-
# error: Argument 2 to "astype_nansafe" has incompatible type
1301-
# "Union[dtype[Any], ExtensionDtype]"; expected "dtype[Any]"
1302-
return astype_nansafe(value, dtype) # type: ignore[arg-type]
1303-
1304-
elif isinstance(value, np.ndarray):
1305-
if value.dtype == _dtype_obj:
1306-
value = maybe_infer_to_datetimelike(value)
1307-
1308-
elif isinstance(value, list):
1309-
# we only get here with dtype=None, which we do not allow
1310-
raise ValueError(
1311-
"maybe_cast_to_datetime allows a list *only* if dtype is not None"
1312-
)
1262+
if is_datetime64_dtype(dtype):
1263+
# Incompatible types in assignment (expression has type
1264+
# "Union[dtype[Any], ExtensionDtype]", variable has type
1265+
# "Optional[dtype[Any]]")
1266+
dtype = _ensure_nanosecond_dtype(dtype) # type: ignore[assignment]
1267+
1268+
value = np.array(value, copy=False)
1269+
1270+
# we have an array of datetime or timedeltas & nulls
1271+
if value.size or not is_dtype_equal(value.dtype, dtype):
1272+
_disallow_mismatched_datetimelike(value, dtype)
1273+
1274+
dta = sequence_to_datetimes(value)
1275+
# GH 25843: Remove tz information since the dtype
1276+
# didn't specify one
1277+
1278+
if dta.tz is not None:
1279+
raise ValueError(
1280+
"Cannot convert timezone-aware data to "
1281+
"timezone-naive dtype. Use "
1282+
"pd.Series(values).dt.tz_localize(None) instead."
1283+
)
1284+
1285+
# TODO(2.0): Do this astype in sequence_to_datetimes to
1286+
# avoid potential extra copy?
1287+
dta = dta.astype(dtype, copy=False)
1288+
return dta
13131289

13141290
# at this point we have converted or raised in all cases where we had a list
13151291
return cast(ArrayLike, value)

pandas/core/internals/construction.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -1052,13 +1052,22 @@ def convert(arr):
10521052
if dtype != np.dtype("O"):
10531053
arr = lib.maybe_convert_objects(arr)
10541054

1055-
if isinstance(dtype, ExtensionDtype):
1055+
if dtype is None:
1056+
if arr.dtype == np.dtype("O"):
1057+
# i.e. maybe_convert_objects didn't convert
1058+
arr = maybe_infer_to_datetimelike(arr)
1059+
elif isinstance(dtype, ExtensionDtype):
10561060
# TODO: test(s) that get here
10571061
# TODO: try to de-duplicate this convert function with
10581062
# core.construction functions
10591063
cls = dtype.construct_array_type()
10601064
arr = cls._from_sequence(arr, dtype=dtype, copy=False)
1061-
else:
1065+
elif dtype.kind in ["m", "M"]:
1066+
# This restriction is harmless bc these are the only cases
1067+
# where maybe_cast_to_datetime is not a no-op.
1068+
# Here we know:
1069+
# 1) dtype.kind in ["m", "M"] and
1070+
# 2) arr is either object or numeric dtype
10621071
arr = maybe_cast_to_datetime(arr, dtype)
10631072

10641073
return arr

0 commit comments

Comments
 (0)