From 39659619a9f1feb7936a4ad82386275143ba83fb Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Dec 2019 09:15:08 -0800 Subject: [PATCH 1/4] REF: move remaining TimedeltaIndex arith tests --- pandas/tests/arithmetic/test_timedelta64.py | 56 ++++++++++++ .../indexes/timedeltas/test_arithmetic.py | 85 +------------------ 2 files changed, 58 insertions(+), 83 deletions(-) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 4a37a56f5029c..441a5f6facf5f 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -484,6 +484,62 @@ def test_tda_add_sub_index(self): expected = tdi - tdi tm.assert_index_equal(result, expected) + # ------------------------------------------------------------- + # Binary operations TimedeltaIndex and timedelta-like + + def test_tdi_iadd_timedeltalike(self, two_hours): + # only test adding/sub offsets as + is now numeric + rng = timedelta_range("1 days", "10 days") + expected = timedelta_range("1 days 02:00:00", "10 days 02:00:00", freq="D") + rng += two_hours + tm.assert_index_equal(rng, expected) + + def test_tdi_isub_timedeltalike(self, two_hours): + # only test adding/sub offsets as - is now numeric + rng = timedelta_range("1 days", "10 days") + expected = timedelta_range("0 days 22:00:00", "9 days 22:00:00") + rng -= two_hours + tm.assert_index_equal(rng, expected) + + # ------------------------------------------------------------- + + def test_tdi_ops_attributes(self): + rng = timedelta_range("2 days", periods=5, freq="2D", name="x") + + result = rng + 1 * rng.freq + exp = timedelta_range("4 days", periods=5, freq="2D", name="x") + tm.assert_index_equal(result, exp) + assert result.freq == "2D" + + result = rng - 2 * rng.freq + exp = timedelta_range("-2 days", periods=5, freq="2D", name="x") + tm.assert_index_equal(result, exp) + assert result.freq == "2D" + + result = rng * 2 + exp = timedelta_range("4 days", periods=5, freq="4D", name="x") + tm.assert_index_equal(result, exp) + assert result.freq == "4D" + + result = rng / 2 + exp = timedelta_range("1 days", periods=5, freq="D", name="x") + tm.assert_index_equal(result, exp) + assert result.freq == "D" + + result = -rng + exp = timedelta_range("-2 days", periods=5, freq="-2D", name="x") + tm.assert_index_equal(result, exp) + assert result.freq == "-2D" + + rng = pd.timedelta_range("-2 days", periods=5, freq="D", name="x") + + result = abs(rng) + exp = TimedeltaIndex( + ["2 days", "1 days", "0 days", "1 days", "2 days"], name="x" + ) + tm.assert_index_equal(result, exp) + assert result.freq is None + class TestAddSubNaTMasking: # TODO: parametrize over boxes diff --git a/pandas/tests/indexes/timedeltas/test_arithmetic.py b/pandas/tests/indexes/timedeltas/test_arithmetic.py index 4f9f8341cb1e5..048b29c0da501 100644 --- a/pandas/tests/indexes/timedeltas/test_arithmetic.py +++ b/pandas/tests/indexes/timedeltas/test_arithmetic.py @@ -1,36 +1,13 @@ -from datetime import timedelta - -import numpy as np import pytest from pandas.errors import NullFrequencyError import pandas as pd -from pandas import Timedelta, TimedeltaIndex, timedelta_range +from pandas import TimedeltaIndex import pandas.util.testing as tm -@pytest.fixture( - params=[ - pd.offsets.Hour(2), - timedelta(hours=2), - np.timedelta64(2, "h"), - Timedelta(hours=2), - ], - ids=str, -) -def delta(request): - # Several ways of representing two hours - return request.param - - -@pytest.fixture(params=["B", "D"]) -def freq(request): - return request.param - - -class TestTimedeltaIndexArithmetic: - # Addition and Subtraction Operations +class TestTimedeltaIndexShift: # ------------------------------------------------------------- # TimedeltaIndex.shift is used by __add__/__sub__ @@ -96,61 +73,3 @@ def test_shift_no_freq(self): tdi = TimedeltaIndex(["1 days 01:00:00", "2 days 01:00:00"], freq=None) with pytest.raises(NullFrequencyError): tdi.shift(2) - - # ------------------------------------------------------------- - # Binary operations TimedeltaIndex and timedelta-like - # Note: add and sub are tested in tests.test_arithmetic, in-place - # tests are kept here because their behavior is Index-specific - - def test_tdi_iadd_timedeltalike(self, delta): - # only test adding/sub offsets as + is now numeric - rng = timedelta_range("1 days", "10 days") - expected = timedelta_range("1 days 02:00:00", "10 days 02:00:00", freq="D") - rng += delta - tm.assert_index_equal(rng, expected) - - def test_tdi_isub_timedeltalike(self, delta): - # only test adding/sub offsets as - is now numeric - rng = timedelta_range("1 days", "10 days") - expected = timedelta_range("0 days 22:00:00", "9 days 22:00:00") - rng -= delta - tm.assert_index_equal(rng, expected) - - # ------------------------------------------------------------- - - def test_tdi_ops_attributes(self): - rng = timedelta_range("2 days", periods=5, freq="2D", name="x") - - result = rng + 1 * rng.freq - exp = timedelta_range("4 days", periods=5, freq="2D", name="x") - tm.assert_index_equal(result, exp) - assert result.freq == "2D" - - result = rng - 2 * rng.freq - exp = timedelta_range("-2 days", periods=5, freq="2D", name="x") - tm.assert_index_equal(result, exp) - assert result.freq == "2D" - - result = rng * 2 - exp = timedelta_range("4 days", periods=5, freq="4D", name="x") - tm.assert_index_equal(result, exp) - assert result.freq == "4D" - - result = rng / 2 - exp = timedelta_range("1 days", periods=5, freq="D", name="x") - tm.assert_index_equal(result, exp) - assert result.freq == "D" - - result = -rng - exp = timedelta_range("-2 days", periods=5, freq="-2D", name="x") - tm.assert_index_equal(result, exp) - assert result.freq == "-2D" - - rng = pd.timedelta_range("-2 days", periods=5, freq="D", name="x") - - result = abs(rng) - exp = TimedeltaIndex( - ["2 days", "1 days", "0 days", "1 days", "2 days"], name="x" - ) - tm.assert_index_equal(result, exp) - assert result.freq is None From 2fdcb4c490ebb1f4bbbbe8741037318ecb28a62c Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Dec 2019 09:15:32 -0800 Subject: [PATCH 2/4] rename test_arithmetic->test_shift --- .../indexes/timedeltas/{test_arithmetic.py => test_shift.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pandas/tests/indexes/timedeltas/{test_arithmetic.py => test_shift.py} (100%) diff --git a/pandas/tests/indexes/timedeltas/test_arithmetic.py b/pandas/tests/indexes/timedeltas/test_shift.py similarity index 100% rename from pandas/tests/indexes/timedeltas/test_arithmetic.py rename to pandas/tests/indexes/timedeltas/test_shift.py From 844cbf13bbf477db11e5aaf427664b7afe047e28 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Dec 2019 10:23:55 -0800 Subject: [PATCH 3/4] De-duplicate and parametrize some arith tests --- pandas/tests/arithmetic/common.py | 89 +++++++ pandas/tests/arithmetic/test_datetime64.py | 50 +--- pandas/tests/arithmetic/test_timedelta64.py | 267 ++++++-------------- 3 files changed, 164 insertions(+), 242 deletions(-) create mode 100644 pandas/tests/arithmetic/common.py diff --git a/pandas/tests/arithmetic/common.py b/pandas/tests/arithmetic/common.py new file mode 100644 index 0000000000000..cec4633b21d4c --- /dev/null +++ b/pandas/tests/arithmetic/common.py @@ -0,0 +1,89 @@ +""" +Assertion helpers for arithmetic tests. +""" +import pytest +import numpy as np + +from pandas import DataFrame, Series, Index +import pandas.util.testing as tm + + +def assert_invalid_addsub_type(left, right, msg=None): + """ + Helper to assert that left and right can be neither added nor subtracted. + + Parameters + --------- + left : object + right : object + msg : str or None, default None + """ + with pytest.raises(TypeError, match=msg): + left + right + with pytest.raises(TypeError, match=msg): + right + left + with pytest.raises(TypeError, match=msg): + left - right + with pytest.raises(TypeError, match=msg): + right - left + + +def get_upcast_box(box, vector): + """ + Given two box-types, find the one that takes priority + """ + if box is DataFrame or isinstance(vector, DataFrame): + return DataFrame + if box is Series or isinstance(vector, Series): + return Series + if box is Index or isinstance(vector, Index): + return Index + return box + + +def assert_invalid_comparison(left, right, box): + """ + Assert that comparison operations with mismatched types behave correctly. + + Parameters + ---------- + left : np.ndarray, ExtensionArray, Index, or Series + right : object + box : {pd.DataFrame, pd.Series, pd.Index, tm.to_array} + """ + # Not for tznaive-tzaware comparison + + # Note: not quite the same as how we do this for tm.box_expected + xbox = box if box is not Index else np.array + + result = left == right + expected = xbox(np.zeros(result.shape, dtype=np.bool_)) + + tm.assert_equal(result, expected) + + result = right == left + tm.assert_equal(result, expected) + + result = left != right + tm.assert_equal(result, ~expected) + + result = right != left + tm.assert_equal(result, ~expected) + + msg = "Invalid comparison between" + with pytest.raises(TypeError, match=msg): + left < right + with pytest.raises(TypeError, match=msg): + left <= right + with pytest.raises(TypeError, match=msg): + left > right + with pytest.raises(TypeError, match=msg): + left >= right + with pytest.raises(TypeError, match=msg): + right < left + with pytest.raises(TypeError, match=msg): + right <= left + with pytest.raises(TypeError, match=msg): + right > left + with pytest.raises(TypeError, match=msg): + right >= left diff --git a/pandas/tests/arithmetic/test_datetime64.py b/pandas/tests/arithmetic/test_datetime64.py index b77c9a2bddcfa..ee22d9e5a1576 100644 --- a/pandas/tests/arithmetic/test_datetime64.py +++ b/pandas/tests/arithmetic/test_datetime64.py @@ -31,54 +31,7 @@ from pandas.core.ops import roperator import pandas.util.testing as tm - -def assert_invalid_comparison(left, right, box): - """ - Assert that comparison operations with mismatched types behave correctly. - - Parameters - ---------- - left : np.ndarray, ExtensionArray, Index, or Series - right : object - box : {pd.DataFrame, pd.Series, pd.Index, tm.to_array} - """ - # Not for tznaive-tzaware comparison - - # Note: not quite the same as how we do this for tm.box_expected - xbox = box if box is not pd.Index else np.array - - result = left == right - expected = xbox(np.zeros(result.shape, dtype=np.bool_)) - - tm.assert_equal(result, expected) - - result = right == left - tm.assert_equal(result, expected) - - result = left != right - tm.assert_equal(result, ~expected) - - result = right != left - tm.assert_equal(result, ~expected) - - msg = "Invalid comparison between" - with pytest.raises(TypeError, match=msg): - left < right - with pytest.raises(TypeError, match=msg): - left <= right - with pytest.raises(TypeError, match=msg): - left > right - with pytest.raises(TypeError, match=msg): - left >= right - with pytest.raises(TypeError, match=msg): - right < left - with pytest.raises(TypeError, match=msg): - right <= left - with pytest.raises(TypeError, match=msg): - right > left - with pytest.raises(TypeError, match=msg): - right >= left - +from .common import assert_invalid_comparison, get_upcast_box # ------------------------------------------------------------------ # Comparisons @@ -2368,7 +2321,6 @@ def test_dti_addsub_offset_arraylike( # GH#18849, GH#19744 box = pd.Index other_box = index_or_series - from .test_timedelta64 import get_upcast_box tz = tz_naive_fixture dti = pd.date_range("2017-01-01", periods=2, tz=tz, name=names[0]) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 441a5f6facf5f..bef62bd2d0b86 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -18,22 +18,13 @@ Timestamp, timedelta_range, ) -from pandas.tests.arithmetic.test_datetime64 import assert_invalid_comparison import pandas.util.testing as tm - -def get_upcast_box(box, vector): - """ - Given two box-types, find the one that takes priority - """ - if box is DataFrame or isinstance(vector, DataFrame): - return DataFrame - if box is Series or isinstance(vector, Series): - return Series - if box is pd.Index or isinstance(vector, pd.Index): - return pd.Index - return box - +from .common import ( + assert_invalid_addsub_type, + assert_invalid_comparison, + get_upcast_box, +) # ------------------------------------------------------------------ # Timedelta64[ns] dtype Comparisons @@ -611,22 +602,6 @@ def test_tdi_add_overflow(self): class TestTimedeltaArraylikeAddSubOps: # Tests for timedelta64[ns] __add__, __sub__, __radd__, __rsub__ - # TODO: moved from frame tests; needs parametrization/de-duplication - def test_td64_df_add_int_frame(self): - # GH#22696 Check that we don't dispatch to numpy implementation, - # which treats int64 as m8[ns] - tdi = pd.timedelta_range("1", periods=3) - df = tdi.to_frame() - other = pd.DataFrame([1, 2, 3], index=tdi) # indexed like `df` - with pytest.raises(TypeError): - df + other - with pytest.raises(TypeError): - other + df - with pytest.raises(TypeError): - df - other - with pytest.raises(TypeError): - other - df - # TODO: moved from tests.indexes.timedeltas.test_arithmetic; needs # parametrization+de-duplication def test_timedelta_ops_with_missing_values(self): @@ -881,51 +856,6 @@ def test_timedelta64_ops_nat(self): tm.assert_series_equal(timedelta_series / 2.0, Series([NaT, Timedelta("0.5s")])) tm.assert_series_equal(timedelta_series / np.nan, nat_series_dtype_timedelta) - # ------------------------------------------------------------- - # Invalid Operations - - @pytest.mark.parametrize("other", ["a", 3.14, np.array([2.0, 3.0])]) - def test_td64arr_add_sub_invalid(self, box_with_array, other): - # GH#13624 for str - tdi = TimedeltaIndex(["1 day", "2 days"]) - tdarr = tm.box_expected(tdi, box_with_array) - - with pytest.raises(TypeError): - tdarr + other - with pytest.raises(TypeError): - other + tdarr - with pytest.raises(TypeError): - tdarr - other - with pytest.raises(TypeError): - other - tdarr - - @pytest.mark.parametrize("freq", [None, "H"]) - def test_td64arr_sub_period(self, box_with_array, freq): - # GH#13078 - # not supported, check TypeError - p = pd.Period("2011-01-01", freq="D") - idx = TimedeltaIndex(["1 hours", "2 hours"], freq=freq) - idx = tm.box_expected(idx, box_with_array) - - with pytest.raises(TypeError): - idx - p - - with pytest.raises(TypeError): - p - idx - - @pytest.mark.parametrize("pi_freq", ["D", "W", "Q", "H"]) - @pytest.mark.parametrize("tdi_freq", [None, "H"]) - def test_td64arr_sub_pi(self, box_with_array, tdi_freq, pi_freq): - # GH#20049 subtracting PeriodIndex should raise TypeError - tdi = TimedeltaIndex(["1 hours", "2 hours"], freq=tdi_freq) - dti = Timestamp("2018-03-07 17:16:40") + tdi - pi = dti.to_period(pi_freq) - - # TODO: parametrize over box for pi? - tdi = tm.box_expected(tdi, box_with_array) - with pytest.raises(TypeError): - tdi - pi - # ------------------------------------------------------------- # Binary operations td64 arraylike and datetime-like @@ -1032,127 +962,109 @@ def test_td64arr_add_datetime64_nat(self, box_with_array): tm.assert_equal(other + tdser, expected) # ------------------------------------------------------------------ - # Operations with int-like others + # Invalid __add__/__sub__ operations + + # TODO: moved from frame tests; needs parametrization/de-duplication + def test_td64_df_add_int_frame(self): + # GH#22696 Check that we don't dispatch to numpy implementation, + # which treats int64 as m8[ns] + tdi = pd.timedelta_range("1", periods=3) + df = tdi.to_frame() + other = pd.DataFrame([1, 2, 3], index=tdi) # indexed like `df` + assert_invalid_addsub_type(df, other) + + @pytest.mark.parametrize("pi_freq", ["D", "W", "Q", "H"]) + @pytest.mark.parametrize("tdi_freq", [None, "H"]) + def test_td64arr_sub_periodlike(self, box_with_array, tdi_freq, pi_freq): + # GH#20049 subtracting PeriodIndex should raise TypeError + tdi = TimedeltaIndex(["1 hours", "2 hours"], freq=tdi_freq) + dti = Timestamp("2018-03-07 17:16:40") + tdi + pi = dti.to_period(pi_freq) + + # TODO: parametrize over box for pi? + tdi = tm.box_expected(tdi, box_with_array) + with pytest.raises(TypeError): + tdi - pi + + # FIXME: don't leave commented-out + # FIXME: this raises with period scalar but not with PeriodIndex? + # with pytest.raises(TypeError): + # pi - tdi + + # GH#13078 subtraction of Period scalar not supported + with pytest.raises(TypeError): + tdi - pi[0] + with pytest.raises(TypeError): + pi[0] - tdi @pytest.mark.parametrize( "other", [ + # GH#12624 for str case + "a", # GH#19123 1, - Series([20, 30, 40], dtype="uint8"), - np.array([20, 30, 40], dtype="uint8"), - pd.UInt64Index([20, 30, 40]), - pd.Int64Index([20, 30, 40]), - Series([2, 3, 4]), 1.5, np.array(2), ], ) - def test_td64arr_addsub_numeric_invalid(self, box_with_array, other): - box = box_with_array + def test_td64arr_addsub_numeric_scalar_invalid(self, box_with_array, other): + # vector-like others are tested in test_td64arr_add_sub_numeric_arr_invalid tdser = pd.Series(["59 Days", "59 Days", "NaT"], dtype="m8[ns]") - tdser = tm.box_expected(tdser, box) + tdarr = tm.box_expected(tdser, box_with_array) - with pytest.raises(TypeError): - tdser + other - with pytest.raises(TypeError): - other + tdser - with pytest.raises(TypeError): - tdser - other - with pytest.raises(TypeError): - other - tdser + assert_invalid_addsub_type(tdarr, other) - @pytest.mark.parametrize( - "dtype", - [ - "int64", - "int32", - "int16", - "uint64", - "uint32", - "uint16", - "uint8", - "float64", - "float32", - "float16", - ], - ) @pytest.mark.parametrize( "vec", [ np.array([1, 2, 3]), pd.Index([1, 2, 3]), - Series([1, 2, 3]) - # TODO: Add DataFrame in here? + Series([1, 2, 3]), + DataFrame([[1, 2, 3]]), ], ids=lambda x: type(x).__name__, ) - def test_td64arr_add_sub_numeric_arr_invalid(self, box_with_array, vec, dtype): - box = box_with_array + def test_td64arr_addsub_numeric_arr_invalid( + self, box_with_array, vec, any_real_dtype + ): tdser = pd.Series(["59 Days", "59 Days", "NaT"], dtype="m8[ns]") - tdser = tm.box_expected(tdser, box) + tdarr = tm.box_expected(tdser, box_with_array) - vector = vec.astype(dtype) - with pytest.raises(TypeError): - tdser + vector - with pytest.raises(TypeError): - vector + tdser - with pytest.raises(TypeError): - tdser - vector - with pytest.raises(TypeError): - vector - tdser + vector = vec.astype(any_real_dtype) + assert_invalid_addsub_type(tdarr, vector) - # TODO: parameterize over box and de-duplicate - def test_tdi_add_sub_int(self, one): + def test_td64arr_add_sub_int(self, box_with_array, one): # Variants of `one` for #19012, deprecated GH#22535 rng = timedelta_range("1 days 09:00:00", freq="H", periods=10) + tdarr = tm.box_expected(rng, box_with_array) + msg = "Addition/subtraction of integers" + assert_invalid_addsub_type(tdarr, one, msg) + # TOOD: get inplace ops into assert_invalid_addsub_type with pytest.raises(TypeError, match=msg): - rng + one + tdarr += one with pytest.raises(TypeError, match=msg): - rng += one - with pytest.raises(TypeError, match=msg): - rng - one - with pytest.raises(TypeError, match=msg): - rng -= one + tdarr -= one - # TODO: parameterize over box and de-duplicate - @pytest.mark.parametrize("box", [np.array, pd.Index]) - def test_tdi_add_sub_integer_array(self, box): + def test_td64arr_add_sub_integer_array(self, box_with_array): # GH#19959, deprecated GH#22535 rng = timedelta_range("1 days 09:00:00", freq="H", periods=3) - other = box([4, 3, 2]) - msg = "Addition/subtraction of integers and integer-arrays" - - with pytest.raises(TypeError, match=msg): - rng + other - - with pytest.raises(TypeError, match=msg): - other + rng + tdarr = tm.box_expected(rng, box_with_array) + other = tm.box_expected([4, 3, 2], box_with_array) - with pytest.raises(TypeError, match=msg): - rng - other - - with pytest.raises(TypeError, match=msg): - other - rng + msg = "Addition/subtraction of integers and integer-arrays" + assert_invalid_addsub_type(tdarr, other, msg) - # TODO: parameterize over box and de-duplicate - @pytest.mark.parametrize("box", [np.array, pd.Index]) - def test_tdi_addsub_integer_array_no_freq(self, box): + def test_td64arr_addsub_integer_array_no_freq(self, box_with_array): # GH#19959 tdi = TimedeltaIndex(["1 Day", "NaT", "3 Hours"]) - other = box([14, -1, 16]) - msg = "Addition/subtraction of integers" + tdarr = tm.box_expected(tdi, box_with_array) + other = tm.box_expected([14, -1, 16], box_with_array) - with pytest.raises(TypeError, match=msg): - tdi + other - with pytest.raises(TypeError, match=msg): - other + tdi - with pytest.raises(TypeError, match=msg): - tdi - other - with pytest.raises(TypeError, match=msg): - other - tdi + msg = "Addition/subtraction of integers" + assert_invalid_addsub_type(tdarr, other, msg) # ------------------------------------------------------------------ # Operations with timedelta-like others @@ -1983,7 +1895,6 @@ def test_td64arr_mul_td64arr_raises(self, box_with_array): # ------------------------------------------------------------------ # Operations with numeric others - @pytest.mark.parametrize("one", [1, np.array(1), 1.0, np.array(1.0)]) def test_td64arr_mul_numeric_scalar(self, box_with_array, one): # GH#4521 # divide/multiply by integers @@ -2022,33 +1933,18 @@ def test_td64arr_div_numeric_scalar(self, box_with_array, two): with pytest.raises(TypeError, match="Cannot divide"): two / tdser - @pytest.mark.parametrize( - "dtype", - [ - "int64", - "int32", - "int16", - "uint64", - "uint32", - "uint16", - "uint8", - "float64", - "float32", - "float16", - ], - ) @pytest.mark.parametrize( "vector", [np.array([20, 30, 40]), pd.Index([20, 30, 40]), Series([20, 30, 40])], ids=lambda x: type(x).__name__, ) - def test_td64arr_rmul_numeric_array(self, box_with_array, vector, dtype): + def test_td64arr_rmul_numeric_array(self, box_with_array, vector, any_real_dtype): # GH#4521 # divide/multiply by integers xbox = get_upcast_box(box_with_array, vector) tdser = pd.Series(["59 Days", "59 Days", "NaT"], dtype="m8[ns]") - vector = vector.astype(dtype) + vector = vector.astype(any_real_dtype) expected = Series(["1180 Days", "1770 Days", "NaT"], dtype="timedelta64[ns]") @@ -2061,32 +1957,17 @@ def test_td64arr_rmul_numeric_array(self, box_with_array, vector, dtype): result = vector * tdser tm.assert_equal(result, expected) - @pytest.mark.parametrize( - "dtype", - [ - "int64", - "int32", - "int16", - "uint64", - "uint32", - "uint16", - "uint8", - "float64", - "float32", - "float16", - ], - ) @pytest.mark.parametrize( "vector", [np.array([20, 30, 40]), pd.Index([20, 30, 40]), Series([20, 30, 40])], ids=lambda x: type(x).__name__, ) - def test_td64arr_div_numeric_array(self, box_with_array, vector, dtype): + def test_td64arr_div_numeric_array(self, box_with_array, vector, any_real_dtype): # GH#4521 # divide/multiply by integers xbox = get_upcast_box(box_with_array, vector) tdser = pd.Series(["59 Days", "59 Days", "NaT"], dtype="m8[ns]") - vector = vector.astype(dtype) + vector = vector.astype(any_real_dtype) expected = Series(["2.95D", "1D 23H 12m", "NaT"], dtype="timedelta64[ns]") tdser = tm.box_expected(tdser, box_with_array) From 170f3156c828927feff90b14ad84e2b5c8f8accc Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Dec 2019 11:17:37 -0800 Subject: [PATCH 4/4] use assert_invalid_addsub_type --- pandas/tests/arithmetic/test_datetime64.py | 32 ++++----------------- pandas/tests/arithmetic/test_timedelta64.py | 2 ++ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/pandas/tests/arithmetic/test_datetime64.py b/pandas/tests/arithmetic/test_datetime64.py index ee22d9e5a1576..bc9a46b1c97fc 100644 --- a/pandas/tests/arithmetic/test_datetime64.py +++ b/pandas/tests/arithmetic/test_datetime64.py @@ -31,7 +31,7 @@ from pandas.core.ops import roperator import pandas.util.testing as tm -from .common import assert_invalid_comparison, get_upcast_box +from .common import assert_invalid_comparison, get_upcast_box, assert_invalid_addsub_type # ------------------------------------------------------------------ # Comparisons @@ -1901,13 +1901,10 @@ def test_dti_addsub_int(self, tz_naive_fixture, one): with pytest.raises(TypeError, match=msg): rng + one - with pytest.raises(TypeError, match=msg): rng += one - with pytest.raises(TypeError, match=msg): rng - one - with pytest.raises(TypeError, match=msg): rng -= one @@ -1921,13 +1918,8 @@ def test_dti_add_intarray_tick(self, int_holder, freq): dti = pd.date_range("2016-01-01", periods=2, freq=freq) other = int_holder([4, -1]) - msg = "Addition/subtraction of integers" - - with pytest.raises(TypeError, match=msg): - dti + other - - with pytest.raises(TypeError, match=msg): - other + dti + msg = "Addition/subtraction of integers|cannot subtract DatetimeArray from" + assert_invalid_addsub_type(dti, other, msg) @pytest.mark.parametrize("freq", ["W", "M", "MS", "Q"]) @pytest.mark.parametrize("int_holder", [np.array, pd.Index]) @@ -1936,13 +1928,8 @@ def test_dti_add_intarray_non_tick(self, int_holder, freq): dti = pd.date_range("2016-01-01", periods=2, freq=freq) other = int_holder([4, -1]) - msg = "Addition/subtraction of integers" - - with pytest.raises(TypeError, match=msg): - dti + other - - with pytest.raises(TypeError, match=msg): - other + dti + msg = "Addition/subtraction of integers|cannot subtract DatetimeArray from" + assert_invalid_addsub_type(dti, other, msg) @pytest.mark.parametrize("int_holder", [np.array, pd.Index]) def test_dti_add_intarray_no_freq(self, int_holder): @@ -1951,14 +1938,7 @@ def test_dti_add_intarray_no_freq(self, int_holder): other = int_holder([9, 4, -1]) tmsg = "cannot subtract DatetimeArray from" msg = "Addition/subtraction of integers" - with pytest.raises(TypeError, match=msg): - dti + other - with pytest.raises(TypeError, match=msg): - other + dti - with pytest.raises(TypeError, match=msg): - dti - other - with pytest.raises(TypeError, match=tmsg): - other - dti + assert_invalid_addsub_type(dti, other, msg+"|"+tmsg) # ------------------------------------------------------------- # Binary operations DatetimeIndex and TimedeltaIndex/array diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index bef62bd2d0b86..4fd8c25a830f2 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -1966,8 +1966,10 @@ def test_td64arr_div_numeric_array(self, box_with_array, vector, any_real_dtype) # GH#4521 # divide/multiply by integers xbox = get_upcast_box(box_with_array, vector) + tdser = pd.Series(["59 Days", "59 Days", "NaT"], dtype="m8[ns]") vector = vector.astype(any_real_dtype) + expected = Series(["2.95D", "1D 23H 12m", "NaT"], dtype="timedelta64[ns]") tdser = tm.box_expected(tdser, box_with_array)