From 2473883792b0f6935b0578169998a8a2db22eabd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Mon, 14 Aug 2023 10:42:29 -0400 Subject: [PATCH 01/11] (r)true/floor div --- pandas-stubs/core/arraylike.pyi | 10 +++---- pandas-stubs/core/frame.pyi | 5 ++++ pandas-stubs/core/indexes/base.pyi | 36 ++++++++++++++++++------ pandas-stubs/core/indexes/timedeltas.pyi | 10 +++++++ pandas-stubs/core/series.pyi | 18 +++++++++--- tests/test_indexes.py | 24 ++++++++++++++++ tests/test_scalars.py | 11 ++------ tests/test_series.py | 17 +++++++++++ 8 files changed, 104 insertions(+), 27 deletions(-) diff --git a/pandas-stubs/core/arraylike.pyi b/pandas-stubs/core/arraylike.pyi index 9c8d95f43..08d47a123 100644 --- a/pandas-stubs/core/arraylike.pyi +++ b/pandas-stubs/core/arraylike.pyi @@ -29,12 +29,12 @@ class OpsMixin: def __rsub__(self, other: Any) -> Self: ... def __mul__(self, other: Any) -> Self: ... def __rmul__(self, other: Any) -> Self: ... - def __truediv__(self, other: Any) -> Self: ... - def __rtruediv__(self, other: Any) -> Self: ... - # __floordiv__ is handled by subclasses that specify only the valid values + # Handled by subclasses that specify only the valid values # that can be passed - # def __floordiv__(self, other: Any) -> Self: ... - def __rfloordiv__(self, other: Any) -> Self: ... + # def __truediv__(self, other: Any) -> Self: ... + # def __rtruediv__(self, other: Any) -> Self: ... + # def __floordiv__(self, other: Any) -> Self: ... + # def __rfloordiv__(self, other: Any) -> Self: ... def __mod__(self, other: Any) -> Self: ... def __rmod__(self, other: Any) -> Self: ... def __divmod__(self, other: Any) -> tuple[Self, Self]: ... diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 71e00c245..69b8e3dcf 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -2279,3 +2279,8 @@ class DataFrame(NDFrame, OpsMixin): def __floordiv__( self, other: float | DataFrame | Series[int] | Series[float] ) -> Self: ... + def __rfloordiv__( + self, other: float | DataFrame | Series[int] | Series[float] + ) -> Self: ... + def __truediv__(self, other: float | DataFrame | Series) -> Self: ... + def __rtruediv__(self, other: float | DataFrame | Series) -> Self: ... diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index 95f1277e7..2dc604047 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -430,17 +430,35 @@ class Index(IndexOpsMixin[S1]): def __floordiv__( self, other: float - | Series[int] - | Series[float] + | IndexOpsMixin[int] + | IndexOpsMixin[float] | Sequence[int] - | Sequence[float] - | Index[int] - | Index[float], + | Sequence[float], + ) -> Self: ... + def __rfloordiv__( + self, + other: float + | IndexOpsMixin[int] + | IndexOpsMixin[float] + | Sequence[int] + | Sequence[float], + ) -> Self: ... + def __truediv__( + self, + other: float + | IndexOpsMixin[int] + | IndexOpsMixin[float] + | Sequence[int] + | Sequence[float], + ) -> Self: ... + def __rtruediv__( + self, + other: float + | IndexOpsMixin[int] + | IndexOpsMixin[float] + | Sequence[int] + | Sequence[float], ) -> Self: ... - @overload - def __truediv__(self: Index[int] | Index[float], other: timedelta) -> Never: ... - @overload - def __truediv__(self, other: Any) -> Self: ... def ensure_index_from_sequences( sequences: Sequence[Sequence[Dtype]], names: list[str] = ... diff --git a/pandas-stubs/core/indexes/timedeltas.pyi b/pandas-stubs/core/indexes/timedeltas.pyi index bcf480ee3..2ac3e478c 100644 --- a/pandas-stubs/core/indexes/timedeltas.pyi +++ b/pandas-stubs/core/indexes/timedeltas.pyi @@ -11,6 +11,7 @@ from typing import ( import numpy as np from pandas import ( DateOffset, + Index, Period, ) from pandas.core.indexes.accessors import TimedeltaIndexProperties @@ -55,7 +56,16 @@ class TimedeltaIndex(DatetimeTimedeltaMixin[Timedelta], TimedeltaIndexProperties def __radd__(self, other: Timestamp | DatetimeIndex) -> DatetimeIndex: ... # type: ignore[override] def __sub__(self, other: Timedelta | Self) -> Self: ... def __mul__(self, other: num) -> Self: ... + @overload # type: ignore[override] def __truediv__(self, other: num) -> Self: ... + @overload + def __truediv__(self, other: dt.timedelta) -> Index[float]: ... + def __rtruediv__(self, other: dt.timedelta) -> Index[float]: ... # type: ignore[override] + @overload # type: ignore[override] + def __floordiv__(self, other: num) -> Self: ... + @overload + def __floordiv__(self, other: dt.timedelta) -> Index[int]: ... + def __rfloordiv__(self, other: dt.timedelta) -> Index[int]: ... # type: ignore[override] def astype(self, dtype, copy: bool = ...): ... def get_value(self, series, key): ... def get_loc(self, key, tolerance=...): ... diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 839c2a19a..e938e0f11 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1502,9 +1502,6 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __ror__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... # type: ignore[misc] def __rsub__(self, other: num | _ListLike | Series[S1]) -> Series: ... - @overload - def __rtruediv__(self, other: TimedeltaSeries) -> Series[float]: ... - @overload def __rtruediv__(self, other: num | _ListLike | Series[S1]) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] @@ -2030,7 +2027,20 @@ class TimedeltaSeries(Series[Timedelta]): def __sub__( # type: ignore[override] self, other: Timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64 ) -> TimedeltaSeries: ... - def __truediv__(self, other: Timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex) -> Series[float]: ... # type: ignore[override] + @overload # type: ignore[override] + def __truediv__(self, other: float) -> Self: ... + @overload + def __truediv__( + self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex + ) -> Series[float]: ... + def __rtruediv__(self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex) -> Series[float]: ... # type: ignore[override,misc] + @overload # type: ignore[override] + def __floordiv__(self, other: float) -> Self: ... + @overload + def __floordiv__( + self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex + ) -> Series[int]: ... + def __rfloordiv__(self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex) -> Series[int]: ... # type: ignore[override,misc] @property def dt(self) -> TimedeltaProperties: ... # type: ignore[override] def mean( # type: ignore[override] diff --git a/tests/test_indexes.py b/tests/test_indexes.py index be437f5e0..03741dc65 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -2,6 +2,7 @@ import datetime as dt from typing import ( + TYPE_CHECKING, Tuple, Union, ) @@ -11,6 +12,7 @@ import pandas as pd from typing_extensions import ( Never, + TypeAlias, assert_type, ) @@ -21,6 +23,11 @@ check, ) +if TYPE_CHECKING: + from pandas.core.indexes.timedeltas import TimedeltaIndex +else: + TimedeltaIndex: TypeAlias = pd.Index + def test_index_unique() -> None: df = pd.DataFrame({"x": [1, 2, 3, 4]}, index=pd.Index([1, 2, 3, 2])) @@ -1022,3 +1029,20 @@ def test_new() -> None: pd.IntervalIndex, pd.Interval, ) + + +def test_timedelta_div() -> None: + index = pd.Index([pd.Timedelta(1)], dtype="timedelta64[s]") + delta = dt.timedelta(1) + + check(assert_type(index / delta, "pd.Index[float]"), pd.Index, float) + check(assert_type(index / 1, "TimedeltaIndex"), pd.Index, pd.Timedelta) + check(assert_type(index // delta, "pd.Index[int]"), pd.Index, np.longlong) + check(assert_type(index // 1, "TimedeltaIndex"), pd.Index, pd.Timedelta) + + check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) + check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) + + if TYPE_CHECKING_INVALID_USAGE: + 1 / index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] + 1 // index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] diff --git a/tests/test_scalars.py b/tests/test_scalars.py index 652814fec..9692676b2 100644 --- a/tests/test_scalars.py +++ b/tests/test_scalars.py @@ -15,7 +15,6 @@ import pandas as pd import pytz from typing_extensions import ( - Never, TypeAlias, assert_type, ) @@ -780,14 +779,8 @@ def test_timedelta_mul_div() -> None: md_ndarray_float / td # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] mp_series_int / td # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] md_series_float / td # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] - assert_type( - md_int64_index / td, # pyright: ignore[reportGeneralTypeIssues] - Never, - ) - assert_type( - md_float_index / td, # pyright: ignore[reportGeneralTypeIssues] - Never, - ) + md_int64_index / td, # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] + md_float_index / td, # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] def test_timedelta_mod_abs_unary() -> None: diff --git a/tests/test_series.py b/tests/test_series.py index 88c9f4854..330f6662e 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -2686,3 +2686,20 @@ def double(x): # Test cases with None and pd.NA as other check(assert_type(s.mask(s > 3, None), pd.Series), pd.Series, np.float64) check(assert_type(s.mask(s > 3, pd.NA), pd.Series), pd.Series, np.float64) + + +def test_timedelta_div() -> None: + series = pd.Series([pd.Timedelta(1)]) + delta = datetime.timedelta(1) + + check(assert_type(series / delta, "pd.Series[float]"), pd.Series, float) + check(assert_type(series / 1, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(series // delta, "pd.Series[int]"), pd.Series, np.longlong) + check(assert_type(series // 1, "TimedeltaSeries"), pd.Series, pd.Timedelta) + + check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) + check(assert_type(delta // series, "pd.Series[int]"), pd.Series, np.longlong) + + if TYPE_CHECKING_INVALID_USAGE: + 1 / series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] + 1 // series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] From addb263d2cb5cf3f67bef67e48c4b6ca6a0c21e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Mon, 14 Aug 2023 22:44:11 -0400 Subject: [PATCH 02/11] address comments --- pandas-stubs/core/series.pyi | 36 ++++++++++++++++++++++++++++++------ tests/test_indexes.py | 11 ++--------- tests/test_series.py | 8 ++++++++ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index e938e0f11..c1055c48e 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2028,19 +2028,43 @@ class TimedeltaSeries(Series[Timedelta]): self, other: Timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64 ) -> TimedeltaSeries: ... @overload # type: ignore[override] - def __truediv__(self, other: float) -> Self: ... + def __truediv__(self, other: float | Sequence[float]) -> Self: ... @overload def __truediv__( - self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex + self, + other: timedelta + | TimedeltaSeries + | np.timedelta64 + | TimedeltaIndex + | Sequence[timedelta], + ) -> Series[float]: ... + def __rtruediv__( # type: ignore[override] + self, + other: timedelta + | TimedeltaSeries + | np.timedelta64 + | TimedeltaIndex + | Sequence[timedelta], ) -> Series[float]: ... - def __rtruediv__(self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex) -> Series[float]: ... # type: ignore[override,misc] @overload # type: ignore[override] - def __floordiv__(self, other: float) -> Self: ... + def __floordiv__(self, other: float | Sequence[float]) -> Self: ... @overload def __floordiv__( - self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex + self, + other: timedelta + | TimedeltaSeries + | np.timedelta64 + | TimedeltaIndex + | Sequence[timedelta], + ) -> Series[int]: ... + def __rfloordiv__( # type: ignore[override] + self, + other: timedelta + | TimedeltaSeries + | np.timedelta64 + | TimedeltaIndex + | Sequence[timedelta], ) -> Series[int]: ... - def __rfloordiv__(self, other: timedelta | TimedeltaSeries | np.timedelta64 | TimedeltaIndex) -> Series[int]: ... # type: ignore[override,misc] @property def dt(self) -> TimedeltaProperties: ... # type: ignore[override] def mean( # type: ignore[override] diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 03741dc65..4461537ef 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -2,7 +2,6 @@ import datetime as dt from typing import ( - TYPE_CHECKING, Tuple, Union, ) @@ -12,7 +11,6 @@ import pandas as pd from typing_extensions import ( Never, - TypeAlias, assert_type, ) @@ -23,11 +21,6 @@ check, ) -if TYPE_CHECKING: - from pandas.core.indexes.timedeltas import TimedeltaIndex -else: - TimedeltaIndex: TypeAlias = pd.Index - def test_index_unique() -> None: df = pd.DataFrame({"x": [1, 2, 3, 4]}, index=pd.Index([1, 2, 3, 2])) @@ -1036,9 +1029,9 @@ def test_timedelta_div() -> None: delta = dt.timedelta(1) check(assert_type(index / delta, "pd.Index[float]"), pd.Index, float) - check(assert_type(index / 1, "TimedeltaIndex"), pd.Index, pd.Timedelta) + check(assert_type(index / 1, "pd.TimedeltaIndex"), pd.TimedeltaIndex, pd.Timedelta) check(assert_type(index // delta, "pd.Index[int]"), pd.Index, np.longlong) - check(assert_type(index // 1, "TimedeltaIndex"), pd.Index, pd.Timedelta) + check(assert_type(index // 1, "pd.TimedeltaIndex"), pd.TimedeltaIndex, pd.Timedelta) check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) diff --git a/tests/test_series.py b/tests/test_series.py index 330f6662e..3481338fd 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -2693,13 +2693,21 @@ def test_timedelta_div() -> None: delta = datetime.timedelta(1) check(assert_type(series / delta, "pd.Series[float]"), pd.Series, float) + check(assert_type(series / [delta], "pd.Series[float]"), pd.Series, float) check(assert_type(series / 1, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(series / [1], "TimedeltaSeries"), pd.Series, pd.Timedelta) check(assert_type(series // delta, "pd.Series[int]"), pd.Series, np.longlong) + check(assert_type(series // [delta], "pd.Series[int]"), pd.Series, int) check(assert_type(series // 1, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(series // [1], "TimedeltaSeries"), pd.Series, pd.Timedelta) check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) + check(assert_type([delta] / series, "pd.Series[float]"), pd.Series, float) check(assert_type(delta // series, "pd.Series[int]"), pd.Series, np.longlong) + check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, np.int64) if TYPE_CHECKING_INVALID_USAGE: 1 / series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] + [1] / series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] 1 // series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] + [1] // series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] From fd2cd0772a5b2a09093783019a47686d471f35b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Mon, 14 Aug 2023 23:03:46 -0400 Subject: [PATCH 03/11] and for DataFrame --- pandas-stubs/core/frame.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 69b8e3dcf..152d97f18 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -2277,10 +2277,10 @@ class DataFrame(NDFrame, OpsMixin): ) -> DataFrame | Series: ... # floordiv overload def __floordiv__( - self, other: float | DataFrame | Series[int] | Series[float] + self, other: float | DataFrame | Series[int] | Series[float] | Sequence[float] ) -> Self: ... def __rfloordiv__( - self, other: float | DataFrame | Series[int] | Series[float] + self, other: float | DataFrame | Series[int] | Series[float] | Sequence[float] ) -> Self: ... - def __truediv__(self, other: float | DataFrame | Series) -> Self: ... - def __rtruediv__(self, other: float | DataFrame | Series) -> Self: ... + def __truediv__(self, other: float | DataFrame | Series | Sequence) -> Self: ... + def __rtruediv__(self, other: float | DataFrame | Series | Sequence) -> Self: ... From 4e941b6f8c303b117176eccfa7efef3719a060d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Tue, 15 Aug 2023 10:40:01 -0400 Subject: [PATCH 04/11] add Sequence for TimedeltaIndex --- pandas-stubs/core/indexes/timedeltas.pyi | 16 ++++++++++------ tests/test_indexes.py | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/pandas-stubs/core/indexes/timedeltas.pyi b/pandas-stubs/core/indexes/timedeltas.pyi index 2ac3e478c..4cdf732c9 100644 --- a/pandas-stubs/core/indexes/timedeltas.pyi +++ b/pandas-stubs/core/indexes/timedeltas.pyi @@ -57,15 +57,19 @@ class TimedeltaIndex(DatetimeTimedeltaMixin[Timedelta], TimedeltaIndexProperties def __sub__(self, other: Timedelta | Self) -> Self: ... def __mul__(self, other: num) -> Self: ... @overload # type: ignore[override] - def __truediv__(self, other: num) -> Self: ... + def __truediv__(self, other: num | Sequence[float]) -> Self: ... @overload - def __truediv__(self, other: dt.timedelta) -> Index[float]: ... - def __rtruediv__(self, other: dt.timedelta) -> Index[float]: ... # type: ignore[override] + def __truediv__( + self, other: dt.timedelta | Sequence[dt.timedelta] + ) -> Index[float]: ... + def __rtruediv__(self, other: dt.timedelta | Sequence[dt.timedelta]) -> Index[float]: ... # type: ignore[override] @overload # type: ignore[override] - def __floordiv__(self, other: num) -> Self: ... + def __floordiv__(self, other: num | Sequence[float]) -> Self: ... @overload - def __floordiv__(self, other: dt.timedelta) -> Index[int]: ... - def __rfloordiv__(self, other: dt.timedelta) -> Index[int]: ... # type: ignore[override] + def __floordiv__( + self, other: dt.timedelta | Sequence[dt.timedelta] + ) -> Index[int]: ... + def __rfloordiv__(self, other: dt.timedelta | Sequence[dt.timedelta]) -> Index[int]: ... # type: ignore[override] def astype(self, dtype, copy: bool = ...): ... def get_value(self, series, key): ... def get_loc(self, key, tolerance=...): ... diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 4461537ef..2b9ae405a 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1029,13 +1029,23 @@ def test_timedelta_div() -> None: delta = dt.timedelta(1) check(assert_type(index / delta, "pd.Index[float]"), pd.Index, float) - check(assert_type(index / 1, "pd.TimedeltaIndex"), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(index / [delta], "pd.Index[float]"), pd.Index, float) + check(assert_type(index / 1, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(index / [1], pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) check(assert_type(index // delta, "pd.Index[int]"), pd.Index, np.longlong) - check(assert_type(index // 1, "pd.TimedeltaIndex"), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(index // [delta], "pd.Index[int]"), pd.Index, int) + check(assert_type(index // 1, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(index // [1], pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) + # ZeroDivisionError + # check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) + # ZeroDivisionError + # check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.longlong) if TYPE_CHECKING_INVALID_USAGE: 1 / index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] + [1] / index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] 1 // index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] + [1] // index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] From c17fdb8f29f680d6bd9ba817ee442e2055edf031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Tue, 15 Aug 2023 11:25:51 -0400 Subject: [PATCH 05/11] list test for DataFrame --- tests/test_frame.py | 83 ++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/tests/test_frame.py b/tests/test_frame.py index e577be021..2e9e35374 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -745,59 +745,74 @@ def test_types_element_wise_arithmetic() -> None: df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) df2 = pd.DataFrame(data={"col1": [10, 20], "col3": [3, 4]}) - res_add1: pd.DataFrame = df + df2 - res_add2: pd.DataFrame = df.add(df2, fill_value=0) + check(assert_type(df + df2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.add(df2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_sub: pd.DataFrame = df - df2 - res_sub2: pd.DataFrame = df.sub(df2, fill_value=0) + check(assert_type(df - df2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.sub(df2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_mul: pd.DataFrame = df * df2 - res_mul2: pd.DataFrame = df.mul(df2, fill_value=0) + check(assert_type(df * df2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.mul(df2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_div: pd.DataFrame = df / df2 - res_div2: pd.DataFrame = df.div(df2, fill_value=0) + check(assert_type(df / df2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.div(df2, fill_value=0), pd.DataFrame), pd.DataFrame) + check(assert_type(df / [2, 2], pd.DataFrame), pd.DataFrame) + check(assert_type(df.div([2, 2], fill_value=0), pd.DataFrame), pd.DataFrame) - res_floordiv: pd.DataFrame = df // df2 - res_floordiv2: pd.DataFrame = df.floordiv(df2, fill_value=0) + check(assert_type(df // df2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.floordiv(df2, fill_value=0), pd.DataFrame), pd.DataFrame) + check(assert_type(df // [2, 2], pd.DataFrame), pd.DataFrame) + check(assert_type(df.floordiv([2, 2], fill_value=0), pd.DataFrame), pd.DataFrame) - res_mod: pd.DataFrame = df % df2 - res_mod2: pd.DataFrame = df.mod(df2, fill_value=0) + check(assert_type(df % df2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.mod(df2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_pow: pd.DataFrame = df2**df - res_pow2: pd.DataFrame = df2.pow(df, fill_value=0) + check(assert_type(df2**df, pd.DataFrame), pd.DataFrame) + check(assert_type(df2.pow(df, fill_value=0), pd.DataFrame), pd.DataFrame) # divmod operation was added in 1.2.0 https://pandas.pydata.org/docs/whatsnew/v1.2.0.html - # noinspection PyTypeChecker - res_divmod: tuple[pd.DataFrame, pd.DataFrame] = divmod(df, df2) - res_divmod2: tuple[pd.DataFrame, pd.DataFrame] = df.__divmod__(df2) - res_rdivmod: tuple[pd.DataFrame, pd.DataFrame] = df.__rdivmod__(df2) + check( + assert_type(divmod(df, df2), tuple[pd.DataFrame, pd.DataFrame]), + tuple, + pd.DataFrame, + ) + check( + assert_type(df.__divmod__(df2), tuple[pd.DataFrame, pd.DataFrame]), + tuple, + pd.DataFrame, + ) + check( + assert_type(df.__rdivmod__(df2), tuple[pd.DataFrame, pd.DataFrame]), + tuple, + pd.DataFrame, + ) def test_types_scalar_arithmetic() -> None: df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) - res_add1: pd.DataFrame = df + 1 - res_add2: pd.DataFrame = df.add(1, fill_value=0) + check(assert_type(df + 1, pd.DataFrame), pd.DataFrame) + check(assert_type(df.add(1, fill_value=0), pd.DataFrame), pd.DataFrame) - res_sub: pd.DataFrame = df - 1 - res_sub2: pd.DataFrame = df.sub(1, fill_value=0) + check(assert_type(df - 1, pd.DataFrame), pd.DataFrame) + check(assert_type(df.sub(1, fill_value=0), pd.DataFrame), pd.DataFrame) - res_mul: pd.DataFrame = df * 2 - res_mul2: pd.DataFrame = df.mul(2, fill_value=0) + check(assert_type(df * 2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.mul(2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_div: pd.DataFrame = df / 2 - res_div2: pd.DataFrame = df.div(2, fill_value=0) + check(assert_type(df / 2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.div(2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_floordiv: pd.DataFrame = df // 2 - res_floordiv2: pd.DataFrame = df.floordiv(2, fill_value=0) + check(assert_type(df // 2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.floordiv(2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_mod: pd.DataFrame = df % 2 - res_mod2: pd.DataFrame = df.mod(2, fill_value=0) + check(assert_type(df % 2, pd.DataFrame), pd.DataFrame) + check(assert_type(df.mod(2, fill_value=0), pd.DataFrame), pd.DataFrame) - res_pow: pd.DataFrame = df**2 - res_pow1: pd.DataFrame = df**0 - res_pow2: pd.DataFrame = df**0.213 - res_pow3: pd.DataFrame = df.pow(0.5) + check(assert_type(df**2, pd.DataFrame), pd.DataFrame) + check(assert_type(df**0, pd.DataFrame), pd.DataFrame) + check(assert_type(df**0.213, pd.DataFrame), pd.DataFrame) + check(assert_type(df.pow(0.5), pd.DataFrame), pd.DataFrame) def test_types_melt() -> None: From 9a8ad789559730da62d279c6add2905c71191453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Tue, 15 Aug 2023 11:29:15 -0400 Subject: [PATCH 06/11] and 3.8 for pyright --- tests/test_frame.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_frame.py b/tests/test_frame.py index 2e9e35374..b71880032 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -772,17 +772,17 @@ def test_types_element_wise_arithmetic() -> None: # divmod operation was added in 1.2.0 https://pandas.pydata.org/docs/whatsnew/v1.2.0.html check( - assert_type(divmod(df, df2), tuple[pd.DataFrame, pd.DataFrame]), + assert_type(divmod(df, df2), "tuple[pd.DataFrame, pd.DataFrame]"), tuple, pd.DataFrame, ) check( - assert_type(df.__divmod__(df2), tuple[pd.DataFrame, pd.DataFrame]), + assert_type(df.__divmod__(df2), "tuple[pd.DataFrame, pd.DataFrame]"), tuple, pd.DataFrame, ) check( - assert_type(df.__rdivmod__(df2), tuple[pd.DataFrame, pd.DataFrame]), + assert_type(df.__rdivmod__(df2), "tuple[pd.DataFrame, pd.DataFrame]"), tuple, pd.DataFrame, ) From 60737de71fa69d5ba4900a7ac3591ebbdb71fe97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Wed, 16 Aug 2023 09:24:06 -0400 Subject: [PATCH 07/11] avoid ZeroDivisionError --- tests/test_indexes.py | 8 +++----- tests/test_series.py | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 2b9ae405a..40a080d0f 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1025,7 +1025,7 @@ def test_new() -> None: def test_timedelta_div() -> None: - index = pd.Index([pd.Timedelta(1)], dtype="timedelta64[s]") + index = pd.Index([pd.Timedelta(days=1)], dtype="timedelta64[s]") delta = dt.timedelta(1) check(assert_type(index / delta, "pd.Index[float]"), pd.Index, float) @@ -1038,11 +1038,9 @@ def test_timedelta_div() -> None: check(assert_type(index // [1], pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) - # ZeroDivisionError - # check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) + check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) - # ZeroDivisionError - # check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.longlong) + check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.int64) if TYPE_CHECKING_INVALID_USAGE: 1 / index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] diff --git a/tests/test_series.py b/tests/test_series.py index 3481338fd..a053d3edc 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -2689,7 +2689,7 @@ def double(x): def test_timedelta_div() -> None: - series = pd.Series([pd.Timedelta(1)]) + series = pd.Series([pd.Timedelta(days=1)]) delta = datetime.timedelta(1) check(assert_type(series / delta, "pd.Series[float]"), pd.Series, float) From cf93d64ce34c00d894699419a2e48312c5f1a92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Wed, 16 Aug 2023 09:31:05 -0400 Subject: [PATCH 08/11] fix 32bit? --- tests/test_indexes.py | 2 +- tests/test_series.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 40a080d0f..63735943c 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1040,7 +1040,7 @@ def test_timedelta_div() -> None: check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) - check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.int64) + check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.intp) if TYPE_CHECKING_INVALID_USAGE: 1 / index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] diff --git a/tests/test_series.py b/tests/test_series.py index a053d3edc..9038b264e 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -2704,7 +2704,7 @@ def test_timedelta_div() -> None: check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) check(assert_type([delta] / series, "pd.Series[float]"), pd.Series, float) check(assert_type(delta // series, "pd.Series[int]"), pd.Series, np.longlong) - check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, np.intp) if TYPE_CHECKING_INVALID_USAGE: 1 / series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] From 607e0a069cd7bfee70348d4b09c1c6fff1454895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Wed, 16 Aug 2023 09:42:30 -0400 Subject: [PATCH 09/11] fix test on windows? --- tests/test_indexes.py | 6 +++++- tests/test_series.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 63735943c..e491fe119 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1,6 +1,7 @@ from __future__ import annotations import datetime as dt +import sys from typing import ( Tuple, Union, @@ -1040,7 +1041,10 @@ def test_timedelta_div() -> None: check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) - check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.intp) + dtype = np.int64 + if sys.platform == "win32": + dtype = np.int32 + check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, dtype) if TYPE_CHECKING_INVALID_USAGE: 1 / index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] diff --git a/tests/test_series.py b/tests/test_series.py index 9038b264e..77a01bd4c 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -6,6 +6,7 @@ from pathlib import Path import platform import re +import sys from typing import ( TYPE_CHECKING, Any, @@ -2704,7 +2705,10 @@ def test_timedelta_div() -> None: check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) check(assert_type([delta] / series, "pd.Series[float]"), pd.Series, float) check(assert_type(delta // series, "pd.Series[int]"), pd.Series, np.longlong) - check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, np.intp) + dtype = np.int64 + if sys.platform == "win32": + dtype = np.int32 + check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, dtype) if TYPE_CHECKING_INVALID_USAGE: 1 / series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] From d68a0f767d4e58f7aa434c83d7fe510dd88d5fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Wed, 16 Aug 2023 09:51:20 -0400 Subject: [PATCH 10/11] fix mypy on win? --- tests/test_indexes.py | 2 +- tests/test_series.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_indexes.py b/tests/test_indexes.py index e491fe119..425aadf3f 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1041,7 +1041,7 @@ def test_timedelta_div() -> None: check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) - dtype = np.int64 + dtype: type[np.integer] = np.int64 if sys.platform == "win32": dtype = np.int32 check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, dtype) diff --git a/tests/test_series.py b/tests/test_series.py index 77a01bd4c..83fcb718b 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -2705,7 +2705,7 @@ def test_timedelta_div() -> None: check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) check(assert_type([delta] / series, "pd.Series[float]"), pd.Series, float) check(assert_type(delta // series, "pd.Series[int]"), pd.Series, np.longlong) - dtype = np.int64 + dtype: type[np.integer] = np.int64 if sys.platform == "win32": dtype = np.int32 check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, dtype) From d7a0fa84060e1100a90bc29da9be40ac427fc150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Wed, 16 Aug 2023 11:12:38 -0400 Subject: [PATCH 11/11] use np.signedinteger --- tests/test_indexes.py | 6 +----- tests/test_series.py | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 425aadf3f..0115b152d 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1,7 +1,6 @@ from __future__ import annotations import datetime as dt -import sys from typing import ( Tuple, Union, @@ -1041,10 +1040,7 @@ def test_timedelta_div() -> None: check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) - dtype: type[np.integer] = np.int64 - if sys.platform == "win32": - dtype = np.int32 - check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, dtype) + check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.signedinteger) if TYPE_CHECKING_INVALID_USAGE: 1 / index # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues] diff --git a/tests/test_series.py b/tests/test_series.py index 83fcb718b..a9eced036 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -6,7 +6,6 @@ from pathlib import Path import platform import re -import sys from typing import ( TYPE_CHECKING, Any, @@ -2705,10 +2704,7 @@ def test_timedelta_div() -> None: check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) check(assert_type([delta] / series, "pd.Series[float]"), pd.Series, float) check(assert_type(delta // series, "pd.Series[int]"), pd.Series, np.longlong) - dtype: type[np.integer] = np.int64 - if sys.platform == "win32": - dtype = np.int32 - check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, dtype) + check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, np.signedinteger) if TYPE_CHECKING_INVALID_USAGE: 1 / series # type: ignore[operator] # pyright: ignore[reportGeneralTypeIssues]