diff --git a/pandas/tests/indexing/test_coercion.py b/pandas/tests/indexing/test_coercion.py index 75337cb3f453f..b2ea989f35e8c 100644 --- a/pandas/tests/indexing/test_coercion.py +++ b/pandas/tests/indexing/test_coercion.py @@ -1,6 +1,9 @@ from __future__ import annotations -from datetime import timedelta +from datetime import ( + datetime, + timedelta, +) import itertools import numpy as np @@ -78,182 +81,9 @@ class TestSetitemCoercion(CoercionBase): method = "setitem" - def _assert_setitem_series_conversion( - self, original_series, loc_value, expected_series, expected_dtype - ): - """test series value's coercion triggered by assignment""" - temp = original_series.copy() - temp[1] = loc_value - tm.assert_series_equal(temp, expected_series) - # check dtype explicitly for sure - assert temp.dtype == expected_dtype - - temp = original_series.copy() - temp.loc[1] = loc_value - tm.assert_series_equal(temp, expected_series) - - @pytest.mark.parametrize( - "val,exp_dtype", [(1, object), (1.1, object), (1 + 1j, object), (True, object)] - ) - def test_setitem_series_object(self, val, exp_dtype): - obj = pd.Series(list("abcd")) - assert obj.dtype == object - - exp = pd.Series(["a", val, "c", "d"]) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", - [(1, np.int64), (1.1, np.float64), (1 + 1j, np.complex128), (True, object)], - ) - def test_setitem_series_int64(self, val, exp_dtype): - obj = pd.Series([1, 2, 3, 4]) - assert obj.dtype == np.int64 - - exp = pd.Series([1, val, 3, 4]) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", [(np.int32(1), np.int8), (np.int16(2 ** 9), np.int16)] - ) - def test_setitem_series_int8(self, val, exp_dtype): - obj = pd.Series([1, 2, 3, 4], dtype=np.int8) - assert obj.dtype == np.int8 - - warn = None if exp_dtype is np.int8 else FutureWarning - msg = "Values are too large to be losslessly cast to int8" - with tm.assert_produces_warning(warn, match=msg): - exp = pd.Series([1, val, 3, 4], dtype=np.int8) - - exp = pd.Series([1, val, 3, 4], dtype=exp_dtype) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", - [(1, np.float64), (1.1, np.float64), (1 + 1j, np.complex128), (True, object)], - ) - def test_setitem_series_float64(self, val, exp_dtype): - obj = pd.Series([1.1, 2.2, 3.3, 4.4]) - assert obj.dtype == np.float64 - - exp = pd.Series([1.1, val, 3.3, 4.4]) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", - [ - (1, np.complex128), - (1.1, np.complex128), - (1 + 1j, np.complex128), - (True, object), - ], - ) - def test_setitem_series_complex128(self, val, exp_dtype): - obj = pd.Series([1 + 1j, 2 + 2j, 3 + 3j, 4 + 4j]) - assert obj.dtype == np.complex128 - - exp = pd.Series([1 + 1j, val, 3 + 3j, 4 + 4j]) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", - [ - (1, object), - ("3", object), - (3, object), - (1.1, object), - (1 + 1j, object), - (True, np.bool_), - ], - ) - def test_setitem_series_bool(self, val, exp_dtype): - obj = pd.Series([True, False, True, False]) - assert obj.dtype == np.bool_ - - exp = pd.Series([True, val, True, False], dtype=exp_dtype) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", - [(pd.Timestamp("2012-01-01"), "datetime64[ns]"), (1, object), ("x", object)], - ) - def test_setitem_series_datetime64(self, val, exp_dtype): - obj = pd.Series( - [ - pd.Timestamp("2011-01-01"), - pd.Timestamp("2011-01-02"), - pd.Timestamp("2011-01-03"), - pd.Timestamp("2011-01-04"), - ] - ) - assert obj.dtype == "datetime64[ns]" - - exp = pd.Series( - [ - pd.Timestamp("2011-01-01"), - val, - pd.Timestamp("2011-01-03"), - pd.Timestamp("2011-01-04"), - ] - ) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", - [ - (pd.Timestamp("2012-01-01", tz="US/Eastern"), "datetime64[ns, US/Eastern]"), - (pd.Timestamp("2012-01-01", tz="US/Pacific"), object), - (pd.Timestamp("2012-01-01"), object), - (1, object), - ], - ) - def test_setitem_series_datetime64tz(self, val, exp_dtype): - tz = "US/Eastern" - obj = pd.Series( - [ - pd.Timestamp("2011-01-01", tz=tz), - pd.Timestamp("2011-01-02", tz=tz), - pd.Timestamp("2011-01-03", tz=tz), - pd.Timestamp("2011-01-04", tz=tz), - ] - ) - assert obj.dtype == "datetime64[ns, US/Eastern]" - - exp = pd.Series( - [ - pd.Timestamp("2011-01-01", tz=tz), - val, - # once deprecation is enforced - # val if getattr(val, "tz", None) is None else val.tz_convert(tz), - pd.Timestamp("2011-01-03", tz=tz), - pd.Timestamp("2011-01-04", tz=tz), - ] - ) - warn = None - if getattr(val, "tz", None) is not None and val.tz != obj[0].tz: - warn = FutureWarning - with tm.assert_produces_warning(warn, match="mismatched timezones"): - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) - - @pytest.mark.parametrize( - "val,exp_dtype", - [(pd.Timedelta("12 day"), "timedelta64[ns]"), (1, object), ("x", object)], - ) - def test_setitem_series_timedelta64(self, val, exp_dtype): - obj = pd.Series( - [ - pd.Timedelta("1 day"), - pd.Timedelta("2 day"), - pd.Timedelta("3 day"), - pd.Timedelta("4 day"), - ] - ) - assert obj.dtype == "timedelta64[ns]" - - exp = pd.Series( - [pd.Timedelta("1 day"), val, pd.Timedelta("3 day"), pd.Timedelta("4 day")] - ) - self._assert_setitem_series_conversion(obj, val, exp, exp_dtype) + # disable comprehensiveness tests, as most of these have been moved to + # tests.series.indexing.test_setitem in SetitemCastingEquivalents subclasses. + klasses: list[str] = [] def test_setitem_series_no_coercion_from_values_list(self): # GH35865 - int casted to str when internally calling np.array(ser.values) @@ -556,6 +386,7 @@ def test_insert_index_bool(self): class TestWhereCoercion(CoercionBase): method = "where" + _cond = np.array([True, False, True, False]) def _assert_where_conversion( self, original, cond, values, expected, expected_dtype @@ -566,6 +397,26 @@ def _assert_where_conversion( tm.assert_equal(res, expected) assert res.dtype == expected_dtype + def _construct_exp(self, obj, klass, fill_val, exp_dtype): + if fill_val is True: + values = klass([True, False, True, True]) + elif isinstance(fill_val, (datetime, np.datetime64)): + values = pd.date_range(fill_val, periods=4) + else: + values = klass(x * fill_val for x in [5, 6, 7, 8]) + + exp = klass([obj[0], values[1], obj[2], values[3]], dtype=exp_dtype) + return values, exp + + def _run_test(self, obj, fill_val, klass, exp_dtype): + cond = klass(self._cond) + + exp = klass([obj[0], fill_val, obj[2], fill_val], dtype=exp_dtype) + self._assert_where_conversion(obj, cond, fill_val, exp, exp_dtype) + + values, exp = self._construct_exp(obj, klass, fill_val, exp_dtype) + self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + @pytest.mark.parametrize( "fill_val,exp_dtype", [(1, object), (1.1, object), (1 + 1j, object), (True, object)], @@ -574,23 +425,7 @@ def test_where_object(self, index_or_series, fill_val, exp_dtype): klass = index_or_series obj = klass(list("abcd")) assert obj.dtype == object - cond = klass([True, False, True, False]) - - if fill_val is True and klass is pd.Series: - ret_val = 1 - else: - ret_val = fill_val - - exp = klass(["a", ret_val, "c", ret_val]) - self._assert_where_conversion(obj, cond, fill_val, exp, exp_dtype) - - if fill_val is True: - values = klass([True, False, True, True]) - else: - values = klass(x * fill_val for x in [5, 6, 7, 8]) - - exp = klass(["a", values[1], "c", values[3]]) - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + self._run_test(obj, fill_val, klass, exp_dtype) @pytest.mark.parametrize( "fill_val,exp_dtype", @@ -604,17 +439,7 @@ def test_where_int64(self, index_or_series, fill_val, exp_dtype, request): obj = klass([1, 2, 3, 4]) assert obj.dtype == np.int64 - cond = klass([True, False, True, False]) - - exp = klass([1, fill_val, 3, fill_val]) - self._assert_where_conversion(obj, cond, fill_val, exp, exp_dtype) - - if fill_val is True: - values = klass([True, False, True, True]) - else: - values = klass(x * fill_val for x in [5, 6, 7, 8]) - exp = klass([1, values[1], 3, values[3]]) - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + self._run_test(obj, fill_val, klass, exp_dtype) @pytest.mark.parametrize( "fill_val, exp_dtype", @@ -628,17 +453,7 @@ def test_where_float64(self, index_or_series, fill_val, exp_dtype, request): obj = klass([1.1, 2.2, 3.3, 4.4]) assert obj.dtype == np.float64 - cond = klass([True, False, True, False]) - - exp = klass([1.1, fill_val, 3.3, fill_val]) - self._assert_where_conversion(obj, cond, fill_val, exp, exp_dtype) - - if fill_val is True: - values = klass([True, False, True, True]) - else: - values = klass(x * fill_val for x in [5, 6, 7, 8]) - exp = klass([1.1, values[1], 3.3, values[3]]) - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + self._run_test(obj, fill_val, klass, exp_dtype) @pytest.mark.parametrize( "fill_val,exp_dtype", @@ -650,41 +465,21 @@ def test_where_float64(self, index_or_series, fill_val, exp_dtype, request): ], ) def test_where_series_complex128(self, fill_val, exp_dtype): - klass = pd.Series + klass = pd.Series # TODO: use index_or_series once we have Index[complex] obj = klass([1 + 1j, 2 + 2j, 3 + 3j, 4 + 4j]) assert obj.dtype == np.complex128 - cond = klass([True, False, True, False]) - - exp = klass([1 + 1j, fill_val, 3 + 3j, fill_val]) - self._assert_where_conversion(obj, cond, fill_val, exp, exp_dtype) - - if fill_val is True: - values = klass([True, False, True, True]) - else: - values = klass(x * fill_val for x in [5, 6, 7, 8]) - exp = klass([1 + 1j, values[1], 3 + 3j, values[3]], dtype=exp_dtype) - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + self._run_test(obj, fill_val, klass, exp_dtype) @pytest.mark.parametrize( "fill_val,exp_dtype", [(1, object), (1.1, object), (1 + 1j, object), (True, np.bool_)], ) def test_where_series_bool(self, fill_val, exp_dtype): - klass = pd.Series + klass = pd.Series # TODO: use index_or_series once we have Index[bool] obj = klass([True, False, True, False]) assert obj.dtype == np.bool_ - cond = klass([True, False, True, False]) - - exp = klass([True, fill_val, True, fill_val]) - self._assert_where_conversion(obj, cond, fill_val, exp, exp_dtype) - - if fill_val is True: - values = klass([True, False, True, True]) - else: - values = klass(x * fill_val for x in [5, 6, 7, 8]) - exp = klass([True, values[1], True, values[3]]) - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + self._run_test(obj, fill_val, klass, exp_dtype) @pytest.mark.parametrize( "fill_val,exp_dtype", @@ -695,43 +490,11 @@ def test_where_series_bool(self, fill_val, exp_dtype): ids=["datetime64", "datetime64tz"], ) def test_where_series_datetime64(self, fill_val, exp_dtype): - obj = pd.Series( - [ - pd.Timestamp("2011-01-01"), - pd.Timestamp("2011-01-02"), - pd.Timestamp("2011-01-03"), - pd.Timestamp("2011-01-04"), - ] - ) - assert obj.dtype == "datetime64[ns]" - cond = pd.Series([True, False, True, False]) - - exp = pd.Series( - [pd.Timestamp("2011-01-01"), fill_val, pd.Timestamp("2011-01-03"), fill_val] - ) - self._assert_where_conversion(obj, cond, fill_val, exp, exp_dtype) + klass = pd.Series - values = pd.Series(pd.date_range(fill_val, periods=4)) - if fill_val.tz: - exp = pd.Series( - [ - pd.Timestamp("2011-01-01"), - pd.Timestamp("2012-01-02 00:00", tz="US/Eastern"), - pd.Timestamp("2011-01-03"), - pd.Timestamp("2012-01-04 00:00", tz="US/Eastern"), - ] - ) - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) - - exp = pd.Series( - [ - pd.Timestamp("2011-01-01"), - values[1], - pd.Timestamp("2011-01-03"), - values[3], - ] - ) - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + obj = klass(pd.date_range("2011-01-01", periods=4, freq="D")._with_freq(None)) + assert obj.dtype == "datetime64[ns]" + self._run_test(obj, fill_val, klass, exp_dtype) @pytest.mark.parametrize( "fill_val", @@ -743,63 +506,19 @@ def test_where_series_datetime64(self, fill_val, exp_dtype): ) def test_where_index_datetime(self, fill_val): exp_dtype = "datetime64[ns]" - obj = pd.Index( - [ - pd.Timestamp("2011-01-01"), - pd.Timestamp("2011-01-02"), - pd.Timestamp("2011-01-03"), - pd.Timestamp("2011-01-04"), - ] - ) + klass = pd.Index + obj = klass(pd.date_range("2011-01-01", periods=4, freq="D")._with_freq(None)) assert obj.dtype == "datetime64[ns]" - cond = pd.Index([True, False, True, False]) - - result = obj.where(cond, fill_val) - expected = pd.DatetimeIndex([obj[0], fill_val, obj[2], fill_val]) - tm.assert_index_equal(result, expected) - - values = pd.Index(pd.date_range(fill_val, periods=4)) - exp = pd.Index( - [ - pd.Timestamp("2011-01-01"), - pd.Timestamp("2012-01-02"), - pd.Timestamp("2011-01-03"), - pd.Timestamp("2012-01-04"), - ] - ) - - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + self._run_test(obj, fill_val, klass, exp_dtype) def test_where_index_datetime64tz(self): + klass = pd.Index + fill_val = pd.Timestamp("2012-01-01", tz="US/Eastern") exp_dtype = object - obj = pd.Index( - [ - pd.Timestamp("2011-01-01"), - pd.Timestamp("2011-01-02"), - pd.Timestamp("2011-01-03"), - pd.Timestamp("2011-01-04"), - ] - ) + obj = klass(pd.date_range("2011-01-01", periods=4, freq="D")._with_freq(None)) assert obj.dtype == "datetime64[ns]" - cond = pd.Index([True, False, True, False]) - - res = obj.where(cond, fill_val) - expected = pd.Index([obj[0], fill_val, obj[2], fill_val], dtype=object) - tm.assert_index_equal(res, expected) - - values = pd.Index(pd.date_range(fill_val, periods=4)) - exp = pd.Index( - [ - pd.Timestamp("2011-01-01"), - pd.Timestamp("2012-01-02", tz="US/Eastern"), - pd.Timestamp("2011-01-03"), - pd.Timestamp("2012-01-04", tz="US/Eastern"), - ], - dtype=exp_dtype, - ) - - self._assert_where_conversion(obj, cond, values, exp, exp_dtype) + self._run_test(obj, fill_val, klass, exp_dtype) @pytest.mark.xfail(reason="Test not implemented") def test_where_index_complex128(self): @@ -842,7 +561,7 @@ def test_where_index_period(self): cond = np.array([False, True, False]) - # Passinga valid scalar + # Passing a valid scalar value = pi[-1] + pi.freq * 10 expected = pd.PeriodIndex([value, pi[1], value]) result = pi.where(cond, value) diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index fb07b28c5a54f..911d5174cb941 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -23,6 +23,7 @@ concat, date_range, period_range, + timedelta_range, ) import pandas._testing as tm from pandas.core.indexing import IndexingError @@ -576,11 +577,15 @@ class SetitemCastingEquivalents: """ @pytest.fixture - def is_inplace(self): + def is_inplace(self, obj, expected): """ - Indicate that we are not (yet) checking whether or not setting is inplace. + Whether we expect the setting to be in-place or not. """ - return None + try: + return expected.dtype == obj.dtype + except TypeError: + # older numpys + return False def check_indexer(self, obj, key, expected, val, indexer, is_inplace): orig = obj @@ -689,8 +694,8 @@ def test_series_where(self, obj, key, expected, val, is_inplace): self._check_inplace(is_inplace, orig, arr, obj) def test_index_where(self, obj, key, expected, val, request): - if obj.dtype == bool: - # TODO(GH#45061): Should become unreachable + if obj.dtype == bool or obj.dtype.kind == "c" or expected.dtype.kind == "c": + # TODO(GH#45061): Should become unreachable (at least the bool part) pytest.skip("test not applicable for this dtype") mask = np.zeros(obj.shape, dtype=bool) @@ -700,8 +705,8 @@ def test_index_where(self, obj, key, expected, val, request): tm.assert_index_equal(res, Index(expected)) def test_index_putmask(self, obj, key, expected, val): - if obj.dtype == bool: - # TODO(GH#45061): Should become unreachable + if obj.dtype == bool or obj.dtype.kind == "c" or expected.dtype.kind == "c": + # TODO(GH#45061): Should become unreachable (at least the bool part) pytest.skip("test not applicable for this dtype") mask = np.zeros(obj.shape, dtype=bool) @@ -800,13 +805,6 @@ def expected(self, dtype): def key(self): return 0 - @pytest.fixture - def is_inplace(self): - """ - Indicate we do _not_ expect the setting to be done inplace. - """ - return False - class TestSetitemDT64IntoInt(SetitemCastingEquivalents): # GH#39619 dont cast dt64 to int when doing this setitem @@ -843,10 +841,6 @@ def val(self, scalar, request): return scalar return box([scalar, scalar]) - @pytest.fixture - def is_inplace(self): - return False - class TestSetitemNAPeriodDtype(SetitemCastingEquivalents): # Setting compatible NA values into Series with PeriodDtype @@ -870,10 +864,6 @@ def key(self, request): def val(self, request): return request.param - @pytest.fixture - def is_inplace(self): - return True - class TestSetitemNADatetimeLikeDtype(SetitemCastingEquivalents): # some nat-like values should be cast to datetime64/timedelta64 when @@ -986,11 +976,6 @@ def key(self): def val(self): return None - @pytest.fixture - def is_inplace(self, obj): - # This is specific to the 4 cases currently implemented for this class. - return obj.dtype.kind != "i" - class TestSetitemFloatIntervalWithIntIntervalValues(SetitemCastingEquivalents): # GH#44201 Cast to shared IntervalDtype rather than object @@ -1048,10 +1033,6 @@ def expected(self, any_int_numpy_dtype): exp = Series([2, 3, 2, 3, 4], dtype=dtype) return exp - @pytest.fixture - def inplace(self): - return True - @pytest.mark.parametrize( "val", @@ -1071,13 +1052,9 @@ def key(self): return slice(0, 2) @pytest.fixture - def inplace(self, val): - # NB: this condition is based on currently-harcoded "val" cases - return val[0] == 2 - - @pytest.fixture - def expected(self, val, inplace): - if inplace: + def expected(self, val): + if val[0] == 2: + # NB: this condition is based on currently-harcoded "val" cases dtype = np.int64 else: dtype = np.float64 @@ -1096,10 +1073,6 @@ def obj(self): def key(self): return 1 - @pytest.fixture - def inplace(self): - return False - @pytest.fixture def expected(self): return Series([1, 512, 3], dtype=np.int16) @@ -1128,18 +1101,13 @@ def obj(self): def key(self): return 0 - @pytest.fixture - def inplace(self): - return False - @pytest.fixture def expected(self, val): - if val == 2 ** 62: - return Series([val, 2, 3], dtype="i8") - elif val == 2 ** 33 + 1.1: - return Series([val, 2, 3], dtype="f8") + if val % 1 != 0: + dtype = "f8" else: - return Series([val, 2, 3], dtype="i8") + dtype = "i8" + return Series([val, 2, 3], dtype=dtype) def test_series_where(self, obj, key, expected, val, is_inplace, request): if isinstance(val, float) and val % 1 == 0: @@ -1160,6 +1128,148 @@ def test_mask_key(self, obj, key, expected, val, indexer_sli, request): super().test_mask_key(obj, key, expected, val, indexer_sli) +class CoercionTest(SetitemCastingEquivalents): + # Tests ported from tests.indexing.test_coercion + + @pytest.fixture + def key(self): + return 1 + + @pytest.fixture + def expected(self, obj, key, val, exp_dtype): + vals = list(obj) + vals[key] = val + return Series(vals, dtype=exp_dtype) + + +@pytest.mark.parametrize( + "val,exp_dtype", [(np.int32(1), np.int8), (np.int16(2 ** 9), np.int16)] +) +class TestCoercionInt8(CoercionTest): + # previously test_setitem_series_int8 in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + return Series([1, 2, 3, 4], dtype=np.int8) + + +@pytest.mark.parametrize("val", [1, 1.1, 1 + 1j, True]) +@pytest.mark.parametrize("exp_dtype", [object]) +class TestCoercionObject(CoercionTest): + # previously test_setitem_series_object in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + return Series(["a", "b", "c", "d"], dtype=object) + + +@pytest.mark.parametrize( + "val,exp_dtype", + [(1, np.complex128), (1.1, np.complex128), (1 + 1j, np.complex128), (True, object)], +) +class TestCoercionComplex(CoercionTest): + # previously test_setitem_series_complex128 in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + return Series([1 + 1j, 2 + 2j, 3 + 3j, 4 + 4j]) + + +@pytest.mark.parametrize( + "val,exp_dtype", + [ + (1, object), + ("3", object), + (3, object), + (1.1, object), + (1 + 1j, object), + (True, bool), + ], +) +class TestCoercionBool(CoercionTest): + # previously test_setitem_series_bool in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + return Series([True, False, True, False], dtype=bool) + + +@pytest.mark.parametrize( + "val,exp_dtype", + [(1, np.int64), (1.1, np.float64), (1 + 1j, np.complex128), (True, object)], +) +class TestCoercionInt64(CoercionTest): + # previously test_setitem_series_int64 in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + return Series([1, 2, 3, 4]) + + +@pytest.mark.parametrize( + "val,exp_dtype", + [(1, np.float64), (1.1, np.float64), (1 + 1j, np.complex128), (True, object)], +) +class TestCoercionFloat64(CoercionTest): + # previously test_setitem_series_float64 in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + return Series([1.1, 2.2, 3.3, 4.4]) + + +@pytest.mark.parametrize( + "val,exp_dtype", + [(Timestamp("2012-01-01"), "datetime64[ns]"), (1, object), ("x", object)], +) +class TestCoercionDatetime64(CoercionTest): + # previously test_setitem_series_datetime64 in tests.indexing.test_coercion + + @pytest.fixture + def obj(self): + return Series(date_range("2011-01-01", freq="D", periods=4)) + + +@pytest.mark.parametrize( + "val,exp_dtype", + [ + (Timestamp("2012-01-01", tz="US/Eastern"), "datetime64[ns, US/Eastern]"), + (Timestamp("2012-01-01", tz="US/Pacific"), object), + (Timestamp("2012-01-01"), object), + (1, object), + ], +) +class TestCoercionDatetime64TZ(CoercionTest): + # previously test_setitem_series_datetime64tz in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + tz = "US/Eastern" + return Series(date_range("2011-01-01", freq="D", periods=4, tz=tz)) + + @pytest.fixture(autouse=True) + def assert_warns(self, request): + # check that we issue a FutureWarning about timezone-matching + if request.function.__name__ == "test_slice_key": + key = request.getfixturevalue("key") + if not isinstance(key, slice): + # The test is a no-op, so no warning will be issued + yield + return + + exp_dtype = request.getfixturevalue("exp_dtype") + val = request.getfixturevalue("val") + if exp_dtype == object and isinstance(val, Timestamp) and val.tz is not None: + with tm.assert_produces_warning(FutureWarning, match="mismatched timezone"): + yield + else: + yield + + +@pytest.mark.parametrize( + "val,exp_dtype", + [(Timedelta("12 day"), "timedelta64[ns]"), (1, object), ("x", object)], +) +class TestCoercionTimedelta64(CoercionTest): + # previously test_setitem_series_timedelta64 in tests.indexing.test_coercion + @pytest.fixture + def obj(self): + return Series(timedelta_range("1 day", periods=4)) + + def test_20643(): # closed by GH#45121 orig = Series([0, 1, 2], index=["a", "b", "c"])