From 1346bbeb2b8832abbd0a8010b3a625ecc33d8a10 Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Mon, 30 Jan 2023 17:38:19 +0000 Subject: [PATCH 1/2] DEPR: Remove NumericIndex from pandas/_testing/ --- doc/source/whatsnew/v2.0.0.rst | 1 + pandas/_testing/__init__.py | 11 +++++------ pandas/_testing/asserters.py | 28 ++++++++++++++++++++-------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 491b9703ffed4..2405b759da0db 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -599,6 +599,7 @@ Other API changes - The ``other`` argument in :meth:`DataFrame.mask` and :meth:`Series.mask` now defaults to ``no_default`` instead of ``np.nan`` consistent with :meth:`DataFrame.where` and :meth:`Series.where`. Entries will be filled with the corresponding NULL value (``np.nan`` for numpy dtypes, ``pd.NA`` for extension dtypes). (:issue:`49111`) - Changed behavior of :meth:`Series.quantile` and :meth:`DataFrame.quantile` with :class:`SparseDtype` to retain sparse dtype (:issue:`49583`) - When creating a :class:`Series` with a object-dtype :class:`Index` of datetime objects, pandas no longer silently converts the index to a :class:`DatetimeIndex` (:issue:`39307`, :issue:`23598`) +- :func:`pandas.testing.assert_index_equal` with parameter ``exact="equiv"`` now considers two indexes equal when both are either a :class:`RangeIndex` or :class:`Index` with an ``int64`` dtype. Previously it meant either a :class:`RangeIndex` or a :class:`Int64Index` (:issue:``) - :meth:`Series.unique` with dtype "timedelta64[ns]" or "datetime64[ns]" now returns :class:`TimedeltaArray` or :class:`DatetimeArray` instead of ``numpy.ndarray`` (:issue:`49176`) - :func:`to_datetime` and :class:`DatetimeIndex` now allow sequences containing both ``datetime`` objects and numeric entries, matching :class:`Series` behavior (:issue:`49037`, :issue:`50453`) - :func:`pandas.api.dtypes.is_string_dtype` now only returns ``True`` for array-likes with ``dtype=object`` when the elements are inferred to be strings (:issue:`15585`) diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py index ea192c497ade0..a738220db20da 100644 --- a/pandas/_testing/__init__.py +++ b/pandas/_testing/__init__.py @@ -108,7 +108,6 @@ use_numexpr, with_csv_dialect, ) -from pandas.core.api import NumericIndex from pandas.core.arrays import ( BaseMaskedArray, ExtensionArray, @@ -357,7 +356,7 @@ def makeBoolIndex(k: int = 10, name=None) -> Index: return Index([False, True] + [False] * (k - 2), name=name) -def makeNumericIndex(k: int = 10, *, name=None, dtype: Dtype | None) -> NumericIndex: +def makeNumericIndex(k: int = 10, *, name=None, dtype: Dtype | None) -> Index: dtype = pandas_dtype(dtype) assert isinstance(dtype, np.dtype) @@ -372,17 +371,17 @@ def makeNumericIndex(k: int = 10, *, name=None, dtype: Dtype | None) -> NumericI else: raise NotImplementedError(f"wrong dtype {dtype}") - return NumericIndex(values, dtype=dtype, name=name) + return Index(values, dtype=dtype, name=name) -def makeIntIndex(k: int = 10, *, name=None, dtype: Dtype = "int64") -> NumericIndex: +def makeIntIndex(k: int = 10, *, name=None, dtype: Dtype = "int64") -> Index: dtype = pandas_dtype(dtype) if not is_signed_integer_dtype(dtype): raise TypeError(f"Wrong dtype {dtype}") return makeNumericIndex(k, name=name, dtype=dtype) -def makeUIntIndex(k: int = 10, *, name=None, dtype: Dtype = "uint64") -> NumericIndex: +def makeUIntIndex(k: int = 10, *, name=None, dtype: Dtype = "uint64") -> Index: dtype = pandas_dtype(dtype) if not is_unsigned_integer_dtype(dtype): raise TypeError(f"Wrong dtype {dtype}") @@ -393,7 +392,7 @@ def makeRangeIndex(k: int = 10, name=None, **kwargs) -> RangeIndex: return RangeIndex(0, k, 1, name=name, **kwargs) -def makeFloatIndex(k: int = 10, *, name=None, dtype: Dtype = "float64") -> NumericIndex: +def makeFloatIndex(k: int = 10, *, name=None, dtype: Dtype = "float64") -> Index: dtype = pandas_dtype(dtype) if not is_float_dtype(dtype): raise TypeError(f"Wrong dtype {dtype}") diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index de28342c0d526..3e171b57af3ba 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -75,7 +75,7 @@ def assert_almost_equal( right : object check_dtype : bool or {'equiv'}, default 'equiv' Check dtype if both a and b are the same type. If 'equiv' is passed in, - then `RangeIndex` and `NumericIndex` with int64 dtype are also considered + then `RangeIndex` and `Index` with int64 dtype are also considered equivalent when doing type checking. rtol : float, default 1e-5 Relative tolerance. @@ -197,7 +197,7 @@ def assert_index_equal( exact : bool or {'equiv'}, default 'equiv' Whether to check the Index class, dtype and inferred_type are identical. If 'equiv', then RangeIndex can be substituted for - NumericIndex with an int64 dtype as well. + Index with an int64 dtype as well. check_names : bool, default True Whether to check the names attribute. check_exact : bool, default True @@ -348,8 +348,6 @@ def assert_class_equal( """ Checks classes are equal. """ - from pandas.core.indexes.numeric import NumericIndex - __tracebackhide__ = True def repr_class(x): @@ -359,12 +357,26 @@ def repr_class(x): return type(x).__name__ + def is_class_equiv(idx: Index) -> bool: + """Classes that are a RangeIndex (sub-)instance or exactly an `Index` . + + This only checks class equivalence. There is a separate check that the + dtype is int64. + """ + from pandas.core.indexes.numeric import NumericIndex + + if isinstance(idx, RangeIndex): + return True + elif type(idx) is Index or type(idx) is NumericIndex: + return True + else: + return False + if type(left) == type(right): return if exact == "equiv": - # accept equivalence of NumericIndex (sub-)classes - if isinstance(left, NumericIndex) and isinstance(right, NumericIndex): + if is_class_equiv(left) and is_class_equiv(right): return msg = f"{obj} classes are different" @@ -470,7 +482,7 @@ def assert_categorical_equal( ): exact = "equiv" else: - # We still want to require exact matches for NumericIndex + # We still want to require exact matches for Index exact = True if check_category_order: @@ -511,7 +523,7 @@ def assert_interval_array_equal( exact : bool or {'equiv'}, default 'equiv' Whether to check the Index class, dtype and inferred_type are identical. If 'equiv', then RangeIndex can be substituted for - NumericIndex with an int64 dtype as well. + Index with an int64 dtype as well. obj : str, default 'IntervalArray' Specify object name being compared, internally used to show appropriate assertion message From 8cf83a0494f08d8a0f1d59b4ea408f41d0d29494 Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Wed, 1 Feb 2023 13:41:40 +0000 Subject: [PATCH 2/2] add GH-number --- doc/source/whatsnew/v2.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 2405b759da0db..2f9fa9dd2a334 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -599,7 +599,7 @@ Other API changes - The ``other`` argument in :meth:`DataFrame.mask` and :meth:`Series.mask` now defaults to ``no_default`` instead of ``np.nan`` consistent with :meth:`DataFrame.where` and :meth:`Series.where`. Entries will be filled with the corresponding NULL value (``np.nan`` for numpy dtypes, ``pd.NA`` for extension dtypes). (:issue:`49111`) - Changed behavior of :meth:`Series.quantile` and :meth:`DataFrame.quantile` with :class:`SparseDtype` to retain sparse dtype (:issue:`49583`) - When creating a :class:`Series` with a object-dtype :class:`Index` of datetime objects, pandas no longer silently converts the index to a :class:`DatetimeIndex` (:issue:`39307`, :issue:`23598`) -- :func:`pandas.testing.assert_index_equal` with parameter ``exact="equiv"`` now considers two indexes equal when both are either a :class:`RangeIndex` or :class:`Index` with an ``int64`` dtype. Previously it meant either a :class:`RangeIndex` or a :class:`Int64Index` (:issue:``) +- :func:`pandas.testing.assert_index_equal` with parameter ``exact="equiv"`` now considers two indexes equal when both are either a :class:`RangeIndex` or :class:`Index` with an ``int64`` dtype. Previously it meant either a :class:`RangeIndex` or a :class:`Int64Index` (:issue:`51098`) - :meth:`Series.unique` with dtype "timedelta64[ns]" or "datetime64[ns]" now returns :class:`TimedeltaArray` or :class:`DatetimeArray` instead of ``numpy.ndarray`` (:issue:`49176`) - :func:`to_datetime` and :class:`DatetimeIndex` now allow sequences containing both ``datetime`` objects and numeric entries, matching :class:`Series` behavior (:issue:`49037`, :issue:`50453`) - :func:`pandas.api.dtypes.is_string_dtype` now only returns ``True`` for array-likes with ``dtype=object`` when the elements are inferred to be strings (:issue:`15585`)