Skip to content

Commit 7cdd833

Browse files
authored
REF: _try_cast (#41618)
1 parent 10a76bd commit 7cdd833

File tree

2 files changed

+35
-29
lines changed

2 files changed

+35
-29
lines changed

pandas/core/construction.py

+31-28
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
maybe_cast_to_datetime,
4040
maybe_cast_to_integer_array,
4141
maybe_convert_platform,
42+
maybe_infer_to_datetimelike,
4243
maybe_upcast,
4344
sanitize_to_nanoseconds,
4445
)
@@ -546,11 +547,12 @@ def sanitize_array(
546547
if dtype is not None or len(data) == 0:
547548
subarr = _try_cast(data, dtype, copy, raise_cast_failure)
548549
else:
550+
# TODO: copy?
549551
subarr = maybe_convert_platform(data)
550-
# error: Incompatible types in assignment (expression has type
551-
# "Union[ExtensionArray, ndarray, List[Any]]", variable has type
552-
# "ExtensionArray")
553-
subarr = maybe_cast_to_datetime(subarr, dtype) # type: ignore[assignment]
552+
if subarr.dtype == object:
553+
# Argument 1 to "maybe_infer_to_datetimelike" has incompatible
554+
# type "Union[ExtensionArray, ndarray]"; expected "ndarray"
555+
subarr = maybe_infer_to_datetimelike(subarr) # type: ignore[arg-type]
554556

555557
subarr = _sanitize_ndim(subarr, data, dtype, index)
556558

@@ -677,22 +679,29 @@ def _try_cast(
677679
"""
678680
is_ndarray = isinstance(arr, np.ndarray)
679681

680-
# perf shortcut as this is the most common case
681-
# Item "List[Any]" of "Union[List[Any], ndarray]" has no attribute "dtype"
682-
if (
683-
is_ndarray
684-
and arr.dtype != object # type: ignore[union-attr]
685-
and not copy
686-
and dtype is None
687-
):
688-
# Argument 1 to "sanitize_to_nanoseconds" has incompatible type
689-
# "Union[List[Any], ndarray]"; expected "ndarray"
690-
return sanitize_to_nanoseconds(arr) # type: ignore[arg-type]
682+
if dtype is None:
683+
# perf shortcut as this is the most common case
684+
if is_ndarray:
685+
arr = cast(np.ndarray, arr)
686+
if arr.dtype != object:
687+
return sanitize_to_nanoseconds(arr, copy=copy)
688+
689+
out = maybe_infer_to_datetimelike(arr)
690+
if out is arr and copy:
691+
out = out.copy()
692+
return out
691693

692-
if isinstance(dtype, ExtensionDtype):
694+
else:
695+
# i.e. list
696+
varr = np.array(arr, copy=False)
697+
# filter out cases that we _dont_ want to go through
698+
# maybe_infer_to_datetimelike
699+
if varr.dtype != object or varr.size == 0:
700+
return varr
701+
return maybe_infer_to_datetimelike(varr)
702+
703+
elif isinstance(dtype, ExtensionDtype):
693704
# create an extension array from its dtype
694-
# DatetimeTZ case needs to go through maybe_cast_to_datetime but
695-
# SparseDtype does not
696705
if isinstance(dtype, DatetimeTZDtype):
697706
# We can't go through _from_sequence because it handles dt64naive
698707
# data differently; _from_sequence treats naive as wall times,
@@ -714,22 +723,12 @@ def _try_cast(
714723
return subarr
715724
return ensure_wrapped_if_datetimelike(arr).astype(dtype, copy=copy)
716725

717-
elif dtype is None and not is_ndarray:
718-
# filter out cases that we _dont_ want to go through maybe_cast_to_datetime
719-
varr = np.array(arr, copy=False)
720-
if varr.dtype != object or varr.size == 0:
721-
return varr
722-
# error: Incompatible return value type (got "Union[ExtensionArray,
723-
# ndarray, List[Any]]", expected "Union[ExtensionArray, ndarray]")
724-
return maybe_cast_to_datetime(varr, None) # type: ignore[return-value]
725-
726726
try:
727727
# GH#15832: Check if we are requesting a numeric dtype and
728728
# that we can convert the data to the requested dtype.
729729
if is_integer_dtype(dtype):
730730
# this will raise if we have e.g. floats
731731

732-
dtype = cast(np.dtype, dtype)
733732
maybe_cast_to_integer_array(arr, dtype)
734733
subarr = arr
735734
else:
@@ -738,7 +737,11 @@ def _try_cast(
738737
return subarr
739738

740739
if not isinstance(subarr, ABCExtensionArray):
740+
# 4 tests fail if we move this to a try/except/else; see
741+
# test_constructor_compound_dtypes, test_constructor_cast_failure
742+
# test_constructor_dict_cast2, test_loc_setitem_dtype
741743
subarr = construct_1d_ndarray_preserving_na(subarr, dtype, copy=copy)
744+
742745
except OutOfBoundsDatetime:
743746
# in case of out of bound datetime64 -> always raise
744747
raise

pandas/core/dtypes/cast.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,7 @@ def maybe_cast_to_datetime(
16921692
return value
16931693

16941694

1695-
def sanitize_to_nanoseconds(values: np.ndarray) -> np.ndarray:
1695+
def sanitize_to_nanoseconds(values: np.ndarray, copy: bool = False) -> np.ndarray:
16961696
"""
16971697
Safely convert non-nanosecond datetime64 or timedelta64 values to nanosecond.
16981698
"""
@@ -1703,6 +1703,9 @@ def sanitize_to_nanoseconds(values: np.ndarray) -> np.ndarray:
17031703
elif dtype.kind == "m" and dtype != TD64NS_DTYPE:
17041704
values = conversion.ensure_timedelta64ns(values)
17051705

1706+
elif copy:
1707+
values = values.copy()
1708+
17061709
return values
17071710

17081711

0 commit comments

Comments
 (0)