Skip to content

Commit b6d5e97

Browse files
authored
REF: share DTA/TDA.__init__ (#47583)
1 parent 8e8f627 commit b6d5e97

File tree

3 files changed

+89
-131
lines changed

3 files changed

+89
-131
lines changed

pandas/core/arrays/datetimelike.py

+78
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
algos,
2626
lib,
2727
)
28+
from pandas._libs.arrays import NDArrayBacked
2829
from pandas._libs.tslibs import (
2930
BaseOffset,
3031
IncompatibleFrequency,
@@ -1906,6 +1907,81 @@ class TimelikeOps(DatetimeLikeArrayMixin):
19061907
Common ops for TimedeltaIndex/DatetimeIndex, but not PeriodIndex.
19071908
"""
19081909

1910+
_default_dtype: np.dtype
1911+
1912+
def __init__(self, values, dtype=None, freq=lib.no_default, copy: bool = False):
1913+
values = extract_array(values, extract_numpy=True)
1914+
if isinstance(values, IntegerArray):
1915+
values = values.to_numpy("int64", na_value=iNaT)
1916+
1917+
inferred_freq = getattr(values, "_freq", None)
1918+
explicit_none = freq is None
1919+
freq = freq if freq is not lib.no_default else None
1920+
1921+
if isinstance(values, type(self)):
1922+
if explicit_none:
1923+
# don't inherit from values
1924+
pass
1925+
elif freq is None:
1926+
freq = values.freq
1927+
elif freq and values.freq:
1928+
freq = to_offset(freq)
1929+
freq, _ = validate_inferred_freq(freq, values.freq, False)
1930+
1931+
if dtype is not None:
1932+
dtype = pandas_dtype(dtype)
1933+
if not is_dtype_equal(dtype, values.dtype):
1934+
# TODO: we only have tests for this for DTA, not TDA (2022-07-01)
1935+
raise TypeError(
1936+
f"dtype={dtype} does not match data dtype {values.dtype}"
1937+
)
1938+
1939+
dtype = values.dtype
1940+
values = values._ndarray
1941+
1942+
elif dtype is None:
1943+
dtype = self._default_dtype
1944+
1945+
if not isinstance(values, np.ndarray):
1946+
raise ValueError(
1947+
f"Unexpected type '{type(values).__name__}'. 'values' must be a "
1948+
f"{type(self).__name__}, ndarray, or Series or Index "
1949+
"containing one of those."
1950+
)
1951+
if values.ndim not in [1, 2]:
1952+
raise ValueError("Only 1-dimensional input arrays are supported.")
1953+
1954+
if values.dtype == "i8":
1955+
# for compat with datetime/timedelta/period shared methods,
1956+
# we can sometimes get here with int64 values. These represent
1957+
# nanosecond UTC (or tz-naive) unix timestamps
1958+
values = values.view(self._default_dtype)
1959+
1960+
dtype = self._validate_dtype(values, dtype)
1961+
1962+
if freq == "infer":
1963+
raise ValueError(
1964+
f"Frequency inference not allowed in {type(self).__name__}.__init__. "
1965+
"Use 'pd.array()' instead."
1966+
)
1967+
1968+
if copy:
1969+
values = values.copy()
1970+
if freq:
1971+
freq = to_offset(freq)
1972+
1973+
NDArrayBacked.__init__(self, values=values, dtype=dtype)
1974+
self._freq = freq
1975+
1976+
if inferred_freq is None and freq is not None:
1977+
type(self)._validate_frequency(self, freq)
1978+
1979+
@classmethod
1980+
def _validate_dtype(cls, values, dtype):
1981+
raise AbstractMethodError(cls)
1982+
1983+
# --------------------------------------------------------------
1984+
19091985
@cache_readonly
19101986
def _reso(self) -> int:
19111987
return get_unit_from_dtype(self._ndarray.dtype)
@@ -1917,6 +1993,8 @@ def _unit(self) -> str:
19171993
# "ExtensionDtype"; expected "Union[DatetimeTZDtype, dtype[Any]]"
19181994
return dtype_to_unit(self.dtype) # type: ignore[arg-type]
19191995

1996+
# --------------------------------------------------------------
1997+
19201998
def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
19211999
if (
19222000
ufunc in [np.isnan, np.isinf, np.isfinite]

pandas/core/arrays/datetimes.py

+5-70
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
lib,
2020
tslib,
2121
)
22-
from pandas._libs.arrays import NDArrayBacked
2322
from pandas._libs.tslibs import (
2423
BaseOffset,
2524
NaT,
@@ -30,7 +29,6 @@
3029
fields,
3130
get_resolution,
3231
get_unit_from_dtype,
33-
iNaT,
3432
ints_to_pydatetime,
3533
is_date_array_normalized,
3634
is_unitless,
@@ -72,9 +70,7 @@
7270

7371
from pandas.core.arrays import datetimelike as dtl
7472
from pandas.core.arrays._ranges import generate_regular_range
75-
from pandas.core.arrays.integer import IntegerArray
7673
import pandas.core.common as com
77-
from pandas.core.construction import extract_array
7874

7975
from pandas.tseries.frequencies import get_period_alias
8076
from pandas.tseries.offsets import (
@@ -254,75 +250,14 @@ def _scalar_type(self) -> type[Timestamp]:
254250

255251
_dtype: np.dtype | DatetimeTZDtype
256252
_freq = None
253+
_default_dtype = DT64NS_DTYPE # used in TimeLikeOps.__init__
257254

258-
def __init__(
259-
self, values, dtype=None, freq=lib.no_default, copy: bool = False
260-
) -> None:
261-
values = extract_array(values, extract_numpy=True)
262-
if isinstance(values, IntegerArray):
263-
values = values.to_numpy("int64", na_value=iNaT)
264-
265-
inferred_freq = getattr(values, "_freq", None)
266-
explicit_none = freq is None
267-
freq = freq if freq is not lib.no_default else None
268-
269-
if isinstance(values, type(self)):
270-
if explicit_none:
271-
# don't inherit from values
272-
pass
273-
elif freq is None:
274-
freq = values.freq
275-
elif freq and values.freq:
276-
freq = to_offset(freq)
277-
freq, _ = dtl.validate_inferred_freq(freq, values.freq, False)
278-
279-
if dtype is not None:
280-
dtype = pandas_dtype(dtype)
281-
if not is_dtype_equal(dtype, values.dtype):
282-
raise TypeError(
283-
f"dtype={dtype} does not match data dtype {values.dtype}"
284-
)
285-
286-
dtype = values.dtype
287-
values = values._ndarray
288-
289-
elif dtype is None:
290-
dtype = DT64NS_DTYPE
291-
292-
if not isinstance(values, np.ndarray):
293-
raise ValueError(
294-
f"Unexpected type '{type(values).__name__}'. 'values' must be a "
295-
f"{type(self).__name__}, ndarray, or Series or Index "
296-
"containing one of those."
297-
)
298-
if values.ndim not in [1, 2]:
299-
raise ValueError("Only 1-dimensional input arrays are supported.")
300-
301-
if values.dtype == "i8":
302-
# for compat with datetime/timedelta/period shared methods,
303-
# we can sometimes get here with int64 values. These represent
304-
# nanosecond UTC (or tz-naive) unix timestamps
305-
values = values.view(DT64NS_DTYPE)
306-
255+
@classmethod
256+
def _validate_dtype(cls, values, dtype):
257+
# used in TimeLikeOps.__init__
307258
_validate_dt64_dtype(values.dtype)
308259
dtype = _validate_dt64_dtype(dtype)
309-
310-
if freq == "infer":
311-
raise ValueError(
312-
f"Frequency inference not allowed in {type(self).__name__}.__init__. "
313-
"Use 'pd.array()' instead."
314-
)
315-
316-
if copy:
317-
values = values.copy()
318-
if freq:
319-
freq = to_offset(freq)
320-
321-
NDArrayBacked.__init__(self, values=values, dtype=dtype)
322-
self._freq = freq
323-
324-
if inferred_freq is None and freq is not None:
325-
type(self)._validate_frequency(self, freq)
260+
return dtype
326261

327262
# error: Signature of "_simple_new" incompatible with supertype "NDArrayBacked"
328263
@classmethod

pandas/core/arrays/timedeltas.py

+6-61
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
lib,
1313
tslibs,
1414
)
15-
from pandas._libs.arrays import NDArrayBacked
1615
from pandas._libs.tslibs import (
1716
BaseOffset,
1817
NaT,
@@ -54,13 +53,9 @@
5453
from pandas.core.dtypes.missing import isna
5554

5655
from pandas.core import nanops
57-
from pandas.core.arrays import (
58-
IntegerArray,
59-
datetimelike as dtl,
60-
)
56+
from pandas.core.arrays import datetimelike as dtl
6157
from pandas.core.arrays._ranges import generate_regular_range
6258
import pandas.core.common as com
63-
from pandas.core.construction import extract_array
6459
from pandas.core.ops.common import unpack_zerodim_and_defer
6560

6661
if TYPE_CHECKING:
@@ -171,64 +166,14 @@ def dtype(self) -> np.dtype: # type: ignore[override]
171166
# Constructors
172167

173168
_freq = None
169+
_default_dtype = TD64NS_DTYPE # used in TimeLikeOps.__init__
174170

175-
def __init__(
176-
self, values, dtype=TD64NS_DTYPE, freq=lib.no_default, copy: bool = False
177-
) -> None:
178-
values = extract_array(values, extract_numpy=True)
179-
if isinstance(values, IntegerArray):
180-
values = values.to_numpy("int64", na_value=tslibs.iNaT)
181-
182-
inferred_freq = getattr(values, "_freq", None)
183-
explicit_none = freq is None
184-
freq = freq if freq is not lib.no_default else None
185-
186-
if isinstance(values, type(self)):
187-
if explicit_none:
188-
# don't inherit from values
189-
pass
190-
elif freq is None:
191-
freq = values.freq
192-
elif freq and values.freq:
193-
freq = to_offset(freq)
194-
freq, _ = dtl.validate_inferred_freq(freq, values.freq, False)
195-
196-
values = values._ndarray
197-
198-
if not isinstance(values, np.ndarray):
199-
raise ValueError(
200-
f"Unexpected type '{type(values).__name__}'. 'values' must be a "
201-
f"{type(self).__name__}, ndarray, or Series or Index "
202-
"containing one of those."
203-
)
204-
if values.ndim not in [1, 2]:
205-
raise ValueError("Only 1-dimensional input arrays are supported.")
206-
207-
if values.dtype == "i8":
208-
# for compat with datetime/timedelta/period shared methods,
209-
# we can sometimes get here with int64 values. These represent
210-
# nanosecond UTC (or tz-naive) unix timestamps
211-
values = values.view(TD64NS_DTYPE)
212-
171+
@classmethod
172+
def _validate_dtype(cls, values, dtype):
173+
# used in TimeLikeOps.__init__
213174
_validate_td64_dtype(values.dtype)
214175
dtype = _validate_td64_dtype(dtype)
215-
216-
if freq == "infer":
217-
raise ValueError(
218-
f"Frequency inference not allowed in {type(self).__name__}.__init__. "
219-
"Use 'pd.array()' instead."
220-
)
221-
222-
if copy:
223-
values = values.copy()
224-
if freq:
225-
freq = to_offset(freq)
226-
227-
NDArrayBacked.__init__(self, values=values, dtype=dtype)
228-
self._freq = freq
229-
230-
if inferred_freq is None and freq is not None:
231-
type(self)._validate_frequency(self, freq)
176+
return dtype
232177

233178
# error: Signature of "_simple_new" incompatible with supertype "NDArrayBacked"
234179
@classmethod

0 commit comments

Comments
 (0)