Skip to content

Commit 33c52d2

Browse files
dataxerikmroeschke
andauthored
ENH: move SpecificationError to error/__init__.py (#47089)
* ENH: move SpecificationError from core/base.py to error/__init__.py per GH27656 * ENH: fix doc string * Update pandas/errors/__init__.py Co-authored-by: Matthew Roeschke <[email protected]>
1 parent 3e3bb90 commit 33c52d2

File tree

13 files changed

+51
-24
lines changed

13 files changed

+51
-24
lines changed

doc/source/reference/testing.rst

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Exceptions and warnings
4141
errors.ParserError
4242
errors.ParserWarning
4343
errors.PerformanceWarning
44+
errors.SpecificationError
4445
errors.UnsortedIndexError
4546
errors.UnsupportedFunctionCall
4647

doc/source/whatsnew/v1.5.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Other enhancements
151151
- A :class:`errors.PerformanceWarning` is now thrown when using ``string[pyarrow]`` dtype with methods that don't dispatch to ``pyarrow.compute`` methods (:issue:`42613`)
152152
- 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`)
153153
- ``times`` argument in :class:`.ExponentialMovingWindow` now accepts ``np.timedelta64`` (:issue:`47003`)
154-
- :class:`DataError` now exposed in ``pandas.errors`` (:issue:`27656`)
154+
- :class:`DataError` and :class:`SpecificationError` are now exposed in ``pandas.errors`` (:issue:`27656`)
155155

156156
.. ---------------------------------------------------------------------------
157157
.. _whatsnew_150.notable_bug_fixes:

pandas/core/apply.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
Axis,
3434
NDFrameT,
3535
)
36-
from pandas.errors import DataError
36+
from pandas.errors import (
37+
DataError,
38+
SpecificationError,
39+
)
3740
from pandas.util._decorators import cache_readonly
3841
from pandas.util._exceptions import find_stack_level
3942

@@ -51,10 +54,7 @@
5154
)
5255

5356
from pandas.core.algorithms import safe_sort
54-
from pandas.core.base import (
55-
SelectionMixin,
56-
SpecificationError,
57-
)
57+
from pandas.core.base import SelectionMixin
5858
import pandas.core.common as com
5959
from pandas.core.construction import (
6060
create_series_with_explicit_dtype,

pandas/core/base.py

-4
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,6 @@ def __setattr__(self, key: str, value):
176176
object.__setattr__(self, key, value)
177177

178178

179-
class SpecificationError(Exception):
180-
pass
181-
182-
183179
class SelectionMixin(Generic[NDFrameT]):
184180
"""
185181
mixin implementing the selection & aggregation interface on a group-like

pandas/core/groupby/generic.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
Manager2D,
3838
SingleManager,
3939
)
40+
from pandas.errors import SpecificationError
4041
from pandas.util._decorators import (
4142
Appender,
4243
Substitution,
@@ -68,7 +69,6 @@
6869
reconstruct_func,
6970
validate_func_kwargs,
7071
)
71-
from pandas.core.base import SpecificationError
7272
import pandas.core.common as com
7373
from pandas.core.construction import create_series_with_explicit_dtype
7474
from pandas.core.frame import DataFrame

pandas/errors/__init__.py

+23
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,26 @@ class DataError(Exception):
244244
Or, it can be raised when trying to apply a function to a non-numerical
245245
column on a rolling window.
246246
"""
247+
248+
249+
class SpecificationError(Exception):
250+
"""
251+
Exception raised in two scenarios. The first way is calling agg on a
252+
Dataframe or Series using a nested renamer (dict-of-dict).
253+
The second way is calling agg on a Dataframe with duplicated functions
254+
names without assigning column name.
255+
256+
Examples
257+
--------
258+
>>> df = pd.DataFrame({'A': [1, 1, 1, 2, 2],
259+
... 'B': range(5),
260+
... 'C': range(5)})
261+
>>> df.groupby('A').B.agg({'foo': 'count'}) # doctest: +SKIP
262+
... # SpecificationError: nested renamer is not supported
263+
264+
>>> df.groupby('A').agg({'B': {'foo': ['sum', 'max']}}) # doctest: +SKIP
265+
... # SpecificationError: nested renamer is not supported
266+
267+
>>> df.groupby('A').agg(['min', 'min']) # doctest: +SKIP
268+
... # SpecificationError: nested renamer is not supported
269+
"""

pandas/tests/apply/test_invalid_arg.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import numpy as np
1313
import pytest
1414

15+
from pandas.errors import SpecificationError
16+
1517
from pandas import (
1618
Categorical,
1719
DataFrame,
@@ -20,7 +22,6 @@
2022
notna,
2123
)
2224
import pandas._testing as tm
23-
from pandas.core.base import SpecificationError
2425

2526

2627
@pytest.mark.parametrize("result_type", ["foo", 1])

pandas/tests/groupby/aggregate/test_aggregate.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import numpy as np
1010
import pytest
1111

12+
from pandas.errors import SpecificationError
13+
1214
from pandas.core.dtypes.common import is_integer_dtype
1315

1416
import pandas as pd
@@ -21,7 +23,6 @@
2123
to_datetime,
2224
)
2325
import pandas._testing as tm
24-
from pandas.core.base import SpecificationError
2526
from pandas.core.groupby.grouper import Grouping
2627

2728

pandas/tests/groupby/aggregate/test_other.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import numpy as np
99
import pytest
1010

11+
from pandas.errors import SpecificationError
12+
1113
import pandas as pd
1214
from pandas import (
1315
DataFrame,
@@ -19,7 +21,6 @@
1921
period_range,
2022
)
2123
import pandas._testing as tm
22-
from pandas.core.base import SpecificationError
2324

2425
from pandas.io.formats.printing import pprint_thing
2526

pandas/tests/groupby/test_groupby.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
from pandas._libs import lib
88
from pandas.compat import IS64
9-
from pandas.errors import PerformanceWarning
9+
from pandas.errors import (
10+
PerformanceWarning,
11+
SpecificationError,
12+
)
1013

1114
import pandas as pd
1215
from pandas import (
@@ -24,7 +27,6 @@
2427
)
2528
import pandas._testing as tm
2629
from pandas.core.arrays import BooleanArray
27-
from pandas.core.base import SpecificationError
2830
import pandas.core.common as com
2931
from pandas.core.groupby.base import maybe_normalize_deprecated_kernels
3032

pandas/tests/resample/test_resample_api.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -427,15 +427,15 @@ def test_agg():
427427

428428
msg = "nested renamer is not supported"
429429
for t in cases:
430-
with pytest.raises(pd.core.base.SpecificationError, match=msg):
430+
with pytest.raises(pd.errors.SpecificationError, match=msg):
431431
t.aggregate({"A": {"mean": "mean", "sum": "sum"}})
432432

433433
expected = pd.concat([a_mean, a_sum, b_mean, b_sum], axis=1)
434434
expected.columns = pd.MultiIndex.from_tuples(
435435
[("A", "mean"), ("A", "sum"), ("B", "mean2"), ("B", "sum2")]
436436
)
437437
for t in cases:
438-
with pytest.raises(pd.core.base.SpecificationError, match=msg):
438+
with pytest.raises(pd.errors.SpecificationError, match=msg):
439439
t.aggregate(
440440
{
441441
"A": {"mean": "mean", "sum": "sum"},
@@ -539,10 +539,10 @@ def test_agg_misc():
539539

540540
# series like aggs
541541
for t in cases:
542-
with pytest.raises(pd.core.base.SpecificationError, match=msg):
542+
with pytest.raises(pd.errors.SpecificationError, match=msg):
543543
t["A"].agg({"A": ["sum", "std"]})
544544

545-
with pytest.raises(pd.core.base.SpecificationError, match=msg):
545+
with pytest.raises(pd.errors.SpecificationError, match=msg):
546546
t["A"].agg({"A": ["sum", "std"], "B": ["mean", "std"]})
547547

548548
# errors
@@ -588,17 +588,17 @@ def test_agg_nested_dicts():
588588

589589
msg = "nested renamer is not supported"
590590
for t in cases:
591-
with pytest.raises(pd.core.base.SpecificationError, match=msg):
591+
with pytest.raises(pd.errors.SpecificationError, match=msg):
592592
t.aggregate({"r1": {"A": ["mean", "sum"]}, "r2": {"B": ["mean", "sum"]}})
593593

594594
for t in cases:
595595

596-
with pytest.raises(pd.core.base.SpecificationError, match=msg):
596+
with pytest.raises(pd.errors.SpecificationError, match=msg):
597597
t[["A", "B"]].agg(
598598
{"A": {"ra": ["mean", "std"]}, "B": {"rb": ["mean", "std"]}}
599599
)
600600

601-
with pytest.raises(pd.core.base.SpecificationError, match=msg):
601+
with pytest.raises(pd.errors.SpecificationError, match=msg):
602602
t.agg({"A": {"ra": ["mean", "std"]}, "B": {"rb": ["mean", "std"]}})
603603

604604

pandas/tests/test_errors.py

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"OptionError",
2121
"NumbaUtilError",
2222
"DataError",
23+
"SpecificationError",
2324
],
2425
)
2526
def test_exception_importable(exc):

pandas/tests/window/test_api.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import numpy as np
22
import pytest
33

4+
from pandas.errors import SpecificationError
5+
46
from pandas import (
57
DataFrame,
68
Index,
@@ -13,7 +15,6 @@
1315
timedelta_range,
1416
)
1517
import pandas._testing as tm
16-
from pandas.core.base import SpecificationError
1718

1819

1920
def test_getitem(step):

0 commit comments

Comments
 (0)