diff --git a/doc/source/whatsnew/v0.25.1.rst b/doc/source/whatsnew/v0.25.1.rst index fb67decb46b64..40fefe7ec43a8 100644 --- a/doc/source/whatsnew/v0.25.1.rst +++ b/doc/source/whatsnew/v0.25.1.rst @@ -78,7 +78,7 @@ Strings Interval ^^^^^^^^ - +- Bug in :class:`IntervalIndex` where `dir(obj)` would raise ``ValueError`` (:issue:`27571`) - - - diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index 928af2de03b5f..47d1e98f214a1 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -925,6 +925,7 @@ _TYPE_MAP = { 'M': 'datetime64', 'timedelta64[ns]': 'timedelta64', 'm': 'timedelta64', + 'interval': 'interval', } # types only exist on certain platform diff --git a/pandas/core/strings.py b/pandas/core/strings.py index 8f06470db60f1..169a3a24c254d 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -1961,8 +1961,11 @@ def _validate(data): values = getattr(data, "values", data) # Series / Index values = getattr(values, "categories", values) # categorical / normal - # missing values obfuscate type inference -> skip - inferred_dtype = lib.infer_dtype(values, skipna=True) + try: + inferred_dtype = lib.infer_dtype(values, skipna=True) + except ValueError: + # GH#27571 mostly occurs with ExtensionArray + inferred_dtype = None if inferred_dtype not in allowed_types: raise AttributeError("Can only use .str accessor with string values!") diff --git a/pandas/tests/dtypes/test_inference.py b/pandas/tests/dtypes/test_inference.py index 0ae4fcc0fef83..0a8707bdac3a0 100644 --- a/pandas/tests/dtypes/test_inference.py +++ b/pandas/tests/dtypes/test_inference.py @@ -1168,6 +1168,17 @@ def test_categorical(self): result = lib.infer_dtype(Series(arr), skipna=True) assert result == "categorical" + def test_interval(self): + idx = pd.IntervalIndex.from_breaks(range(5), closed="both") + inferred = lib.infer_dtype(idx, skipna=False) + assert inferred == "interval" + + inferred = lib.infer_dtype(idx._data, skipna=False) + assert inferred == "interval" + + inferred = lib.infer_dtype(pd.Series(idx), skipna=False) + assert inferred == "interval" + class TestNumberScalar: def test_is_number(self): diff --git a/pandas/tests/indexes/interval/test_interval.py b/pandas/tests/indexes/interval/test_interval.py index c61af1ce70aed..c1a21e6a7f152 100644 --- a/pandas/tests/indexes/interval/test_interval.py +++ b/pandas/tests/indexes/interval/test_interval.py @@ -1095,3 +1095,10 @@ def test_is_all_dates(self): ) year_2017_index = pd.IntervalIndex([year_2017]) assert not year_2017_index.is_all_dates + + +def test_dir(): + # GH#27571 dir(interval_index) should not raise + index = IntervalIndex.from_arrays([0, 1], [1, 2]) + result = dir(index) + assert "str" not in result