From cac423956a72ecb513446b72a49b370c45f7a75e Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Thu, 29 Dec 2022 11:26:56 -0500 Subject: [PATCH] fix up ignores for invalid usage --- pandas-stubs/_libs/interval.pyi | 31 ++++++++++++++++++++++--------- pandas-stubs/core/series.pyi | 14 ++------------ tests/test_frame.py | 9 ++++++--- tests/test_interval.py | 19 +++++-------------- tests/test_scalars.py | 15 +++++++++------ tests/test_timefuncs.py | 4 ++-- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/pandas-stubs/_libs/interval.pyi b/pandas-stubs/_libs/interval.pyi index 69e79b7c8..0c4a82856 100644 --- a/pandas-stubs/_libs/interval.pyi +++ b/pandas-stubs/_libs/interval.pyi @@ -77,14 +77,20 @@ class Interval(IntervalMixin, Generic[_OrderableT]): closed: IntervalClosedType = ..., ): ... def __hash__(self) -> int: ... + # for __contains__, it seems that we have to separate out the 4 cases to make + # mypy happy @overload - def __contains__(self: Interval[_OrderableTimesT], _OrderableTimesT) -> bool: ... + def __contains__(self: Interval[Timestamp], key: Timestamp) -> bool: ... @overload - def __contains__(self: Interval[_OrderableScalarT], key: float) -> bool: ... + def __contains__(self: Interval[Timedelta], key: Timedelta) -> bool: ... @overload - def __add__( - self: Interval[_OrderableTimesT], y: Timedelta - ) -> Interval[_OrderableTimesT]: ... + def __contains__(self: Interval[int], key: float) -> bool: ... + @overload + def __contains__(self: Interval[float], key: float) -> bool: ... + @overload + def __add__(self: Interval[Timestamp], y: Timedelta) -> Interval[Timestamp]: ... + @overload + def __add__(self: Interval[Timedelta], y: Timedelta) -> Interval[Timedelta]: ... @overload def __add__( self: Interval[int], y: _OrderableScalarT @@ -138,7 +144,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __rmul__(self: Interval[Timedelta], y: float) -> Interval[Timedelta]: ... @overload - def __truediv__(self: Interval[int], y: _OrderableScalarT) -> Interval[float]: ... + def __truediv__(self: Interval[int], y: int | float) -> Interval[float]: ... @overload def __truediv__(self: Interval[float], y: float) -> Interval[float]: ... @overload @@ -162,19 +168,26 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __gt__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ... @overload - def __gt__(self, other: Series[_OrderableT]) -> Series[bool]: ... + def __gt__( + self, + other: Series[int] | Series[float] | Series[Timestamp] | Series[Timedelta], + ) -> Series[bool]: ... @overload def __lt__(self, other: Interval[_OrderableT]) -> bool: ... @overload def __lt__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ... @overload - def __lt__(self, other: Series[_OrderableT]) -> Series[bool]: ... + def __lt__( + self, other: Series[int] | Series[float] | Series[Timestamp] | Series[Timedelta] + ) -> Series[bool]: ... @overload def __ge__(self, other: Interval[_OrderableT]) -> bool: ... @overload def __ge__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ... @overload - def __ge__(self, other: Series[_OrderableT]) -> Series[bool]: ... + def __ge__( + self, other: Series[int] | Series[float] | Series[Timestamp] | Series[Timedelta] + ) -> Series[bool]: ... @overload def __le__(self, other: Interval[_OrderableT]) -> bool: ... @overload diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 93b1603e1..79961bd3b 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1351,11 +1351,6 @@ class Series(IndexOpsMixin, NDFrame, Generic[S1]): ) -> TimedeltaSeries: ... @overload def __sub__(self, other: num | _ListLike | Series) -> Series: ... - @overload - def __truediv__( - self, other: Timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64 - ) -> Series[float]: ... - @overload def __truediv__(self, other: num | _ListLike | Series[S1]) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload @@ -1779,12 +1774,7 @@ class TimestampSeries(Series[Timestamp]): # ignore needed because of mypy @property def dt(self) -> TimestampProperties: ... # type: ignore[override] - @overload # type: ignore[override] - def __add__( - self, other: TimedeltaSeries | np.timedelta64 | TimestampSeries - ) -> TimestampSeries: ... - @overload - def __add__(self, other: Timestamp) -> Never: ... + def __add__(self, other: TimedeltaSeries | np.timedelta64) -> TimestampSeries: ... # type: ignore[override] def __mul__(self, other: TimestampSeries | np.timedelta64 | TimedeltaSeries) -> Never: ... # type: ignore[override] def __truediv__(self, other: TimestampSeries | np.timedelta64 | TimedeltaSeries) -> Never: ... # type: ignore[override] @@ -1808,7 +1798,7 @@ class TimedeltaSeries(Series[Timedelta]): def __sub__( # type: ignore[override] self, other: Timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64 ) -> TimedeltaSeries: ... - def __truediv__(self, other: TimedeltaSeries | np.timedelta64 | TimedeltaIndex) -> Series[float]: ... # type: ignore[override] + def __truediv__(self, other: Timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex) -> Series[float]: ... # type: ignore[override] @property def dt(self) -> TimedeltaProperties: ... # type: ignore[override] diff --git a/tests/test_frame.py b/tests/test_frame.py index 2157f79f1..f3fbc46bb 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1790,6 +1790,8 @@ def test_set_columns() -> None: df.columns = pd.Series([1, "a"]) df.columns = (1, 2) df.columns = (1, "a") + if TYPE_CHECKING_INVALID_USAGE: + df.columns = "abc" # pyright: ignore[reportGeneralTypeIssues] def test_frame_index_numpy() -> None: @@ -1825,9 +1827,10 @@ def test_not_hashable() -> None: def test_func(h: Hashable): pass - test_func(pd.DataFrame()) # type: ignore[arg-type] - test_func(pd.Series([], dtype=object)) # type: ignore[arg-type] - test_func(pd.Index([])) # type: ignore[arg-type] + if TYPE_CHECKING_INVALID_USAGE: + test_func(pd.DataFrame()) # type: ignore[arg-type] + test_func(pd.Series([], dtype=object)) # type: ignore[arg-type] + test_func(pd.Index([])) # type: ignore[arg-type] def test_columns_mixlist() -> None: diff --git a/tests/test_interval.py b/tests/test_interval.py index 38a0dbf12..149eba584 100644 --- a/tests/test_interval.py +++ b/tests/test_interval.py @@ -50,7 +50,7 @@ def test_interval_length() -> None: check(assert_type(idres, "pd.Interval[pd.Timestamp]"), pd.Interval, pd.Timestamp) if TYPE_CHECKING_INVALID_USAGE: - 20 in i1 # TODO both: ignore[operator] + 20 in i1 # type: ignore[operator] i1 + pd.Timestamp("2000-03-03") # type: ignore[operator] i1 * 3 # type: ignore[operator] i1 * pd.Timedelta(seconds=20) # type: ignore[operator] @@ -69,13 +69,8 @@ def test_interval_length() -> None: check(assert_type(i2 * 4.2, "pd.Interval[float]"), pd.Interval, float) if TYPE_CHECKING_INVALID_USAGE: - pd.Timestamp( - "2001-01-02" - ) in i2 # pyright: ignore[reportGeneralTypeIssues] # TODO mypy: ignore[operator] - i2 + pd.Timedelta( - seconds=20 - ) # pyright: ignore[reportGeneralTypeIssues] # TODO mypy: ignore[operator] - + pd.Timestamp("2001-01-02") in i2 # type: ignore[operator] + i2 + pd.Timedelta(seconds=20) # type: ignore[type-var] i3 = pd.Interval(13.2, 19.5) check(assert_type(i3.length, float), float) check(assert_type(i3.left, float), float) @@ -87,9 +82,5 @@ def test_interval_length() -> None: check(assert_type(i3 + 3, "pd.Interval[float]"), pd.Interval, float) check(assert_type(i3 * 3, "pd.Interval[float]"), pd.Interval, float) if TYPE_CHECKING_INVALID_USAGE: - pd.Timestamp( - "2001-01-02" - ) in i3 # pyright: ignore[reportGeneralTypeIssues] # TODO mypy: ignore[operator] - i3 + pd.Timedelta( - seconds=20 - ) # pyright: ignore[reportGeneralTypeIssues] # TODO mypy: ignore[operator] + pd.Timestamp("2001-01-02") in i3 # type: ignore[operator] + i3 + pd.Timedelta(seconds=20) # type: ignore[operator] diff --git a/tests/test_scalars.py b/tests/test_scalars.py index 48c21e7c9..479a2f940 100644 --- a/tests/test_scalars.py +++ b/tests/test_scalars.py @@ -26,6 +26,7 @@ from pandas._libs.tslibs.timedeltas import Components from tests import ( + IS_TYPE_CHECKER_MYPY, TYPE_CHECKING_INVALID_USAGE, check, pytest_warns_bounded, @@ -782,10 +783,8 @@ def test_timedelta_mul_div() -> None: md_float / td # type: ignore[operator] md_ndarray_intp / td # type: ignore[operator] md_ndarray_float / td # type: ignore[operator] - # TODO: Series.__truediv__ says it supports Timedelta - # it does not, in general, except for TimedeltaSeries - # mp_series_int / td # type: ignore[operator] - # mp_series_float / td # type: ignore[operator] + mp_series_int / td # type: ignore[operator] + md_series_float / td # type: ignore[operator] md_int64_index / td # type: ignore[operator] md_float_index / td # type: ignore[operator] @@ -826,8 +825,12 @@ def test_timedelta_mod_abs_unary() -> None: pd.TimedeltaIndex, ) - # mypy reports dt.timedelta, even though __abs__ returns Timedelta - check(assert_type(abs(td), pd.Timedelta), pd.Timedelta) # type: ignore[assert-type] + if TYPE_CHECKING and IS_TYPE_CHECKER_MYPY: + # mypy reports dt.timedelta, even though __abs__ returns Timedelta + check(assert_type(abs(td), pd.Timedelta), pd.Timedelta) # type: ignore[assert-type] + else: + # This is valid for pyright + check(assert_type(abs(td), pd.Timedelta), pd.Timedelta) check(assert_type(td.__abs__(), pd.Timedelta), pd.Timedelta) check(assert_type(-td, pd.Timedelta), pd.Timedelta) check(assert_type(+td, pd.Timedelta), pd.Timedelta) diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index 91c1be634..ee0d1ee53 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -261,9 +261,9 @@ def test_fail_on_adding_two_timestamps() -> None: s1 = pd.Series(pd.to_datetime(["2022-05-01", "2022-06-01"])) s2 = pd.Series(pd.to_datetime(["2022-05-15", "2022-06-15"])) if TYPE_CHECKING_INVALID_USAGE: - ssum: pd.Series = s1 + s2 # TODO both: ignore[operator] + ssum: pd.Series = s1 + s2 # type: ignore[operator] ts = pd.Timestamp("2022-06-30") - tsum: pd.Series = s1 + ts # pyright: ignore + tsum: pd.Series = s1 + ts # type: ignore[operator] def test_dtindex_tzinfo() -> None: