diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 0fac9a3d..49961ecb 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -25,6 +25,7 @@ from typing import ( Generic, Literal, NoReturn, + TypeVar, final, overload, ) @@ -175,6 +176,8 @@ from pandas._typing import ( VoidDtypeArg, WriteBuffer, np_ndarray_anyint, + np_ndarray_complex, + np_ndarray_float, npt, num, ) @@ -184,6 +187,8 @@ from pandas.core.dtypes.dtypes import CategoricalDtype from pandas.plotting import PlotAccessor +_T_COMPLEX = TypeVar("_T_COMPLEX", bound=complex) + class _iLocIndexerSeries(_iLocIndexer, Generic[S1]): # get item @overload @@ -424,20 +429,180 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series: ... @property def hasnans(self) -> bool: ... + @overload + def div( + self: Series[Never], + other: Scalar | _ListLike | Series, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... + @overload def div( self, - other: num | _ListLike | Series[S1], + other: Series[Never], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... + @overload + def div( + self: Series[int], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., ) -> Series[float]: ... + @overload + def div( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def div( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def div( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def div( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def div( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def div( + self: Series[complex], + other: ( + _T_COMPLEX + | Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def div( + self, + other: Scalar | _ListLike | Series, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... + @overload + def rdiv( + self: Series[Never], + other: Scalar | _ListLike | Series, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... + @overload def rdiv( self, - other: Series[S1] | Scalar, + other: Series[Never], level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., - ) -> Series[S1]: ... + ) -> Series: ... + @overload + def rdiv( + self: Series[int], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def rdiv( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def rdiv( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def rdiv( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def rdiv( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def rdiv( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def rdiv( + self: Series[complex], + other: ( + _T_COMPLEX + | Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def rdiv( + self, + other: Scalar | _ListLike | Series, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... @property def dtype(self) -> DtypeObj: ... @property @@ -1689,6 +1854,39 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __ror__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... def __rsub__(self, other: num | _ListLike | Series[S1]) -> Series: ... + @overload + def __rtruediv__( + self: Series[Never], other: num | _ListLike | Series | Path + ) -> Series: ... + @overload + def __rtruediv__( + self: Series[int], other: int | Sequence[int] + ) -> Series[float]: ... + @overload + def __rtruediv__( + self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload + def __rtruediv__( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float, + ) -> Series[float]: ... + @overload + def __rtruediv__( + self: Series[complex], + other: ( + _T_COMPLEX + | Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + ), + ) -> Series[complex]: ... + @overload + def __rtruediv__( + self: Series[float], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload def __rtruediv__(self, other: num | _ListLike | Series[S1] | Path) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] @@ -1713,6 +1911,52 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> TimedeltaSeries: ... @overload def __sub__(self, other: num | _ListLike | Series) -> Series: ... + @overload + def __truediv__( + self: Series[Never], other: num | _ListLike | Series | Path + ) -> Series: ... + @overload + def __truediv__(self: Series, other: Series[Never]) -> Series: ... + @overload + def __truediv__( + self: Series[int], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + ) -> Series[float]: ... + @overload + def __truediv__( + self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload + def __truediv__( + self: Series[int], other: np_ndarray_complex + ) -> Series[complex]: ... + @overload + def __truediv__( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + ) -> Series[float]: ... + @overload + def __truediv__( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + ) -> Series[_T_COMPLEX]: ... + @overload + def __truediv__( + self: Series[float], other: np_ndarray_complex + ) -> Series[complex]: ... + @overload + def __truediv__( + self: Series[complex], + other: ( + _T_COMPLEX + | Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + ) -> Series[complex]: ... + @overload def __truediv__(self, other: num | _ListLike | Series[S1] | Path) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] @@ -2067,13 +2311,85 @@ class Series(IndexOpsMixin[S1], NDFrame): fill_value: float | None = ..., axis: AxisIndex = ..., ) -> Series[S1]: ... + @overload + def rtruediv( + self: Series[Never], + other: Scalar | _ListLike | Series, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... + @overload + def rtruediv( + self: Series[int], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def rtruediv( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def rtruediv( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def rtruediv( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def rtruediv( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def rtruediv( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def rtruediv( + self: Series[complex], + other: ( + _T_COMPLEX + | Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload def rtruediv( self, - other, + other: Scalar | _ListLike | Series, level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., - ) -> Series[S1]: ... + ) -> Series: ... def sem( self, axis: AxisIndex | None = ..., @@ -2157,13 +2473,93 @@ class Series(IndexOpsMixin[S1], NDFrame): **kwargs: Any, ) -> np.ndarray: ... def tolist(self) -> list[S1]: ... + @overload + def truediv( + self: Series[Never], + other: Scalar | _ListLike | Series, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... + @overload def truediv( self, - other, + other: Series[Never], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... + @overload + def truediv( + self: Series[int], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def truediv( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def truediv( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def truediv( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., ) -> Series[float]: ... + @overload + def truediv( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def truediv( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def truediv( + self: Series[complex], + other: ( + _T_COMPLEX + | Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series[complex]: ... + @overload + def truediv( + self, + other: Scalar | _ListLike | Series, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., + ) -> Series: ... def var( self, axis: AxisIndex | None = ..., diff --git a/tests/series/__init__.py b/tests/series/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/series/arithmetic/__init__.py b/tests/series/arithmetic/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/series/arithmetic/complex/__init__.py b/tests/series/arithmetic/complex/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/series/arithmetic/complex/test_truediv.py b/tests/series/arithmetic/complex/test_truediv.py new file mode 100644 index 00000000..d08c7caf --- /dev/null +++ b/tests/series/arithmetic/complex/test_truediv.py @@ -0,0 +1,146 @@ +import numpy as np +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.Series([1j, 2j, 3j]) # left operand + + +def test_truediv_py_scalar() -> None: + """Test pd.Series[complex] / Python native scalars""" + i, f, c = 1, 1.0, 1j + + check(assert_type(left / i, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(f / left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_py_sequence() -> None: + """Test pd.Series[complex] / Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left / i, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(f / left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_numpy_array() -> None: + """Test pd.Series[complex] / numpy array""" + i = np.array([2, 3, 5], np.int64) + f = np.array([1.0, 2.0, 3.0], np.float64) + c = np.array([1.1j, 2.2j, 4.1j], np.complex128) + + check(assert_type(left / i, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i / left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) + check( + assert_type( # type: ignore[assert-type] + f / left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) + check( + assert_type( # type: ignore[assert-type] + c / left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) + + check(assert_type(left.truediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_pd_series() -> None: + """Test pd.Series[complex] / pandas series""" + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + check(assert_type(left / i, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(f / left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) diff --git a/tests/series/arithmetic/float/__init__.py b/tests/series/arithmetic/float/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/series/arithmetic/float/test_truediv.py b/tests/series/arithmetic/float/test_truediv.py new file mode 100644 index 00000000..1e440b9f --- /dev/null +++ b/tests/series/arithmetic/float/test_truediv.py @@ -0,0 +1,146 @@ +import numpy as np +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.Series([1.0, 2.0, 3.0]) # left operand + + +def test_truediv_py_scalar() -> None: + """Test pd.Series[float] / Python native scalars""" + i, f, c = 1, 1.0, 1j + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_py_sequence() -> None: + """Test pd.Series[float] / Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_numpy_array() -> None: + """Test pd.Series[float] / numpy array""" + i = np.array([2, 3, 5], np.int64) + f = np.array([1.0, 2.0, 3.0], np.float64) + c = np.array([1.1j, 2.2j, 4.1j], np.complex128) + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i / left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.float64, + ) + check( + assert_type( # type: ignore[assert-type] + f / left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.float64, + ) + check( + assert_type( # type: ignore[assert-type] + c / left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_pd_series() -> None: + """Test pd.Series[float] / pandas series""" + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) diff --git a/tests/series/arithmetic/int/__init__.py b/tests/series/arithmetic/int/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/series/arithmetic/int/test_truediv.py b/tests/series/arithmetic/int/test_truediv.py new file mode 100644 index 00000000..fee98380 --- /dev/null +++ b/tests/series/arithmetic/int/test_truediv.py @@ -0,0 +1,146 @@ +import numpy as np +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.Series([1, 2, 3]) # left operand + + +def test_truediv_py_scalar() -> None: + """Test pd.Series[int] / Python native scalars""" + i, f, c = 1, 1.0, 1j + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_py_sequence() -> None: + """Test pd.Series[int] / Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_numpy_array() -> None: + """Test pd.Series[int] / numpy array""" + i = np.array([2, 3, 5], np.int64) + f = np.array([1.0, 2.0, 3.0], np.float64) + c = np.array([1.1j, 2.2j, 4.1j], np.complex128) + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i / left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.float64, + ) + check( + assert_type( # type: ignore[assert-type] + f / left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.float64, + ) + check( + assert_type( # type: ignore[assert-type] + c / left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_truediv_pd_series() -> None: + """Test pd.Series[int] / pandas series""" + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.truediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rtruediv(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complex128) diff --git a/tests/series/arithmetic/test_truediv.py b/tests/series/arithmetic/test_truediv.py new file mode 100644 index 00000000..7a806549 --- /dev/null +++ b/tests/series/arithmetic/test_truediv.py @@ -0,0 +1,143 @@ +import numpy as np +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.DataFrame({"a": [1, 2, 3]})["a"] # left operand + + +def test_truediv_py_scalar() -> None: + """Test pd.Series[Any] / Python native scalars""" + i, f, c = 1, 1.0, 1j + + check(assert_type(left / i, pd.Series), pd.Series) + check(assert_type(left / f, pd.Series), pd.Series) + check(assert_type(left / c, pd.Series), pd.Series) + + check(assert_type(i / left, pd.Series), pd.Series) + check(assert_type(f / left, pd.Series), pd.Series) + check(assert_type(c / left, pd.Series), pd.Series) + + check(assert_type(left.truediv(i), pd.Series), pd.Series) + check(assert_type(left.truediv(f), pd.Series), pd.Series) + check(assert_type(left.truediv(c), pd.Series), pd.Series) + + check(assert_type(left.div(i), pd.Series), pd.Series) + check(assert_type(left.div(f), pd.Series), pd.Series) + check(assert_type(left.div(c), pd.Series), pd.Series) + + check(assert_type(left.rtruediv(i), pd.Series), pd.Series) + check(assert_type(left.rtruediv(f), pd.Series), pd.Series) + check(assert_type(left.rtruediv(c), pd.Series), pd.Series) + + check(assert_type(left.rdiv(i), pd.Series), pd.Series) + check(assert_type(left.rdiv(f), pd.Series), pd.Series) + check(assert_type(left.rdiv(c), pd.Series), pd.Series) + + +def test_truediv_py_sequence() -> None: + """Test pd.Series[Any] / Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left / i, pd.Series), pd.Series) + check(assert_type(left / f, pd.Series), pd.Series) + check(assert_type(left / c, pd.Series), pd.Series) + + check(assert_type(i / left, pd.Series), pd.Series) + check(assert_type(f / left, pd.Series), pd.Series) + check(assert_type(c / left, pd.Series), pd.Series) + + check(assert_type(left.truediv(i), pd.Series), pd.Series) + check(assert_type(left.truediv(f), pd.Series), pd.Series) + check(assert_type(left.truediv(c), pd.Series), pd.Series) + + check(assert_type(left.div(i), pd.Series), pd.Series) + check(assert_type(left.div(f), pd.Series), pd.Series) + check(assert_type(left.div(c), pd.Series), pd.Series) + + check(assert_type(left.rtruediv(i), pd.Series), pd.Series) + check(assert_type(left.rtruediv(f), pd.Series), pd.Series) + check(assert_type(left.rtruediv(c), pd.Series), pd.Series) + + check(assert_type(left.rdiv(i), pd.Series), pd.Series) + check(assert_type(left.rdiv(f), pd.Series), pd.Series) + check(assert_type(left.rdiv(c), pd.Series), pd.Series) + + +def test_truediv_numpy_array() -> None: + """Test pd.Series[Any] / numpy array""" + i = np.array([2, 3, 5], np.int64) + f = np.array([1.0, 2.0, 3.0], np.float64) + c = np.array([1.1j, 2.2j, 4.1j], np.complex64) + + check(assert_type(left / i, pd.Series), pd.Series) + check(assert_type(left / f, pd.Series), pd.Series) + check(assert_type(left / c, pd.Series), pd.Series) + + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i / left, pd.Series # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + ) + check( + assert_type( # type: ignore[assert-type] + f / left, pd.Series # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + ) + check( + assert_type( # type: ignore[assert-type] + c / left, pd.Series # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + ) + + check(assert_type(left.truediv(i), pd.Series), pd.Series) + check(assert_type(left.truediv(f), pd.Series), pd.Series) + check(assert_type(left.truediv(c), pd.Series), pd.Series) + + check(assert_type(left.div(i), pd.Series), pd.Series) + check(assert_type(left.div(f), pd.Series), pd.Series) + check(assert_type(left.div(c), pd.Series), pd.Series) + + check(assert_type(left.rtruediv(i), pd.Series), pd.Series) + check(assert_type(left.rtruediv(f), pd.Series), pd.Series) + check(assert_type(left.rtruediv(c), pd.Series), pd.Series) + + check(assert_type(left.rdiv(i), pd.Series), pd.Series) + check(assert_type(left.rdiv(f), pd.Series), pd.Series) + check(assert_type(left.rdiv(c), pd.Series), pd.Series) + + +def test_truediv_pd_series() -> None: + """Test pd.Series[Any] / pandas series""" + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + check(assert_type(left / i, pd.Series), pd.Series) + check(assert_type(left / f, pd.Series), pd.Series) + check(assert_type(left / c, pd.Series), pd.Series) + + check(assert_type(i / left, pd.Series), pd.Series) + check(assert_type(f / left, pd.Series), pd.Series) + check(assert_type(c / left, pd.Series), pd.Series) + + check(assert_type(left.truediv(i), pd.Series), pd.Series) + check(assert_type(left.truediv(f), pd.Series), pd.Series) + check(assert_type(left.truediv(c), pd.Series), pd.Series) + + check(assert_type(left.div(i), pd.Series), pd.Series) + check(assert_type(left.div(f), pd.Series), pd.Series) + check(assert_type(left.div(c), pd.Series), pd.Series) + + check(assert_type(left.rtruediv(i), pd.Series), pd.Series) + check(assert_type(left.rtruediv(f), pd.Series), pd.Series) + check(assert_type(left.rtruediv(c), pd.Series), pd.Series) + + check(assert_type(left.rdiv(i), pd.Series), pd.Series) + check(assert_type(left.rdiv(f), pd.Series), pd.Series) + check(assert_type(left.rdiv(c), pd.Series), pd.Series) diff --git a/tests/test_series.py b/tests/series/test_series.py similarity index 99% rename from tests/test_series.py rename to tests/series/test_series.py index 1e48aae7..3fc7d1d2 100644 --- a/tests/test_series.py +++ b/tests/series/test_series.py @@ -821,9 +821,7 @@ def test_types_element_wise_arithmetic() -> None: # check(assert_type(s.mul(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) check(assert_type(s.mul(s2, fill_value=0), pd.Series), pd.Series, np.integer) - # TODO these two below should type pd.Series[float] - # check(assert_type(s / s2, "pd.Series[float]"), pd.Series, np.float64) - check(assert_type(s / s2, pd.Series), pd.Series, np.float64) + check(assert_type(s / s2, "pd.Series[float]"), pd.Series, np.float64) check( assert_type(s.div(s2, fill_value=0), "pd.Series[float]"), pd.Series, np.float64 )