From b1e4bb3563709f8ba18e982f409ff2029b6532a8 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 28 Sep 2020 18:19:56 -0700 Subject: [PATCH] EA: Tighten signature on DatetimeArray._from_sequence --- pandas/core/arrays/datetimes.py | 6 ++++- pandas/core/indexes/datetimes.py | 2 +- pandas/core/nanops.py | 4 ++- pandas/tests/arrays/test_array.py | 4 ++- pandas/tests/arrays/test_datetimes.py | 27 +++++++++++++------ pandas/tests/extension/test_datetime.py | 4 ++- .../indexes/datetimes/test_constructors.py | 4 ++- pandas/tests/scalar/test_nat.py | 5 +++- 8 files changed, 41 insertions(+), 15 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 6b051f1f73467..3e9a06a0faa17 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -296,7 +296,11 @@ def _simple_new(cls, values, freq=None, dtype=DT64NS_DTYPE): return result @classmethod - def _from_sequence( + def _from_sequence(cls, scalars, dtype=None, copy: bool = False): + return cls._from_sequence_not_strict(scalars, dtype=dtype, copy=copy) + + @classmethod + def _from_sequence_not_strict( cls, data, dtype=None, diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 016544d823ae3..43ec4fe376030 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -267,7 +267,7 @@ def __new__( name = maybe_extract_name(name, data, cls) - dtarr = DatetimeArray._from_sequence( + dtarr = DatetimeArray._from_sequence_not_strict( data, dtype=dtype, copy=copy, diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index 64470da2fb910..f2354f649b1e3 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -1616,7 +1616,9 @@ def na_accum_func(values: ArrayLike, accum_func, skipna: bool) -> ArrayLike: result = result.view(orig_dtype) else: # DatetimeArray - result = type(values)._from_sequence(result, dtype=orig_dtype) + result = type(values)._simple_new( # type: ignore[attr-defined] + result, dtype=orig_dtype + ) elif skipna and not issubclass(values.dtype.type, (np.integer, np.bool_)): vals = values.copy() diff --git a/pandas/tests/arrays/test_array.py b/pandas/tests/arrays/test_array.py index 304e1c80a3f77..096897f62a594 100644 --- a/pandas/tests/arrays/test_array.py +++ b/pandas/tests/arrays/test_array.py @@ -204,7 +204,9 @@ def test_array_copy(): datetime.datetime(2000, 1, 1, tzinfo=cet), datetime.datetime(2001, 1, 1, tzinfo=cet), ], - DatetimeArray._from_sequence(["2000", "2001"], tz=cet), + DatetimeArray._from_sequence( + ["2000", "2001"], dtype=pd.DatetimeTZDtype(tz=cet) + ), ), # timedelta ( diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index 53f26de09f94e..e7605125e7420 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -71,7 +71,7 @@ def test_mixing_naive_tzaware_raises(self, meth): def test_from_pandas_array(self): arr = pd.array(np.arange(5, dtype=np.int64)) * 3600 * 10 ** 9 - result = DatetimeArray._from_sequence(arr, freq="infer") + result = DatetimeArray._from_sequence(arr)._with_freq("infer") expected = pd.date_range("1970-01-01", periods=5, freq="H")._data tm.assert_datetime_array_equal(result, expected) @@ -162,7 +162,9 @@ def test_cmp_dt64_arraylike_tznaive(self, all_compare_operators): class TestDatetimeArray: def test_astype_to_same(self): - arr = DatetimeArray._from_sequence(["2000"], tz="US/Central") + arr = DatetimeArray._from_sequence( + ["2000"], dtype=DatetimeTZDtype(tz="US/Central") + ) result = arr.astype(DatetimeTZDtype(tz="US/Central"), copy=False) assert result is arr @@ -193,7 +195,9 @@ def test_astype_int(self, dtype): tm.assert_numpy_array_equal(result, expected) def test_tz_setter_raises(self): - arr = DatetimeArray._from_sequence(["2000"], tz="US/Central") + arr = DatetimeArray._from_sequence( + ["2000"], dtype=DatetimeTZDtype(tz="US/Central") + ) with pytest.raises(AttributeError, match="tz_localize"): arr.tz = "UTC" @@ -282,7 +286,8 @@ def test_fillna_preserves_tz(self, method): fill_val = dti[1] if method == "pad" else dti[3] expected = DatetimeArray._from_sequence( - [dti[0], dti[1], fill_val, dti[3], dti[4]], freq=None, tz="US/Central" + [dti[0], dti[1], fill_val, dti[3], dti[4]], + dtype=DatetimeTZDtype(tz="US/Central"), ) result = arr.fillna(method=method) @@ -434,12 +439,16 @@ def test_shift_value_tzawareness_mismatch(self): class TestSequenceToDT64NS: def test_tz_dtype_mismatch_raises(self): - arr = DatetimeArray._from_sequence(["2000"], tz="US/Central") + arr = DatetimeArray._from_sequence( + ["2000"], dtype=DatetimeTZDtype(tz="US/Central") + ) with pytest.raises(TypeError, match="data is already tz-aware"): sequence_to_dt64ns(arr, dtype=DatetimeTZDtype(tz="UTC")) def test_tz_dtype_matches(self): - arr = DatetimeArray._from_sequence(["2000"], tz="US/Central") + arr = DatetimeArray._from_sequence( + ["2000"], dtype=DatetimeTZDtype(tz="US/Central") + ) result, _, _ = sequence_to_dt64ns(arr, dtype=DatetimeTZDtype(tz="US/Central")) tm.assert_numpy_array_equal(arr._data, result) @@ -447,6 +456,7 @@ def test_tz_dtype_matches(self): class TestReductions: @pytest.mark.parametrize("tz", [None, "US/Central"]) def test_min_max(self, tz): + dtype = DatetimeTZDtype(tz=tz) if tz is not None else np.dtype("M8[ns]") arr = DatetimeArray._from_sequence( [ "2000-01-03", @@ -456,7 +466,7 @@ def test_min_max(self, tz): "2000-01-05", "2000-01-04", ], - tz=tz, + dtype=dtype, ) result = arr.min() @@ -476,7 +486,8 @@ def test_min_max(self, tz): @pytest.mark.parametrize("tz", [None, "US/Central"]) @pytest.mark.parametrize("skipna", [True, False]) def test_min_max_empty(self, skipna, tz): - arr = DatetimeArray._from_sequence([], tz=tz) + dtype = DatetimeTZDtype(tz=tz) if tz is not None else np.dtype("M8[ns]") + arr = DatetimeArray._from_sequence([], dtype=dtype) result = arr.min(skipna=skipna) assert result is pd.NaT diff --git a/pandas/tests/extension/test_datetime.py b/pandas/tests/extension/test_datetime.py index e026809f7e611..0fde1e8a2fdb8 100644 --- a/pandas/tests/extension/test_datetime.py +++ b/pandas/tests/extension/test_datetime.py @@ -181,8 +181,10 @@ def test_concat_mixed_dtypes(self, data): @pytest.mark.parametrize("obj", ["series", "frame"]) def test_unstack(self, obj): # GH-13287: can't use base test, since building the expected fails. + dtype = DatetimeTZDtype(tz="US/Central") data = DatetimeArray._from_sequence( - ["2000", "2001", "2002", "2003"], tz="US/Central" + ["2000", "2001", "2002", "2003"], + dtype=dtype, ) index = pd.MultiIndex.from_product(([["A", "B"], ["a", "b"]]), names=["a", "b"]) diff --git a/pandas/tests/indexes/datetimes/test_constructors.py b/pandas/tests/indexes/datetimes/test_constructors.py index 9a855a1624520..d3c79f231449a 100644 --- a/pandas/tests/indexes/datetimes/test_constructors.py +++ b/pandas/tests/indexes/datetimes/test_constructors.py @@ -16,7 +16,9 @@ class TestDatetimeIndex: - @pytest.mark.parametrize("dt_cls", [DatetimeIndex, DatetimeArray._from_sequence]) + @pytest.mark.parametrize( + "dt_cls", [DatetimeIndex, DatetimeArray._from_sequence_not_strict] + ) def test_freq_validation_with_nat(self, dt_cls): # GH#11587 make sure we get a useful error message when generate_range # raises diff --git a/pandas/tests/scalar/test_nat.py b/pandas/tests/scalar/test_nat.py index 09d5d9c1677d0..2ea7602b00206 100644 --- a/pandas/tests/scalar/test_nat.py +++ b/pandas/tests/scalar/test_nat.py @@ -12,6 +12,7 @@ from pandas import ( DatetimeIndex, + DatetimeTZDtype, Index, NaT, Period, @@ -440,7 +441,9 @@ def test_nat_rfloordiv_timedelta(val, expected): DatetimeIndex(["2011-01-01", "2011-01-02"], name="x"), DatetimeIndex(["2011-01-01", "2011-01-02"], tz="US/Eastern", name="x"), DatetimeArray._from_sequence(["2011-01-01", "2011-01-02"]), - DatetimeArray._from_sequence(["2011-01-01", "2011-01-02"], tz="US/Pacific"), + DatetimeArray._from_sequence( + ["2011-01-01", "2011-01-02"], dtype=DatetimeTZDtype(tz="US/Pacific") + ), TimedeltaIndex(["1 day", "2 day"], name="x"), ], )