Skip to content

Commit 4b18266

Browse files
authored
API: IncompatibleFrequency subclass TypeError (#61875)
1 parent 6fca116 commit 4b18266

File tree

12 files changed

+22
-19
lines changed

12 files changed

+22
-19
lines changed

ci/code_checks.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
7474
-i "pandas.Series.dt PR01" `# Accessors are implemented as classes, but we do not document the Parameters section` \
7575
-i "pandas.Period.freq GL08" \
7676
-i "pandas.Period.ordinal GL08" \
77+
-i "pandas.errors.IncompatibleFrequency SA01,SS06,EX01" \
7778
-i "pandas.core.groupby.DataFrameGroupBy.plot PR02" \
7879
-i "pandas.core.groupby.SeriesGroupBy.plot PR02" \
7980
-i "pandas.core.resample.Resampler.quantile PR01,PR07" \

doc/source/reference/testing.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Exceptions and warnings
3636
errors.DuplicateLabelError
3737
errors.EmptyDataError
3838
errors.IncompatibilityWarning
39+
errors.IncompatibleFrequency
3940
errors.IndexingError
4041
errors.InvalidColumnName
4142
errors.InvalidComparison

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ Other API changes
414414
- Index set operations (like union or intersection) will now ignore the dtype of
415415
an empty ``RangeIndex`` or empty ``Index`` with object dtype when determining
416416
the dtype of the resulting Index (:issue:`60797`)
417+
- :class:`IncompatibleFrequency` now subclasses ``TypeError`` instead of ``ValueError``. As a result, joins with mismatched frequencies now cast to object like other non-comparable joins, and arithmetic with indexes with mismatched frequencies align (:issue:`55782`)
417418
- Comparison operations between :class:`Index` and :class:`Series` now consistently return :class:`Series` regardless of which object is on the left or right (:issue:`36759`)
418419
- Numpy functions like ``np.isinf`` that return a bool dtype when called on a :class:`Index` object now return a bool-dtype :class:`Index` instead of ``np.ndarray`` (:issue:`52676`)
419420

pandas/_libs/tslibs/period.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ from pandas._typing import (
1515
INVALID_FREQ_ERR_MSG: str
1616
DIFFERENT_FREQ: str
1717

18-
class IncompatibleFrequency(ValueError): ...
18+
class IncompatibleFrequency(TypeError): ...
1919

2020
def periodarr_to_dt64arr(
2121
periodarr: npt.NDArray[np.int64], # const int64_t[:]

pandas/_libs/tslibs/period.pyx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1625,7 +1625,11 @@ DIFFERENT_FREQ = ("Input has different freq={other_freq} "
16251625
"from {cls}(freq={own_freq})")
16261626

16271627

1628-
class IncompatibleFrequency(ValueError):
1628+
class IncompatibleFrequency(TypeError):
1629+
"""
1630+
Raised when trying to compare or operate between Periods with different
1631+
frequencies.
1632+
"""
16291633
pass
16301634

16311635

pandas/core/arrays/datetimelike.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ def _validate_comparison_value(self, other):
544544
other = self._scalar_type(other)
545545
try:
546546
self._check_compatible_with(other)
547-
except (TypeError, IncompatibleFrequency) as err:
547+
except TypeError as err:
548548
# e.g. tzawareness mismatch
549549
raise InvalidComparison(other) from err
550550

@@ -558,7 +558,7 @@ def _validate_comparison_value(self, other):
558558
try:
559559
other = self._validate_listlike(other, allow_object=True)
560560
self._check_compatible_with(other)
561-
except (TypeError, IncompatibleFrequency) as err:
561+
except TypeError as err:
562562
if is_object_dtype(getattr(other, "dtype", None)):
563563
# We will have to operate element-wise
564564
pass

pandas/core/indexes/base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
no_default,
3939
)
4040
from pandas._libs.tslibs import (
41-
IncompatibleFrequency,
4241
OutOfBoundsDatetime,
4342
Timestamp,
4443
tz_compare,
@@ -3139,7 +3138,7 @@ def _union(self, other: Index, sort: bool | None):
31393138
# test_union_same_value_duplicated_in_both fails)
31403139
try:
31413140
return self._outer_indexer(other)[0]
3142-
except (TypeError, IncompatibleFrequency):
3141+
except TypeError:
31433142
# incomparable objects; should only be for object dtype
31443143
value_list = list(lvals)
31453144

pandas/errors/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from pandas._config.config import OptionError
1010

1111
from pandas._libs.tslibs import (
12+
IncompatibleFrequency,
1213
OutOfBoundsDatetime,
1314
OutOfBoundsTimedelta,
1415
)
@@ -917,6 +918,7 @@ class InvalidComparison(Exception):
917918
"DuplicateLabelError",
918919
"EmptyDataError",
919920
"IncompatibilityWarning",
921+
"IncompatibleFrequency",
920922
"IndexingError",
921923
"IntCastingNaNError",
922924
"InvalidColumnName",

pandas/tests/indexes/period/test_indexing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ def test_get_indexer2(self):
502502
)
503503

504504
msg = "Input has different freq=None from PeriodArray\\(freq=h\\)"
505-
with pytest.raises(ValueError, match=msg):
505+
with pytest.raises(libperiod.IncompatibleFrequency, match=msg):
506506
idx.get_indexer(target, "nearest", tolerance="1 minute")
507507

508508
tm.assert_numpy_array_equal(

pandas/tests/indexes/period/test_join.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
import numpy as np
2-
import pytest
3-
4-
from pandas._libs.tslibs import IncompatibleFrequency
52

63
from pandas import (
74
DataFrame,
@@ -51,8 +48,9 @@ def test_join_does_not_recur(self):
5148
tm.assert_index_equal(res, expected)
5249

5350
def test_join_mismatched_freq_raises(self):
51+
# pre-GH#55782 this raises IncompatibleFrequency
5452
index = period_range("1/1/2000", "1/20/2000", freq="D")
5553
index3 = period_range("1/1/2000", "1/20/2000", freq="2D")
56-
msg = r".*Input has different freq=2D from Period\(freq=D\)"
57-
with pytest.raises(IncompatibleFrequency, match=msg):
58-
index.join(index3)
54+
result = index.join(index3)
55+
expected = index.astype(object).join(index3.astype(object))
56+
tm.assert_index_equal(result, expected)

0 commit comments

Comments
 (0)