diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index c57123f4..5b0e5be9 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2032,11 +2032,424 @@ class Series(IndexOpsMixin[S1], NDFrame): self, other: S1 | _ListLike | Series[S1] | datetime | timedelta | date ) -> Series[_bool]: ... @overload + def __mul__(self: Series[Never], other: complex | _ListLike | Series) -> Series: ... + @overload + def __mul__(self, other: Series[Never]) -> Series: ... # type: ignore[overload-overlap] + @overload + def __mul__( + self: Series[bool], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + ) -> Series[_T_COMPLEX]: ... + @overload + def __mul__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... + @overload + def __mul__(self: Series[bool], other: np_ndarray_anyint) -> Series[int]: ... + @overload + def __mul__(self: Series[bool], other: np_ndarray_float) -> Series[float]: ... + @overload + def __mul__(self: Series[bool], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __mul__( + self: Series[int], + other: ( + bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + ), + ) -> Series[int]: ... + @overload + def __mul__( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + ) -> Series[_T_COMPLEX]: ... + @overload + def __mul__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... + @overload + def __mul__(self: Series[int], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __mul__( + self: Series[float], + other: ( + _T_INT + | Sequence[_T_INT] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Series[_T_INT] + ), + ) -> Series[float]: ... + @overload + def __mul__( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + ) -> Series[_T_COMPLEX]: ... + @overload + def __mul__(self: Series[float], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __mul__( + self: Series[complex], + other: ( + Sequence[_T_COMPLEX] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + ) -> Series[complex]: ... + @overload def __mul__( self, other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64 ) -> TimedeltaSeries: ... @overload - def __mul__(self, other: num | _ListLike | Series) -> Series: ... + def __mul__(self, other: S1 | Series[S1]) -> Self: ... + @overload + def mul( + self: Series[Never], + other: complex | _ListLike | Series, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series: ... + @overload + def mul( + self: Series[bool], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[_T_COMPLEX]: ... + @overload + def mul( + self: Series[bool], + other: np_ndarray_bool, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[bool]: ... + @overload + def mul( + self: Series[bool], + other: np_ndarray_anyint, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[int]: ... + @overload + def mul( + self: Series[bool], + other: np_ndarray_float, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[float]: ... + @overload + def mul( + self: Series[bool], + other: np_ndarray_complex, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def mul( + self: Series[int], + other: ( + bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[int]: ... + @overload + def mul( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[_T_COMPLEX]: ... + @overload + def mul( + self: Series[int], + other: np_ndarray_float, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[float]: ... + @overload + def mul( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def mul( + self: Series[float], + other: ( + _T_INT + | Sequence[_T_INT] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Series[_T_INT] + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[float]: ... + @overload + def mul( + self, + other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex | None = 0, + ) -> TimedeltaSeries: ... + @overload + def mul( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[_T_COMPLEX]: ... + @overload + def mul( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def mul( + self: Series[complex], + other: ( + Sequence[_T_COMPLEX] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def mul( + self, + other: S1 | Series[S1], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Self: ... + @overload + def __rmul__(self: Series[Never], other: complex | _ListLike) -> Series: ... + @overload + def __rmul__( + self: Series[bool], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload + def __rmul__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... + @overload + def __rmul__(self: Series[bool], other: np_ndarray_anyint) -> Series[int]: ... + @overload + def __rmul__(self: Series[bool], other: np_ndarray_float) -> Series[float]: ... + @overload + def __rmul__(self: Series[bool], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __rmul__( + self: Series[int], + other: bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint, + ) -> Series[int]: ... + @overload + def __rmul__( + self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload + def __rmul__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... + @overload + def __rmul__(self: Series[int], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __rmul__( + self: Series[float], + other: ( + _T_INT + | Sequence[_T_INT] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + ), + ) -> Series[float]: ... + @overload + def __rmul__( + self: Series[float], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload + def __rmul__(self: Series[float], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __rmul__( + self: Series[complex], + other: ( + np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Sequence[_T_COMPLEX] + ), + ) -> Series[complex]: ... + @overload + def __rmul__( + self, other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64 + ) -> TimedeltaSeries: ... + @overload + def __rmul__(self, other: S1) -> Self: ... + @overload + def rmul( + self: Series[Never], + other: complex | _ListLike | Series, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series: ... + @overload + def rmul( + self: Series[bool], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[_T_COMPLEX]: ... + @overload + def rmul( + self: Series[bool], + other: np_ndarray_bool, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[bool]: ... + @overload + def rmul( + self: Series[bool], + other: np_ndarray_anyint, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[int]: ... + @overload + def rmul( + self: Series[bool], + other: np_ndarray_float, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[float]: ... + @overload + def rmul( + self: Series[bool], + other: np_ndarray_complex, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def rmul( + self: Series[int], + other: ( + bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[int]: ... + @overload + def rmul( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[_T_COMPLEX]: ... + @overload + def rmul( + self: Series[int], + other: np_ndarray_float, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[float]: ... + @overload + def rmul( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def rmul( + self: Series[float], + other: ( + _T_INT + | Sequence[_T_INT] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Series[_T_INT] + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[float]: ... + @overload + def rmul( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[_T_COMPLEX]: ... + @overload + def rmul( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def rmul( + self: Series[complex], + other: ( + Sequence[_T_COMPLEX] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload + def rmul( + self, + other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex = ..., + ) -> TimedeltaSeries: ... + @overload + def rmul( + self, + other: S1 | Series[S1], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Self: ... def __mod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... def __ne__(self, other: object) -> Series[_bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] def __pow__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... @@ -2057,12 +2470,6 @@ class Series(IndexOpsMixin[S1], NDFrame): def __rdivmod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] def __rfloordiv__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... def __rmod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... - @overload - def __rmul__( - self, other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64 - ) -> TimedeltaSeries: ... - @overload - def __rmul__(self, other: num | _ListLike | Series) -> Series: ... def __rpow__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] @@ -2793,29 +3200,6 @@ class Series(IndexOpsMixin[S1], NDFrame): fill_value: float | None = None, axis: AxisIndex | None = 0, ) -> Series[S1]: ... - @overload - def mul( - self, - other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, - level: Level | None = ..., - fill_value: float | None = None, - axis: AxisIndex | None = 0, - ) -> TimedeltaSeries: ... - @overload - def mul( - self, - other: num | _ListLike | Series, - level: Level | None = ..., - fill_value: float | None = None, - axis: AxisIndex | None = 0, - ) -> Series: ... - def multiply( - self, - other: num | _ListLike | Series[S1], - level: Level | None = ..., - fill_value: float | None = None, - axis: AxisIndex | None = 0, - ) -> Series[S1]: ... def ne( self, other: Scalar | Series[S1], @@ -2870,22 +3254,6 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: AxisIndex = ..., ) -> Series[S1]: ... @overload - def rmul( - self, - other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, - level: Level | None = ..., - fill_value: float | None = None, - axis: AxisIndex = ..., - ) -> TimedeltaSeries: ... - @overload - def rmul( - self, - other: num | _ListLike | Series, - level: Level | None = ..., - fill_value: float | None = None, - axis: AxisIndex = ..., - ) -> Series: ... - @overload def rolling( self, window: int | _str | timedelta | BaseOffset | BaseIndexer, diff --git a/tests/series/arithmetic/bool/test_mul.py b/tests/series/arithmetic/bool/test_mul.py new file mode 100644 index 00000000..0728b6e8 --- /dev/null +++ b/tests/series/arithmetic/bool/test_mul.py @@ -0,0 +1,129 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.Series([True, True, False]) # left operand + + +def test_mul_py_scalar() -> None: + """Test pd.Series[bool] * Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left * b, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_py_sequence() -> None: + """Test pd.Series[bool] * Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left * b, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_numpy_array() -> None: + """Test pd.Series[bool] * numpy array""" + b = np.array([True, False, True], np.bool_) + 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 * b, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rmul__` cannot override. At runtime, they return + # `Series`s with the correct element type. + check(assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series, np.bool_) + check(assert_type(i * left, "npt.NDArray[np.int64]"), pd.Series, np.integer) + check(assert_type(f * left, "npt.NDArray[np.float64]"), pd.Series, np.floating) + check( + assert_type(c * left, "npt.NDArray[np.complex128]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.mul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_pd_series() -> None: + """Test pd.Series[bool] * pandas series""" + b = pd.Series([True, False, True]) + 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 * b, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/complex/test_mul.py b/tests/series/arithmetic/complex/test_mul.py new file mode 100644 index 00000000..d89c7654 --- /dev/null +++ b/tests/series/arithmetic/complex/test_mul.py @@ -0,0 +1,155 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.Series([1j, 2j, 3j]) # left operand + + +def test_mul_py_scalar() -> None: + """Test pd.Series[complex] * Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left * b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(i * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(f * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.rmul(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_py_sequence() -> None: + """Test pd.Series[complex] * Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left * b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(i * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(f * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.rmul(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_numpy_array() -> None: + """Test pd.Series[complex] * numpy array""" + b = np.array([True, False, True], np.bool_) + 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 * b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rmul__` cannot override. At runtime, they return + # `Series`s with the correct element type. + check(assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series, np.complexfloating) + check(assert_type(i * left, "npt.NDArray[np.int64]"), pd.Series, np.complexfloating) + check( + assert_type(f * left, "npt.NDArray[np.float64]"), pd.Series, np.complexfloating + ) + check( + assert_type(c * left, "npt.NDArray[np.complex128]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.mul(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.rmul(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_pd_series() -> None: + """Test pd.Series[complex] * pandas series""" + b = pd.Series([True, False, True]) + 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 * b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(i * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(f * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.rmul(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/float/test_mul.py b/tests/series/arithmetic/float/test_mul.py new file mode 100644 index 00000000..80cb8aa6 --- /dev/null +++ b/tests/series/arithmetic/float/test_mul.py @@ -0,0 +1,129 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +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_mul_py_scalar() -> None: + """Test pd.Series[float] * Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left * b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_py_sequence() -> None: + """Test pd.Series[float] * Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left * b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_numpy_array() -> None: + """Test pd.Series[float] * numpy array""" + b = np.array([True, False, True], np.bool_) + 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 * b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rmul__` cannot override. At runtime, they return + # `Series`s with the correct element type. + check(assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series, np.floating) + check(assert_type(i * left, "npt.NDArray[np.int64]"), pd.Series, np.floating) + check(assert_type(f * left, "npt.NDArray[np.float64]"), pd.Series, np.floating) + check( + assert_type(c * left, "npt.NDArray[np.complex128]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.mul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_pd_series() -> None: + """Test pd.Series[float] * pandas series""" + b = pd.Series([True, False, True]) + 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 * b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/int/test_mul.py b/tests/series/arithmetic/int/test_mul.py new file mode 100644 index 00000000..028829b7 --- /dev/null +++ b/tests/series/arithmetic/int/test_mul.py @@ -0,0 +1,129 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.Series([1, 2, 3]) # left operand + + +def test_mul_py_scalar() -> None: + """Test pd.Series[int] * Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left * b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_py_sequence() -> None: + """Test pd.Series[int] * Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left * b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_numpy_array() -> None: + """Test pd.Series[int] * numpy array""" + b = np.array([True, False, True], np.bool_) + 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 * b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rmul__` cannot override. At runtime, they return + # `Series`s with the correct element type. + check(assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series, np.integer) + check(assert_type(i * left, "npt.NDArray[np.int64]"), pd.Series, np.integer) + check(assert_type(f * left, "npt.NDArray[np.float64]"), pd.Series, np.floating) + check( + assert_type(c * left, "npt.NDArray[np.complex128]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.mul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + +def test_mul_pd_series() -> None: + """Test pd.Series[int] * pandas series""" + b = pd.Series([True, False, True]) + 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 * b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/test_mul.py b/tests/series/arithmetic/test_mul.py new file mode 100644 index 00000000..00ffe068 --- /dev/null +++ b/tests/series/arithmetic/test_mul.py @@ -0,0 +1,127 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +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_mul_py_scalar() -> None: + """Test pd.Series[Any] * Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left * b, pd.Series), pd.Series) + 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(b * left, 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.mul(b), pd.Series), pd.Series) + check(assert_type(left.mul(i), pd.Series), pd.Series) + check(assert_type(left.mul(f), pd.Series), pd.Series) + check(assert_type(left.mul(c), pd.Series), pd.Series) + + check(assert_type(left.rmul(b), pd.Series), pd.Series) + check(assert_type(left.rmul(i), pd.Series), pd.Series) + check(assert_type(left.rmul(f), pd.Series), pd.Series) + check(assert_type(left.rmul(c), pd.Series), pd.Series) + + +def test_mul_py_sequence() -> None: + """Test pd.Series[Any] * Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left * b, pd.Series), pd.Series) + 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) + + # `mypy` thinks the return types are `list[_T]` + check(assert_type(b * left, pd.Series), pd.Series) # type: ignore[assert-type] + check(assert_type(i * left, pd.Series), pd.Series) # type: ignore[assert-type] + check(assert_type(f * left, pd.Series), pd.Series) # type: ignore[assert-type] + check(assert_type(c * left, pd.Series), pd.Series) # type: ignore[assert-type] + + check(assert_type(left.mul(b), pd.Series), pd.Series) + check(assert_type(left.mul(i), pd.Series), pd.Series) + check(assert_type(left.mul(f), pd.Series), pd.Series) + check(assert_type(left.mul(c), pd.Series), pd.Series) + + check(assert_type(left.rmul(b), pd.Series), pd.Series) + check(assert_type(left.rmul(i), pd.Series), pd.Series) + check(assert_type(left.rmul(f), pd.Series), pd.Series) + check(assert_type(left.rmul(c), pd.Series), pd.Series) + + +def test_mul_numpy_array() -> None: + """Test pd.Series[Any] * numpy array""" + b = np.array([True, False, True], np.bool_) + 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 * b, pd.Series), pd.Series) + 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 the corresponding `ndarray`s in the static type + # checking, where our `__rmul__` cannot override. At runtime, they return + # `Series`s. + # `mypy` thinks the return types are `Any`, which is a bug. + check( + assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series # type: ignore[assert-type] + ) + check( + assert_type(i * left, "npt.NDArray[np.int64]"), pd.Series # type: ignore[assert-type] + ) + check( + assert_type(f * left, "npt.NDArray[np.float64]"), pd.Series # type: ignore[assert-type] + ) + check( + assert_type(c * left, "npt.NDArray[np.complex128]"), pd.Series # type: ignore[assert-type] + ) + + check(assert_type(left.mul(b), pd.Series), pd.Series) + check(assert_type(left.mul(i), pd.Series), pd.Series) + check(assert_type(left.mul(f), pd.Series), pd.Series) + check(assert_type(left.mul(c), pd.Series), pd.Series) + + check(assert_type(left.rmul(b), pd.Series), pd.Series) + check(assert_type(left.rmul(i), pd.Series), pd.Series) + check(assert_type(left.rmul(f), pd.Series), pd.Series) + check(assert_type(left.rmul(c), pd.Series), pd.Series) + + +def test_mul_pd_series() -> None: + """Test pd.Series[Any] * pandas series""" + b = pd.Series([True, False, True]) + 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 * b, pd.Series), pd.Series) + 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(b * left, 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.mul(b), pd.Series), pd.Series) + check(assert_type(left.mul(i), pd.Series), pd.Series) + check(assert_type(left.mul(f), pd.Series), pd.Series) + check(assert_type(left.mul(c), pd.Series), pd.Series) + + check(assert_type(left.rmul(b), pd.Series), pd.Series) + check(assert_type(left.rmul(i), pd.Series), pd.Series) + check(assert_type(left.rmul(f), pd.Series), pd.Series) + check(assert_type(left.rmul(c), pd.Series), pd.Series) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index 250a0e5e..8df9c123 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -815,20 +815,12 @@ def test_types_element_wise_arithmetic() -> None: s = pd.Series([0, 1, -10]) s2 = pd.Series([7, -5, 10]) - check(assert_type(s + s2, "pd.Series[int]"), pd.Series, np.integer) check(assert_type(s.add(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) - # TODO this one below should type pd.Series[int] - check(assert_type(s - s2, "pd.Series[int]"), pd.Series, np.integer) check(assert_type(s.sub(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) - # TODO these two below should type pd.Series[int] - # check(assert_type(s * s2, "pd.Series[int]"), pd.Series, np.integer ) - check(assert_type(s * s2, pd.Series), pd.Series, np.integer) - # 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) + check(assert_type(s.mul(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) - 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 ) @@ -1638,18 +1630,6 @@ def test_series_multiindex_getitem() -> None: s1: pd.Series = s["a", :] -def test_series_mul() -> None: - s = pd.Series([1, 2, 3]) - sm = s * 4 - check(assert_type(sm, pd.Series), pd.Series) - ss = s - 4 - check(assert_type(ss, "pd.Series[int]"), pd.Series, np.integer) - sm2 = s * s - check(assert_type(sm2, pd.Series), pd.Series) - sp = s + 4 - check(assert_type(sp, "pd.Series[int]"), pd.Series, np.integer) - - def test_reset_index() -> None: s = pd.Series( [1, 2, 3, 4],