From 17f991f273265d1958814c814aa5e7d74d20d1b0 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Oct 2020 14:44:37 -0700 Subject: [PATCH 1/4] CLN: test cleanup --- pandas/tests/arrays/test_datetimelike.py | 24 +++++++++++++----------- pandas/tests/arrays/test_timedeltas.py | 1 + 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index 3f5ab5baa7d69..aa902b313feba 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -17,7 +17,12 @@ # TODO: more freq variants @pytest.fixture(params=["D", "B", "W", "M", "Q", "Y"]) -def period_index(request): +def freqstr(request): + return request.param + + +@pytest.fixture +def period_index(freqstr): """ A fixture to provide PeriodIndex objects with different frequencies. @@ -25,14 +30,13 @@ def period_index(request): so here we just test that the PeriodArray behavior matches the PeriodIndex behavior. """ - freqstr = request.param # TODO: non-monotone indexes; NaTs, different start dates pi = pd.period_range(start=pd.Timestamp("2000-01-01"), periods=100, freq=freqstr) return pi -@pytest.fixture(params=["D", "B", "W", "M", "Q", "Y"]) -def datetime_index(request): +@pytest.fixture +def datetime_index(freqstr): """ A fixture to provide DatetimeIndex objects with different frequencies. @@ -40,14 +44,13 @@ def datetime_index(request): so here we just test that the DatetimeArray behavior matches the DatetimeIndex behavior. """ - freqstr = request.param # TODO: non-monotone indexes; NaTs, different start dates, timezones dti = pd.date_range(start=pd.Timestamp("2000-01-01"), periods=100, freq=freqstr) return dti @pytest.fixture -def timedelta_index(request): +def timedelta_index(): """ A fixture to provide TimedeltaIndex objects with different frequencies. Most TimedeltaArray behavior is already tested in TimedeltaIndex tests, @@ -438,16 +441,15 @@ class TestDatetimeArray(SharedTests): dtype = pd.Timestamp @pytest.fixture - def arr1d(self, tz_naive_fixture): + def arr1d(self, tz_naive_fixture, freqstr): tz = tz_naive_fixture - dti = pd.date_range("2016-01-01 01:01:00", periods=3, freq="H", tz=tz) + dti = pd.date_range("2016-01-01 01:01:00", periods=3, freq=freqstr, tz=tz) dta = dti._data return dta - def test_round(self, tz_naive_fixture): + def test_round(self, arr1d): # GH#24064 - tz = tz_naive_fixture - dti = pd.date_range("2016-01-01 01:01:00", periods=3, freq="H", tz=tz) + dti = self.index_cls(arr1d) result = dti.round(freq="2T") expected = dti - pd.Timedelta(minutes=1) diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index a32529cb58ba3..7cd7285f9e2eb 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -61,6 +61,7 @@ def test_copy(self): class TestTimedeltaArray: + # TODO: de-duplicate with test_npsum below def test_np_sum(self): # GH#25282 vals = np.arange(5, dtype=np.int64).view("m8[h]").astype("m8[ns]") From 2d11242748f1ae44f0c22cf52252e94d3f2c0f26 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Oct 2020 14:46:13 -0700 Subject: [PATCH 2/4] use arr1d fixture --- pandas/tests/arrays/test_datetimelike.py | 36 +++++++++++------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index aa902b313feba..0dadbf30e3d79 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -503,11 +503,10 @@ def test_array_interface(self, datetime_index): expected = np.asarray(arr).astype(dtype) tm.assert_numpy_array_equal(result, expected) - def test_array_object_dtype(self, tz_naive_fixture): + def test_array_object_dtype(self, arr1d): # GH#23524 - tz = tz_naive_fixture - dti = pd.date_range("2016-01-01", periods=3, tz=tz) - arr = DatetimeArray(dti) + arr = arr1d + dti = self.index_cls(arr1d) expected = np.array(list(dti)) @@ -518,11 +517,10 @@ def test_array_object_dtype(self, tz_naive_fixture): result = np.array(dti, dtype=object) tm.assert_numpy_array_equal(result, expected) - def test_array_tz(self, tz_naive_fixture): + def test_array_tz(self, arr1d): # GH#23524 - tz = tz_naive_fixture - dti = pd.date_range("2016-01-01", periods=3, tz=tz) - arr = DatetimeArray(dti) + arr = arr1d + dti = self.index_cls(arr1d) expected = dti.asi8.view("M8[ns]") result = np.array(arr, dtype="M8[ns]") @@ -539,10 +537,9 @@ def test_array_tz(self, tz_naive_fixture): assert result.base is expected.base assert result.base is not None - def test_array_i8_dtype(self, tz_naive_fixture): - tz = tz_naive_fixture - dti = pd.date_range("2016-01-01", periods=3, tz=tz) - arr = DatetimeArray(dti) + def test_array_i8_dtype(self, arr1d): + arr = arr1d + dti = self.index_cls(arr1d) expected = dti.asi8 result = np.array(arr, dtype="i8") @@ -565,10 +562,9 @@ def test_from_array_keeps_base(self): dta = DatetimeArray(arr[:0]) assert dta._data.base is arr - def test_from_dti(self, tz_naive_fixture): - tz = tz_naive_fixture - dti = pd.date_range("2016-01-01", periods=3, tz=tz) - arr = DatetimeArray(dti) + def test_from_dti(self, arr1d): + arr = arr1d + dti = self.index_cls(arr1d) assert list(dti) == list(arr) # Check that Index.__new__ knows what to do with DatetimeArray @@ -576,10 +572,10 @@ def test_from_dti(self, tz_naive_fixture): assert isinstance(dti2, pd.DatetimeIndex) assert list(dti2) == list(arr) - def test_astype_object(self, tz_naive_fixture): - tz = tz_naive_fixture - dti = pd.date_range("2016-01-01", periods=3, tz=tz) - arr = DatetimeArray(dti) + def test_astype_object(self, arr1d): + arr = arr1d + dti = self.index_cls(arr1d) + asobj = arr.astype("O") assert isinstance(asobj, np.ndarray) assert asobj.dtype == "O" From cd5cce192341b520ab6e1ce0838e81f6d13cd5ce Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Oct 2020 15:01:22 -0700 Subject: [PATCH 3/4] CLN: use fixture consistetnyl --- pandas/tests/arrays/test_datetimelike.py | 72 +++++++++++------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index 0dadbf30e3d79..c50927eb66a52 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -581,7 +581,6 @@ def test_astype_object(self, arr1d): assert asobj.dtype == "O" assert list(asobj) == list(dti) - @pytest.mark.parametrize("freqstr", ["D", "B", "W", "M", "Q", "Y"]) def test_to_perioddelta(self, datetime_index, freqstr): # GH#23113 dti = datetime_index @@ -600,7 +599,6 @@ def test_to_perioddelta(self, datetime_index, freqstr): # an EA-specific tm.assert_ function tm.assert_index_equal(pd.Index(result), pd.Index(expected)) - @pytest.mark.parametrize("freqstr", ["D", "B", "W", "M", "Q", "Y"]) def test_to_period(self, datetime_index, freqstr): dti = datetime_index arr = DatetimeArray(dti) @@ -614,10 +612,10 @@ def test_to_period(self, datetime_index, freqstr): tm.assert_index_equal(pd.Index(result), pd.Index(expected)) @pytest.mark.parametrize("propname", pd.DatetimeIndex._bool_ops) - def test_bool_properties(self, datetime_index, propname): + def test_bool_properties(self, arr1d, propname): # in this case _bool_ops is just `is_leap_year` - dti = datetime_index - arr = DatetimeArray(dti) + dti = self.index_cls(arr1d) + arr = arr1d assert dti.freq == arr.freq result = getattr(arr, propname) @@ -626,21 +624,21 @@ def test_bool_properties(self, datetime_index, propname): tm.assert_numpy_array_equal(result, expected) @pytest.mark.parametrize("propname", pd.DatetimeIndex._field_ops) - def test_int_properties(self, datetime_index, propname): + def test_int_properties(self, arr1d, propname): if propname in ["week", "weekofyear"]: # GH#33595 Deprecate week and weekofyear return - dti = datetime_index - arr = DatetimeArray(dti) + dti = self.index_cls(arr1d) + arr = arr1d result = getattr(arr, propname) expected = np.array(getattr(dti, propname), dtype=result.dtype) tm.assert_numpy_array_equal(result, expected) - def test_take_fill_valid(self, datetime_index, tz_naive_fixture): - dti = datetime_index.tz_localize(tz_naive_fixture) - arr = DatetimeArray(dti) + def test_take_fill_valid(self, arr1d): + arr = arr1d + dti = self.index_cls(arr1d) now = pd.Timestamp.now().tz_localize(dti.tz) result = arr.take([-1, 1], allow_fill=True, fill_value=now) @@ -675,10 +673,9 @@ def test_take_fill_valid(self, datetime_index, tz_naive_fixture): # require appropriate-dtype if we have a NA value arr.take([-1, 1], allow_fill=True, fill_value=value) - def test_concat_same_type_invalid(self, datetime_index): + def test_concat_same_type_invalid(self, arr1d): # different timezones - dti = datetime_index - arr = DatetimeArray(dti) + arr = arr1d if arr.tz is None: other = arr.tz_localize("UTC") @@ -706,8 +703,8 @@ def test_concat_same_type_different_freq(self): tm.assert_datetime_array_equal(result, expected) - def test_strftime(self, datetime_index): - arr = DatetimeArray(datetime_index) + def test_strftime(self, arr1d): + arr = arr1d result = arr.strftime("%Y %b") expected = np.array([ts.strftime("%Y %b") for ts in arr], dtype=object) @@ -852,9 +849,9 @@ class TestPeriodArray(SharedTests): def arr1d(self, period_index): return period_index._data - def test_from_pi(self, period_index): - pi = period_index - arr = PeriodArray(pi) + def test_from_pi(self, arr1d): + pi = self.index_cls(arr1d) + arr = arr1d assert list(arr) == list(pi) # Check that Index.__new__ knows what to do with PeriodArray @@ -862,17 +859,16 @@ def test_from_pi(self, period_index): assert isinstance(pi2, pd.PeriodIndex) assert list(pi2) == list(arr) - def test_astype_object(self, period_index): - pi = period_index - arr = PeriodArray(pi) + def test_astype_object(self, arr1d): + pi = self.index_cls(arr1d) + arr = arr1d asobj = arr.astype("O") assert isinstance(asobj, np.ndarray) assert asobj.dtype == "O" assert list(asobj) == list(pi) - def test_take_fill_valid(self, period_index): - pi = period_index - arr = PeriodArray(pi) + def test_take_fill_valid(self, arr1d): + arr = arr1d value = pd.NaT.value msg = f"'fill_value' should be a {self.dtype}. Got '{value}'." @@ -887,9 +883,9 @@ def test_take_fill_valid(self, period_index): arr.take([-1, 1], allow_fill=True, fill_value=value) @pytest.mark.parametrize("how", ["S", "E"]) - def test_to_timestamp(self, how, period_index): - pi = period_index - arr = PeriodArray(pi) + def test_to_timestamp(self, how, arr1d): + pi = self.index_cls(arr1d) + arr = arr1d expected = DatetimeArray(pi.to_timestamp(how=how)) result = arr.to_timestamp(how=how) @@ -910,10 +906,10 @@ def test_to_timestamp_out_of_bounds(self): pi._data.to_timestamp() @pytest.mark.parametrize("propname", PeriodArray._bool_ops) - def test_bool_properties(self, period_index, propname): + def test_bool_properties(self, arr1d, propname): # in this case _bool_ops is just `is_leap_year` - pi = period_index - arr = PeriodArray(pi) + pi = self.index_cls(arr1d) + arr = arr1d result = getattr(arr, propname) expected = np.array(getattr(pi, propname)) @@ -921,17 +917,17 @@ def test_bool_properties(self, period_index, propname): tm.assert_numpy_array_equal(result, expected) @pytest.mark.parametrize("propname", PeriodArray._field_ops) - def test_int_properties(self, period_index, propname): - pi = period_index - arr = PeriodArray(pi) + def test_int_properties(self, arr1d, propname): + pi = self.index_cls(arr1d) + arr = arr1d result = getattr(arr, propname) expected = np.array(getattr(pi, propname)) tm.assert_numpy_array_equal(result, expected) - def test_array_interface(self, period_index): - arr = PeriodArray(period_index) + def test_array_interface(self, arr1d): + arr = arr1d # default asarray gives objects result = np.asarray(arr) @@ -954,8 +950,8 @@ def test_array_interface(self, period_index): expected = np.asarray(arr).astype("S20") tm.assert_numpy_array_equal(result, expected) - def test_strftime(self, period_index): - arr = PeriodArray(period_index) + def test_strftime(self, arr1d): + arr = arr1d result = arr.strftime("%Y") expected = np.array([per.strftime("%Y") for per in arr], dtype=object) From fbecbe3607708b6a11ab6571b51256642c18fd15 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Oct 2020 15:30:07 -0700 Subject: [PATCH 4/4] REF: collect unary ops tests --- pandas/tests/arrays/test_timedeltas.py | 60 +++++++++++++------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index 7cd7285f9e2eb..b3b8f4d55e4de 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -77,35 +77,6 @@ def test_from_sequence_dtype(self): with pytest.raises(ValueError, match=msg): TimedeltaArray._from_sequence([], dtype=object) - def test_abs(self): - vals = np.array([-3600 * 10 ** 9, "NaT", 7200 * 10 ** 9], dtype="m8[ns]") - arr = TimedeltaArray(vals) - - evals = np.array([3600 * 10 ** 9, "NaT", 7200 * 10 ** 9], dtype="m8[ns]") - expected = TimedeltaArray(evals) - - result = abs(arr) - tm.assert_timedelta_array_equal(result, expected) - - def test_neg(self): - vals = np.array([-3600 * 10 ** 9, "NaT", 7200 * 10 ** 9], dtype="m8[ns]") - arr = TimedeltaArray(vals) - - evals = np.array([3600 * 10 ** 9, "NaT", -7200 * 10 ** 9], dtype="m8[ns]") - expected = TimedeltaArray(evals) - - result = -arr - tm.assert_timedelta_array_equal(result, expected) - - def test_neg_freq(self): - tdi = pd.timedelta_range("2 Days", periods=4, freq="H") - arr = TimedeltaArray(tdi, freq=tdi.freq) - - expected = TimedeltaArray(-tdi._data, freq=-tdi.freq) - - result = -arr - tm.assert_timedelta_array_equal(result, expected) - @pytest.mark.parametrize("dtype", [int, np.int32, np.int64, "uint32", "uint64"]) def test_astype_int(self, dtype): arr = TimedeltaArray._from_sequence([pd.Timedelta("1H"), pd.Timedelta("2H")]) @@ -172,6 +143,37 @@ def test_searchsorted_invalid_types(self, other, index): arr.searchsorted(other) +class TestUnaryOps: + def test_abs(self): + vals = np.array([-3600 * 10 ** 9, "NaT", 7200 * 10 ** 9], dtype="m8[ns]") + arr = TimedeltaArray(vals) + + evals = np.array([3600 * 10 ** 9, "NaT", 7200 * 10 ** 9], dtype="m8[ns]") + expected = TimedeltaArray(evals) + + result = abs(arr) + tm.assert_timedelta_array_equal(result, expected) + + def test_neg(self): + vals = np.array([-3600 * 10 ** 9, "NaT", 7200 * 10 ** 9], dtype="m8[ns]") + arr = TimedeltaArray(vals) + + evals = np.array([3600 * 10 ** 9, "NaT", -7200 * 10 ** 9], dtype="m8[ns]") + expected = TimedeltaArray(evals) + + result = -arr + tm.assert_timedelta_array_equal(result, expected) + + def test_neg_freq(self): + tdi = pd.timedelta_range("2 Days", periods=4, freq="H") + arr = TimedeltaArray(tdi, freq=tdi.freq) + + expected = TimedeltaArray(-tdi._data, freq=-tdi.freq) + + result = -arr + tm.assert_timedelta_array_equal(result, expected) + + class TestReductions: @pytest.mark.parametrize("name", ["sum", "std", "min", "max", "median"]) @pytest.mark.parametrize("skipna", [True, False])