diff --git a/doc/source/reference/testing.rst b/doc/source/reference/testing.rst index 9d9fb91821ab1..2c419e8df9517 100644 --- a/doc/source/reference/testing.rst +++ b/doc/source/reference/testing.rst @@ -30,6 +30,7 @@ Exceptions and warnings errors.DtypeWarning errors.DuplicateLabelError errors.EmptyDataError + errors.IndexingError errors.InvalidIndexError errors.IntCastingNaNError errors.MergeError diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 681139fb51272..3a6f6f480837f 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -174,7 +174,7 @@ Other enhancements - A :class:`errors.PerformanceWarning` is now thrown when using ``string[pyarrow]`` dtype with methods that don't dispatch to ``pyarrow.compute`` methods (:issue:`42613`) - Added ``numeric_only`` argument to :meth:`Resampler.sum`, :meth:`Resampler.prod`, :meth:`Resampler.min`, :meth:`Resampler.max`, :meth:`Resampler.first`, and :meth:`Resampler.last` (:issue:`46442`) - ``times`` argument in :class:`.ExponentialMovingWindow` now accepts ``np.timedelta64`` (:issue:`47003`) -- :class:`DataError`, :class:`SpecificationError`, :class:`SettingWithCopyError`, :class:`SettingWithCopyWarning`, :class:`NumExprClobberingError`, :class:`UndefinedVariableError` are now exposed in ``pandas.errors`` (:issue:`27656`) +- :class:`DataError`, :class:`SpecificationError`, :class:`SettingWithCopyError`, :class:`SettingWithCopyWarning`, :class:`NumExprClobberingError`, :class:`UndefinedVariableError`, and :class:`IndexingError` are now exposed in ``pandas.errors`` (:issue:`27656`) - Added ``check_like`` argument to :func:`testing.assert_series_equal` (:issue:`47247`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 20ac0fedc28d1..5a97e1d5a04ea 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -16,6 +16,7 @@ from pandas._libs.lib import item_from_zerodim from pandas.errors import ( AbstractMethodError, + IndexingError, InvalidIndexError, ) from pandas.util._decorators import doc @@ -121,10 +122,6 @@ def __getitem__(self, arg): IndexSlice = _IndexSlice() -class IndexingError(Exception): - pass - - class IndexingMixin: """ Mixin for adding .loc/.iloc/.at/.iat to Dataframes and Series. diff --git a/pandas/errors/__init__.py b/pandas/errors/__init__.py index e30e5019c3568..b8d9df16311d7 100644 --- a/pandas/errors/__init__.py +++ b/pandas/errors/__init__.py @@ -353,3 +353,24 @@ def __init__(self, name: str, is_local: bool | None = None) -> None: else: msg = f"name {base_msg}" super().__init__(msg) + + +class IndexingError(Exception): + """ + Exception is raised when trying to index and there is a mismatch in dimensions. + + Examples + -------- + >>> df = pd.DataFrame({'A': [1, 1, 1]}) + >>> df.loc[..., ..., 'A'] # doctest: +SKIP + ... # IndexingError: indexer may only contain one '...' entry + >>> df = pd.DataFrame({'A': [1, 1, 1]}) + >>> df.loc[1, ..., ...] # doctest: +SKIP + ... # IndexingError: Too many indexers + >>> df[pd.Series([True], dtype=bool)] # doctest: +SKIP + ... # IndexingError: Unalignable boolean Series provided as indexer... + >>> s = pd.Series(range(2), + ... index = pd.MultiIndex.from_product([["a", "b"], ["c"]])) + >>> s.loc["a", "c", "d"] # doctest: +SKIP + ... # IndexingError: Too many indexers + """ diff --git a/pandas/tests/frame/test_query_eval.py b/pandas/tests/frame/test_query_eval.py index 3d703b54ca301..35335c54cd41e 100644 --- a/pandas/tests/frame/test_query_eval.py +++ b/pandas/tests/frame/test_query_eval.py @@ -3,6 +3,7 @@ import numpy as np import pytest +from pandas.errors import UndefinedVariableError import pandas.util._test_decorators as td import pandas as pd @@ -495,8 +496,6 @@ def test_query_syntax_error(self): df.query("i - +", engine=engine, parser=parser) def test_query_scope(self): - from pandas.errors import UndefinedVariableError - engine, parser = self.engine, self.parser skip_if_no_pandas_parser(parser) @@ -522,8 +521,6 @@ def test_query_scope(self): df.query("@a > b > c", engine=engine, parser=parser) def test_query_doesnt_pickup_local(self): - from pandas.errors import UndefinedVariableError - engine, parser = self.engine, self.parser n = m = 10 df = DataFrame(np.random.randint(m, size=(n, 3)), columns=list("abc")) @@ -618,8 +615,6 @@ def test_nested_scope(self): tm.assert_frame_equal(result, expected) def test_nested_raises_on_local_self_reference(self): - from pandas.errors import UndefinedVariableError - df = DataFrame(np.random.randn(5, 3)) # can't reference ourself b/c we're a local so @ is necessary @@ -678,8 +673,6 @@ def test_at_inside_string(self): tm.assert_frame_equal(result, expected) def test_query_undefined_local(self): - from pandas.errors import UndefinedVariableError - engine, parser = self.engine, self.parser skip_if_no_pandas_parser(parser) @@ -838,8 +831,6 @@ def test_date_index_query_with_NaT_duplicates(self): df.query("index < 20130101 < dates3", engine=engine, parser=parser) def test_nested_scope(self): - from pandas.errors import UndefinedVariableError - engine = self.engine parser = self.parser # smoke test diff --git a/pandas/tests/indexing/multiindex/test_loc.py b/pandas/tests/indexing/multiindex/test_loc.py index 19dfe20a3a68d..d4354766a203b 100644 --- a/pandas/tests/indexing/multiindex/test_loc.py +++ b/pandas/tests/indexing/multiindex/test_loc.py @@ -1,7 +1,10 @@ import numpy as np import pytest -from pandas.errors import PerformanceWarning +from pandas.errors import ( + IndexingError, + PerformanceWarning, +) import pandas as pd from pandas import ( @@ -11,7 +14,6 @@ Series, ) import pandas._testing as tm -from pandas.core.indexing import IndexingError @pytest.fixture diff --git a/pandas/tests/indexing/test_iloc.py b/pandas/tests/indexing/test_iloc.py index 44cdc320148e1..2a116c992231b 100644 --- a/pandas/tests/indexing/test_iloc.py +++ b/pandas/tests/indexing/test_iloc.py @@ -11,6 +11,7 @@ import pytest from pandas.compat.numpy import is_numpy_min +from pandas.errors import IndexingError import pandas.util._test_decorators as td from pandas import ( @@ -32,7 +33,6 @@ ) import pandas._testing as tm from pandas.api.types import is_scalar -from pandas.core.indexing import IndexingError from pandas.tests.indexing.common import Base # We pass through the error message from numpy diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index dcb06f1cf778d..9d10e487e0cc2 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -7,6 +7,8 @@ import numpy as np import pytest +from pandas.errors import IndexingError + from pandas.core.dtypes.common import ( is_float_dtype, is_integer_dtype, @@ -24,7 +26,6 @@ ) import pandas._testing as tm from pandas.core.api import Float64Index -from pandas.core.indexing import IndexingError from pandas.tests.indexing.common import _mklbl from pandas.tests.indexing.test_floats import gen_obj diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index 9b1cb69cc33ad..01dfeaef1a5a1 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -12,6 +12,7 @@ import numpy as np import pytest +from pandas.errors import IndexingError import pandas.util._test_decorators as td import pandas as pd @@ -36,10 +37,7 @@ import pandas._testing as tm from pandas.api.types import is_scalar from pandas.core.api import Float64Index -from pandas.core.indexing import ( - IndexingError, - _one_ellipsis_message, -) +from pandas.core.indexing import _one_ellipsis_message from pandas.tests.indexing.common import Base diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index e2a5517066ad9..abee8e75e89d9 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -6,6 +6,8 @@ import numpy as np import pytest +from pandas.errors import IndexingError + from pandas.core.dtypes.common import is_list_like from pandas import ( @@ -30,7 +32,6 @@ timedelta_range, ) import pandas._testing as tm -from pandas.core.indexing import IndexingError from pandas.tseries.offsets import BDay diff --git a/pandas/tests/test_errors.py b/pandas/tests/test_errors.py index d4e3fff5c2f86..7e3d5b43f3014 100644 --- a/pandas/tests/test_errors.py +++ b/pandas/tests/test_errors.py @@ -27,6 +27,7 @@ "SettingWithCopyError", "SettingWithCopyWarning", "NumExprClobberingError", + "IndexingError", ], ) def test_exception_importable(exc):