diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 5c1fabd67bc8d..346258fe5162b 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -115,7 +115,7 @@ ) if TYPE_CHECKING: - from pandas import IntervalIndex, MultiIndex, RangeIndex, Series + from pandas import CategoricalIndex, IntervalIndex, MultiIndex, RangeIndex, Series from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin @@ -405,6 +405,7 @@ def _ensure_array(cls, data, dtype, copy: bool): data = data.copy() return data + @final @classmethod def _dtype_to_subclass(cls, dtype: DtypeObj): # Delay import for perf. https://github.com/pandas-dev/pandas/pull/31423 @@ -1013,8 +1014,8 @@ def _format_data(self, name=None) -> str_t: if self.inferred_type == "string": is_justify = False elif self.inferred_type == "categorical": - # error: "Index" has no attribute "categories" - if is_object_dtype(self.categories): # type: ignore[attr-defined] + self = cast("CategoricalIndex", self) + if is_object_dtype(self.categories): is_justify = False return format_object_summary( @@ -1075,6 +1076,7 @@ def _format_with_header( result = trim_front(format_array(values, None, justify="left")) return header + result + @final def to_native_types(self, slicer=None, **kwargs): """ Format specified values of `self` and return them. diff --git a/pandas/tests/arrays/sparse/test_arithmetics.py b/pandas/tests/arrays/sparse/test_arithmetics.py index 86fbcb337b30e..6cc730ce49840 100644 --- a/pandas/tests/arrays/sparse/test_arithmetics.py +++ b/pandas/tests/arrays/sparse/test_arithmetics.py @@ -357,7 +357,7 @@ def test_mixed_array_float_int(self, kind, mix, all_arithmetic_functions, reques if not np_version_under1p20: if op in [operator.floordiv, ops.rfloordiv] and mix: - mark = pytest.mark.xfail(strict=True, reason="GH#38172") + mark = pytest.mark.xfail(reason="GH#38172") request.node.add_marker(mark) rdtype = "int64" diff --git a/pandas/tests/base/test_conversion.py b/pandas/tests/base/test_conversion.py index 94330f861eacd..67e519553517f 100644 --- a/pandas/tests/base/test_conversion.py +++ b/pandas/tests/base/test_conversion.py @@ -197,13 +197,13 @@ def test_iter_box(self): pd.DatetimeIndex(["2017", "2018"]), np.ndarray, "datetime64[ns]", - marks=[pytest.mark.xfail(reason="datetime _values", strict=True)], + marks=[pytest.mark.xfail(reason="datetime _values")], ), pytest.param( pd.TimedeltaIndex([10 ** 10]), np.ndarray, "m8[ns]", - marks=[pytest.mark.xfail(reason="timedelta _values", strict=True)], + marks=[pytest.mark.xfail(reason="timedelta _values")], ), ], ) diff --git a/pandas/tests/extension/test_boolean.py b/pandas/tests/extension/test_boolean.py index 1db18fb72bdeb..3ef3beaa9c1b1 100644 --- a/pandas/tests/extension/test_boolean.py +++ b/pandas/tests/extension/test_boolean.py @@ -106,16 +106,16 @@ def check_opname(self, s, op_name, other, exc=None): # overwriting to indicate ops don't raise an error super().check_opname(s, op_name, other, exc=None) - def _check_op(self, s, op, other, op_name, exc=NotImplementedError): + def _check_op(self, obj, op, other, op_name, exc=NotImplementedError): if exc is None: if op_name in self.implements: msg = r"numpy boolean subtract" with pytest.raises(TypeError, match=msg): - op(s, other) + op(obj, other) return - result = op(s, other) - expected = s.combine(other, op) + result = op(obj, other) + expected = self._combine(obj, other, op) if op_name in ( "__floordiv__", @@ -130,27 +130,20 @@ def _check_op(self, s, op, other, op_name, exc=NotImplementedError): elif op_name in ("__truediv__", "__rtruediv__"): # combine with bools does not generate the correct result # (numpy behaviour for div is to regard the bools as numeric) - expected = s.astype(float).combine(other, op).astype("Float64") + expected = self._combine(obj.astype(float), other, op) + expected = expected.astype("Float64") if op_name == "__rpow__": # for rpow, combine does not propagate NaN expected[result.isna()] = np.nan - self.assert_series_equal(result, expected) + self.assert_equal(result, expected) else: with pytest.raises(exc): - op(s, other) + op(obj, other) def _check_divmod_op(self, s, op, other, exc=None): # override to not raise an error super()._check_divmod_op(s, op, other, None) - def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): - # frame & scalar - op_name = all_arithmetic_operators - if op_name not in self.implements: - mark = pytest.mark.xfail(reason="_reduce needs implementation") - request.node.add_marker(mark) - super().test_arith_frame_with_scalar(data, all_arithmetic_operators) - class TestComparisonOps(base.BaseComparisonOpsTests): def check_opname(self, s, op_name, other, exc=None): diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index 870099a9fcb4c..766910618d925 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -450,7 +450,7 @@ def _compare_other(self, s, data, op_name, other): class TestPrinting(BaseSparseTests, base.BasePrintingTests): - @pytest.mark.xfail(reason="Different repr", strict=True) + @pytest.mark.xfail(reason="Different repr") def test_array_repr(self, data, size): super().test_array_repr(data, size) diff --git a/pandas/tests/frame/indexing/test_getitem.py b/pandas/tests/frame/indexing/test_getitem.py index 6c6b4e002644c..4282db6933371 100644 --- a/pandas/tests/frame/indexing/test_getitem.py +++ b/pandas/tests/frame/indexing/test_getitem.py @@ -6,6 +6,7 @@ CategoricalDtype, CategoricalIndex, DataFrame, + Index, MultiIndex, Series, Timestamp, @@ -174,3 +175,24 @@ def test_getitem_bool_mask_categorical_index(self): df4[df4.index < 2] with pytest.raises(TypeError, match=msg): df4[df4.index > 1] + + +class TestGetitemSlice: + def test_getitem_slice_float64(self, frame_or_series): + values = np.arange(10.0, 50.0, 2) + index = Index(values) + + start, end = values[[5, 15]] + + data = np.random.randn(20, 3) + if frame_or_series is not DataFrame: + data = data[:, 0] + + obj = frame_or_series(data, index=index) + + result = obj[start:end] + expected = obj.iloc[5:16] + tm.assert_equal(result, expected) + + result = obj.loc[start:end] + tm.assert_equal(result, expected) diff --git a/pandas/tests/frame/methods/test_replace.py b/pandas/tests/frame/methods/test_replace.py index 1b570028964df..febd113f309ae 100644 --- a/pandas/tests/frame/methods/test_replace.py +++ b/pandas/tests/frame/methods/test_replace.py @@ -1587,7 +1587,6 @@ def test_replace_value_category_type(self): @pytest.mark.xfail( reason="category dtype gets changed to object type after replace, see #35268", - strict=True, ) def test_replace_dict_category_type(self, input_category_df, expected_category_df): """ diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index 686f383deab37..e9ae7bb056041 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -60,16 +60,22 @@ def test_getitem_ndarray_3d(self, index, frame_or_series, indexer_sli): idxr = indexer_sli(obj) nd3 = np.random.randint(5, size=(2, 2, 2)) - msg = "|".join( - [ - r"Buffer has wrong number of dimensions \(expected 1, got 3\)", - "Cannot index with multidimensional key", - r"Wrong number of dimensions. values.ndim != ndim \[3 != 1\]", - "Index data must be 1-dimensional", - "positional indexers are out-of-bounds", - "Indexing a MultiIndex with a multidimensional key is not implemented", - ] - ) + msgs = [] + if frame_or_series is Series and indexer_sli in [tm.setitem, tm.iloc]: + msgs.append(r"Wrong number of dimensions. values.ndim != ndim \[3 != 1\]") + if frame_or_series is Series or indexer_sli is tm.iloc: + msgs.append(r"Buffer has wrong number of dimensions \(expected 1, got 3\)") + if indexer_sli is tm.loc or ( + frame_or_series is Series and indexer_sli is tm.setitem + ): + msgs.append("Cannot index with multidimensional key") + if frame_or_series is DataFrame and indexer_sli is tm.setitem: + msgs.append("Index data must be 1-dimensional") + if isinstance(index, pd.IntervalIndex) and indexer_sli is tm.iloc: + msgs.append("Index data must be 1-dimensional") + if len(index) == 0 or isinstance(index, pd.MultiIndex): + msgs.append("positional indexers are out-of-bounds") + msg = "|".join(msgs) potential_errors = (IndexError, ValueError, NotImplementedError) with pytest.raises(potential_errors, match=msg): diff --git a/pandas/tests/series/indexing/test_getitem.py b/pandas/tests/series/indexing/test_getitem.py index a7a60f37bcd00..5a5e285bf719f 100644 --- a/pandas/tests/series/indexing/test_getitem.py +++ b/pandas/tests/series/indexing/test_getitem.py @@ -222,6 +222,24 @@ def test_getitem_slice_float_raises(self, datetime_series): with pytest.raises(TypeError, match=msg.format(key=r"4\.5")): datetime_series[4.5:10.0] + def test_getitem_slice_bug(self): + ser = Series(range(10), index=list(range(10))) + result = ser[-12:] + tm.assert_series_equal(result, ser) + + result = ser[-7:] + tm.assert_series_equal(result, ser[3:]) + + result = ser[:-12] + tm.assert_series_equal(result, ser[:0]) + + def test_getitem_slice_integers(self): + ser = Series(np.random.randn(8), index=[2, 4, 6, 8, 10, 12, 14, 16]) + + result = ser[:4] + expected = Series(ser.values[:4], index=[2, 4, 6, 8]) + tm.assert_series_equal(result, expected) + class TestSeriesGetitemListLike: @pytest.mark.parametrize("box", [list, np.array, Index, pd.Series]) diff --git a/pandas/tests/series/indexing/test_numeric.py b/pandas/tests/series/indexing/test_numeric.py deleted file mode 100644 index 10b9360802c1c..0000000000000 --- a/pandas/tests/series/indexing/test_numeric.py +++ /dev/null @@ -1,55 +0,0 @@ -import numpy as np - -from pandas import DataFrame, Index, Series -import pandas._testing as tm - - -def test_slice_float64(frame_or_series): - values = np.arange(10.0, 50.0, 2) - index = Index(values) - - start, end = values[[5, 15]] - - data = np.random.randn(20, 3) - if frame_or_series is not DataFrame: - data = data[:, 0] - - obj = frame_or_series(data, index=index) - - result = obj[start:end] - expected = obj.iloc[5:16] - tm.assert_equal(result, expected) - - result = obj.loc[start:end] - tm.assert_equal(result, expected) - - -def test_getitem_setitem_slice_bug(): - s = Series(range(10), index=list(range(10))) - result = s[-12:] - tm.assert_series_equal(result, s) - - result = s[-7:] - tm.assert_series_equal(result, s[3:]) - - result = s[:-12] - tm.assert_series_equal(result, s[:0]) - - s = Series(range(10), index=list(range(10))) - s[-12:] = 0 - assert (s == 0).all() - - s[:-12] = 5 - assert (s == 0).all() - - -def test_getitem_setitem_slice_integers(): - s = Series(np.random.randn(8), index=[2, 4, 6, 8, 10, 12, 14, 16]) - - result = s[:4] - expected = s.reindex([2, 4, 6, 8]) - tm.assert_series_equal(result, expected) - - s[:4] = 0 - assert (s[:4] == 0).all() - assert not (s[4:] == 0).any() diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index 3a993f544b64a..3023baca6ff5d 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -113,6 +113,21 @@ def test_setitem_slice_float_raises(self, datetime_series): with pytest.raises(TypeError, match=msg.format(key=r"4\.5")): datetime_series[4.5:10.0] = 0 + def test_setitem_slice(self): + ser = Series(range(10), index=list(range(10))) + ser[-12:] = 0 + assert (ser == 0).all() + + ser[:-12] = 5 + assert (ser == 0).all() + + def test_setitem_slice_integers(self): + ser = Series(np.random.randn(8), index=[2, 4, 6, 8, 10, 12, 14, 16]) + + ser[:4] = 0 + assert (ser[:4] == 0).all() + assert not (ser[4:] == 0).any() + class TestSetitemBooleanMask: def test_setitem_boolean(self, string_series): diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index 4dd91b942474a..c09df52fb5df5 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -174,6 +174,6 @@ def test_attrs(self): @skip_if_no("jinja2") def test_inspect_getmembers(self): # GH38782 - ser = Series() + ser = Series(dtype=object) with tm.assert_produces_warning(None): inspect.getmembers(ser) diff --git a/pandas/tests/series/test_logical_ops.py b/pandas/tests/series/test_logical_ops.py index 7cfda2464f21a..23aa11bc9358a 100644 --- a/pandas/tests/series/test_logical_ops.py +++ b/pandas/tests/series/test_logical_ops.py @@ -286,7 +286,6 @@ def test_reversed_xor_with_index_returns_index(self): marks=pytest.mark.xfail( reason="GH#22092 Index __and__ returns Index intersection", raises=AssertionError, - strict=True, ), ), pytest.param( @@ -294,7 +293,6 @@ def test_reversed_xor_with_index_returns_index(self): marks=pytest.mark.xfail( reason="GH#22092 Index __or__ returns Index union", raises=AssertionError, - strict=True, ), ), ],