Repository: pandas-dev/pandas

Issue:
DEPR: is_decimal, is_interval
These are aliases for isinstance checks, don't seem necessary.



Discussion:
Hey, I'm a new contributor to pandas, and this seems to be a pretty simple issue to take on. I'll wait for the core team discussion to start working on it but for now I'll take it if that's ok.
take
So I've been trying to figure this issue out today but I've been having a hard time. Hasn't this deprecation already been done? is_interval already has a warning saying it has been deprecated since version 2.0.0, and is_decimal isn't being defined in the file is_interval is (pandas\core\indexes\base.py). I'm still new here, so am I missing something?

Patch:
diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst
index 98926712ac7ce..7c1d0fb81a530 100644
--- a/doc/source/whatsnew/v2.2.0.rst
+++ b/doc/source/whatsnew/v2.2.0.rst
@@ -262,6 +262,7 @@ For example:
 Other Deprecations
 ^^^^^^^^^^^^^^^^^^
 - Changed :meth:`Timedelta.resolution_string` to return ``h``, ``min``, ``s``, ``ms``, ``us``, and ``ns`` instead of ``H``, ``T``, ``S``, ``L``, ``U``, and ``N``, for compatibility with respective deprecations in frequency aliases (:issue:`52536`)
+- Deprecated :func:`pandas.api.types.is_interval` and :func:`pandas.api.types.is_period`, use ``isinstance(obj, pd.Interval)`` and ``isinstance(obj, pd.Period)`` instead (:issue:`55264`)
 - Deprecated :func:`read_gbq` and :meth:`DataFrame.to_gbq`. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`)
 - Deprecated :meth:`.DataFrameGroupBy.fillna` and :meth:`.SeriesGroupBy.fillna`; use :meth:`.DataFrameGroupBy.ffill`, :meth:`.DataFrameGroupBy.bfill` for forward and backward filling or :meth:`.DataFrame.fillna` to fill with a single value (or the Series equivalents) (:issue:`55718`)
 - Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`)
diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx
index 2f1b24d9dfc38..b26985abd92af 100644
--- a/pandas/_libs/lib.pyx
+++ b/pandas/_libs/lib.pyx
@@ -65,6 +65,7 @@ from numpy cimport (
 )
 
 cnp.import_array()
+from pandas._libs.interval import Interval
 
 
 cdef extern from "numpy/arrayobject.h":
@@ -245,7 +246,7 @@ def is_scalar(val: object) -> bool:
     # Note: PyNumber_Check check includes Decimal, Fraction, numbers.Number
     return (PyNumber_Check(val)
             or is_period_object(val)
-            or is_interval(val)
+            or isinstance(val, Interval)
             or is_offset_object(val))
 
 
@@ -1178,6 +1179,17 @@ cpdef bint is_decimal(object obj):
 
 
 cpdef bint is_interval(object obj):
+    import warnings
+
+    from pandas.util._exceptions import find_stack_level
+
+    warnings.warn(
+        # GH#55264
+        "is_interval is deprecated and will be removed in a future version. "
+        "Use isinstance(obj, pd.Interval) instead.",
+        FutureWarning,
+        stacklevel=find_stack_level(),
+    )
     return getattr(obj, "_typ", "_typ") == "interval"
 
 
@@ -1189,6 +1201,17 @@ def is_period(val: object) -> bool:
     -------
     bool
     """
+    import warnings
+
+    from pandas.util._exceptions import find_stack_level
+
+    warnings.warn(
+        # GH#55264
+        "is_period is deprecated and will be removed in a future version. "
+        "Use isinstance(obj, pd.Period) instead.",
+        FutureWarning,
+        stacklevel=find_stack_level(),
+    )
     return is_period_object(val)
 
 
@@ -1711,7 +1734,7 @@ def infer_dtype(value: object, skipna: bool = True) -> str:
         if is_period_array(values, skipna=skipna):
             return "period"
 
-    elif is_interval(val):
+    elif isinstance(val, Interval):
         if is_interval_array(values):
             return "interval"
 
@@ -2186,7 +2209,7 @@ cpdef bint is_interval_array(ndarray values):
     for i in range(n):
         val = values[i]
 
-        if is_interval(val):
+        if isinstance(val, Interval):
             if closed is None:
                 closed = val.closed
                 numeric = (
@@ -2647,7 +2670,7 @@ def maybe_convert_objects(ndarray[object] objects,
             except (ValueError, TypeError):
                 seen.object_ = True
                 break
-        elif is_interval(val):
+        elif isinstance(val, Interval):
             if convert_non_numeric:
                 seen.interval_ = True
                 break
diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py
index 3cac25600bd0e..0ad652bd5aa64 100644
--- a/pandas/core/dtypes/cast.py
+++ b/pandas/core/dtypes/cast.py
@@ -20,7 +20,11 @@
 
 from pandas._config import using_pyarrow_string_dtype
 
-from pandas._libs import lib
+from pandas._libs import (
+    Interval,
+    Period,
+    lib,
+)
 from pandas._libs.missing import (
     NA,
     NAType,
@@ -850,9 +854,9 @@ def infer_dtype_from_scalar(val) -> tuple[DtypeObj, Any]:
     elif is_complex(val):
         dtype = np.dtype(np.complex128)
 
-    if lib.is_period(val):
+    if isinstance(val, Period):
         dtype = PeriodDtype(freq=val.freq)
-    elif lib.is_interval(val):
+    elif isinstance(val, Interval):
         subtype = infer_dtype_from_scalar(val.left)[0]
         dtype = IntervalDtype(subtype=subtype, closed=val.closed)
 
diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py
index f73e2b5512262..0982b376a27d5 100644
--- a/pandas/core/indexes/interval.py
+++ b/pandas/core/indexes/interval.py
@@ -22,6 +22,7 @@
 )
 from pandas._libs.tslibs import (
     BaseOffset,
+    Period,
     Timedelta,
     Timestamp,
     to_offset,
@@ -561,7 +562,7 @@ def _maybe_convert_i8(self, key):
         if scalar:
             # Timestamp/Timedelta
             key_dtype, key_i8 = infer_dtype_from_scalar(key)
-            if lib.is_period(key):
+            if isinstance(key, Period):
                 key_i8 = key.ordinal
             elif isinstance(key_i8, Timestamp):
                 key_i8 = key_i8._value


Test patch:
diff --git a/pandas/tests/dtypes/test_inference.py b/pandas/tests/dtypes/test_inference.py
index df7c787d2b9bf..32c8def669c21 100644
--- a/pandas/tests/dtypes/test_inference.py
+++ b/pandas/tests/dtypes/test_inference.py
@@ -1622,11 +1622,23 @@ def test_to_object_array_width(self):
         tm.assert_numpy_array_equal(out, expected)
 
     def test_is_period(self):
-        assert lib.is_period(Period("2011-01", freq="M"))
-        assert not lib.is_period(PeriodIndex(["2011-01"], freq="M"))
-        assert not lib.is_period(Timestamp("2011-01"))
-        assert not lib.is_period(1)
-        assert not lib.is_period(np.nan)
+        # GH#55264
+        msg = "is_period is deprecated and will be removed in a future version"
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            assert lib.is_period(Period("2011-01", freq="M"))
+            assert not lib.is_period(PeriodIndex(["2011-01"], freq="M"))
+            assert not lib.is_period(Timestamp("2011-01"))
+            assert not lib.is_period(1)
+            assert not lib.is_period(np.nan)
+
+    def test_is_interval(self):
+        # GH#55264
+        msg = "is_interval is deprecated and will be removed in a future version"
+        item = Interval(1, 2)
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            assert lib.is_interval(item)
+            assert not lib.is_interval(pd.IntervalIndex([item]))
+            assert not lib.is_interval(pd.IntervalIndex([item])._engine)
 
     def test_categorical(self):
         # GH 8974