Skip to content

REF: share some constructor code #47555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@
DatetimeTZDtype,
ExtensionDtype,
)
from pandas.core.dtypes.generic import (
ABCCategorical,
ABCMultiIndex,
)
from pandas.core.dtypes.missing import (
is_valid_na_for_dtype,
isna,
Expand All @@ -114,6 +118,8 @@
NDArrayBackedExtensionArray,
ravel_compat,
)
from pandas.core.arrays.base import ExtensionArray
from pandas.core.arrays.integer import IntegerArray
import pandas.core.common as com
from pandas.core.construction import (
array as pd_array,
Expand Down Expand Up @@ -2024,6 +2030,36 @@ def factorize( # type:ignore[override]
# Shared Constructor Helpers


def ensure_arraylike_for_datetimelike(data, copy: bool, cls_name: str):
if not hasattr(data, "dtype"):
# e.g. list, tuple
if np.ndim(data) == 0:
# i.e. generator
data = list(data)
data = np.asarray(data)
copy = False
elif isinstance(data, ABCMultiIndex):
raise TypeError(f"Cannot create a {cls_name} from a MultiIndex.")
else:
data = extract_array(data, extract_numpy=True)

if isinstance(data, IntegerArray):
data = data.to_numpy("int64", na_value=iNaT)
copy = False
elif not isinstance(data, (np.ndarray, ExtensionArray)):
# GH#24539 e.g. xarray, dask object
data = np.asarray(data)

elif isinstance(data, ABCCategorical):
# GH#18664 preserve tz in going DTI->Categorical->DTI
# TODO: cases where we need to do another pass through maybe_convert_dtype,
# e.g. the categories are timedelta64s
data = data.categories.take(data.codes, fill_value=NaT)._values
copy = False

return data, copy


def validate_periods(periods):
"""
If a `periods` argument is passed to the Datetime/Timedelta Array/Index
Expand Down
34 changes: 4 additions & 30 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
DT64NS_DTYPE,
INT64_DTYPE,
is_bool_dtype,
is_categorical_dtype,
is_datetime64_any_dtype,
is_datetime64_dtype,
is_datetime64_ns_dtype,
Expand All @@ -69,13 +68,9 @@
pandas_dtype,
)
from pandas.core.dtypes.dtypes import DatetimeTZDtype
from pandas.core.dtypes.generic import ABCMultiIndex
from pandas.core.dtypes.missing import isna

from pandas.core.arrays import (
ExtensionArray,
datetimelike as dtl,
)
from pandas.core.arrays import datetimelike as dtl
from pandas.core.arrays._ranges import generate_regular_range
from pandas.core.arrays.integer import IntegerArray
import pandas.core.common as com
Expand Down Expand Up @@ -2064,23 +2059,9 @@ def _sequence_to_dt64ns(
# if dtype has an embedded tz, capture it
tz = validate_tz_from_dtype(dtype, tz)

if not hasattr(data, "dtype"):
# e.g. list, tuple
if np.ndim(data) == 0:
# i.e. generator
data = list(data)
data = np.asarray(data)
copy = False
elif isinstance(data, ABCMultiIndex):
raise TypeError("Cannot create a DatetimeArray from a MultiIndex.")
else:
data = extract_array(data, extract_numpy=True)

if isinstance(data, IntegerArray):
data = data.to_numpy("int64", na_value=iNaT)
elif not isinstance(data, (np.ndarray, ExtensionArray)):
# GH#24539 e.g. xarray, dask object
data = np.asarray(data)
data, copy = dtl.ensure_arraylike_for_datetimelike(
data, copy, cls_name="DatetimeArray"
)

if isinstance(data, DatetimeArray):
inferred_freq = data.freq
Expand Down Expand Up @@ -2320,13 +2301,6 @@ def maybe_convert_dtype(data, copy: bool, tz: tzinfo | None = None):
"Passing PeriodDtype data is invalid. Use `data.to_timestamp()` instead"
)

elif is_categorical_dtype(data.dtype):
# GH#18664 preserve tz in going DTI->Categorical->DTI
# TODO: cases where we need to do another pass through this func,
# e.g. the categories are timedelta64s
data = data.categories.take(data.codes, fill_value=NaT)._values
copy = False

elif is_extension_array_dtype(data.dtype) and not is_datetime64tz_dtype(data.dtype):
# TODO: We have no tests for these
data = np.array(data, dtype=np.object_)
Expand Down
28 changes: 3 additions & 25 deletions pandas/core/arrays/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,10 @@
is_timedelta64_dtype,
pandas_dtype,
)
from pandas.core.dtypes.generic import (
ABCCategorical,
ABCMultiIndex,
)
from pandas.core.dtypes.missing import isna

from pandas.core import nanops
from pandas.core.arrays import (
ExtensionArray,
IntegerArray,
datetimelike as dtl,
)
Expand Down Expand Up @@ -936,26 +931,9 @@ def sequence_to_td64ns(
if unit is not None:
unit = parse_timedelta_unit(unit)

# Unwrap whatever we have into a np.ndarray
if not hasattr(data, "dtype"):
# e.g. list, tuple
if np.ndim(data) == 0:
# i.e. generator
data = list(data)
data = np.array(data, copy=False)
elif isinstance(data, ABCMultiIndex):
raise TypeError("Cannot create a TimedeltaArray from a MultiIndex.")
else:
data = extract_array(data, extract_numpy=True)

if isinstance(data, IntegerArray):
data = data.to_numpy("int64", na_value=iNaT)
elif not isinstance(data, (np.ndarray, ExtensionArray)):
# GH#24539 e.g. xarray, dask object
data = np.asarray(data)
elif isinstance(data, ABCCategorical):
data = data.categories.take(data.codes, fill_value=NaT)._values
copy = False
data, copy = dtl.ensure_arraylike_for_datetimelike(
data, copy, cls_name="TimedeltaArray"
)

if isinstance(data, TimedeltaArray):
inferred_freq = data.freq
Expand Down