Skip to content

Commit 01d597f

Browse files
authored
feat(arithmetic): #1347 #1378 ➗ truediv (#1431)
* refactor: truediv * feat: truediv for index[bool] * TimedeltaIndex * TimedeltaIndex * feat: truediv, also pandas-dev/pandas#62712 * Index[Any] * Index[complex] * mypy fails * mypy unhappy * mypy happiness * mypy happiness * pyright unhappy * propagate pandas-dev/pandas#62229 * comments * remove Index[Timedelta] and be independent of pandas-dev/pandas#62524
1 parent 6c5d850 commit 01d597f

38 files changed

+1299
-561
lines changed

pandas-stubs/_libs/tslibs/period.pyi

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ class Period(PeriodMixin):
9191
def __add__(self, other: _PeriodAddSub) -> Self: ...
9292
@overload
9393
def __add__(self, other: NaTType) -> NaTType: ...
94-
@overload
95-
def __add__(self, other: Index) -> PeriodIndex: ...
9694
# Ignored due to indecipherable error from mypy:
9795
# Forward operator "__add__" is not callable [misc]
9896
if sys.version_info >= (3, 11):
@@ -104,12 +102,6 @@ class Period(PeriodMixin):
104102

105103
@overload
106104
def __radd__(self, other: NaTType) -> NaTType: ...
107-
# Real signature is -> PeriodIndex, but conflicts with Index.__add__
108-
# Changing Index is very hard due to Index inheritance
109-
# Signatures of "__radd__" of "Period" and "__add__" of "Index"
110-
# are unsafely overlapping
111-
@overload
112-
def __radd__(self, other: Index) -> PeriodIndex: ...
113105
# ignore[misc] here because we know all other comparisons
114106
# are False, so we use Literal[False]
115107
@overload

pandas-stubs/_libs/tslibs/timedeltas.pyi

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ from typing import (
1313
)
1414

1515
import numpy as np
16+
from numpy import typing as npt
1617
from pandas.core.indexes.base import Index
1718
from pandas.core.indexes.datetimes import DatetimeIndex
1819
from pandas.core.indexes.period import PeriodIndex
@@ -30,7 +31,6 @@ from pandas._typing import (
3031
TimeUnit,
3132
np_1darray,
3233
np_ndarray,
33-
npt,
3434
)
3535

3636
class Components(NamedTuple):
@@ -250,22 +250,24 @@ class Timedelta(timedelta):
250250
) -> np_ndarray[ShapeT, np.int_]: ...
251251
# Override due to more types supported than timedelta
252252
@overload # type: ignore[override]
253-
def __truediv__(self, other: timedelta | Timedelta | NaTType) -> float: ...
253+
# pyrefly: ignore[bad-override]
254+
def __truediv__(self, other: Just[int] | Just[float]) -> Self: ...
254255
@overload
255-
def __truediv__(self, other: float) -> Self: ...
256+
def __truediv__(self, other: Self | NaTType) -> float: ...
256257
@overload
257258
def __truediv__(
258259
self, other: np_ndarray[ShapeT, np.integer | np.floating]
259260
) -> np_ndarray[ShapeT, np.timedelta64]: ...
260261
@overload
261-
def __truediv__(self, other: Series[Timedelta]) -> Series[float]: ...
262-
@overload
263-
def __truediv__(self, other: Series[int]) -> Series[Timedelta]: ...
262+
def __truediv__(
263+
self, other: np_ndarray[ShapeT, np.timedelta64]
264+
) -> np_ndarray[ShapeT, np.floating]: ...
264265
@overload
265-
def __truediv__(self, other: Series[float]) -> Series[Timedelta]: ...
266+
def __rtruediv__(self, other: Self | NaTType) -> float: ...
266267
@overload
267-
def __truediv__(self, other: Index[int] | Index[float]) -> TimedeltaIndex: ...
268-
def __rtruediv__(self, other: timedelta | Timedelta | NaTType) -> float: ...
268+
def __rtruediv__(
269+
self, other: np_ndarray[ShapeT, np.timedelta64]
270+
) -> np_ndarray[ShapeT, np.floating]: ...
269271
# Override due to more types supported than timedelta
270272
@overload
271273
def __eq__(self, other: timedelta | np.timedelta64 | Self) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]

pandas-stubs/_libs/tslibs/timestamps.pyi

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ from typing import (
1818
)
1919

2020
import numpy as np
21-
from pandas import (
22-
DatetimeIndex,
23-
TimedeltaIndex,
24-
)
2521
from pandas.core.indexes.base import Index
22+
from pandas.core.indexes.datetimes import DatetimeIndex
23+
from pandas.core.indexes.timedeltas import TimedeltaIndex
2624
from pandas.core.series import Series
2725
from typing_extensions import (
2826
Never,
@@ -99,10 +97,9 @@ class Timestamp(datetime, SupportsIndex):
9997
def tz(self) -> _tzinfo | None: ...
10098
@property
10199
def fold(self) -> int: ...
102-
103100
if sys.version_info >= (3, 12):
104101
@classmethod
105-
def fromtimestamp( # pyright: ignore[reportIncompatibleMethodOverride] # pyrefly: ignore
102+
def fromtimestamp( # pyright: ignore[reportIncompatibleMethodOverride]
106103
cls, t: float, tz: _tzinfo | str | None = ...
107104
) -> Self: ...
108105
else:

pandas-stubs/_typing.pyi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ from typing import (
2525
overload,
2626
)
2727

28+
from _typeshed import _T_contra
2829
import numpy as np
2930
from numpy import typing as npt
3031
import pandas as pd
@@ -860,6 +861,9 @@ np_ndarray_td: TypeAlias = npt.NDArray[np.timedelta64]
860861
# Define shape and generic type variables with defaults similar to numpy
861862
GenericT = TypeVar("GenericT", bound=np.generic, default=Any)
862863
GenericT_co = TypeVar("GenericT_co", bound=np.generic, default=Any, covariant=True)
864+
GenericT_contra = TypeVar(
865+
"GenericT_contra", bound=np.generic, default=Any, contravariant=True
866+
)
863867
ShapeT = TypeVar("ShapeT", bound=tuple[int, ...], default=tuple[Any, ...])
864868
# Numpy ndarray with more ergonomic typevar
865869
np_ndarray: TypeAlias = np.ndarray[ShapeT, np.dtype[GenericT]]
@@ -1114,4 +1118,10 @@ class Just(Protocol, Generic[T]):
11141118
@override
11151119
def __class__(self, t: type[T], /) -> None: ...
11161120

1121+
class SupportsTrueDiv(Protocol[_T_contra, _T_co]):
1122+
def __truediv__(self, x: _T_contra, /) -> _T_co: ...
1123+
1124+
class SupportsRTrueDiv(Protocol[_T_contra, _T_co]):
1125+
def __rtruediv__(self, x: _T_contra, /) -> _T_co: ...
1126+
11171127
__all__ = ["npt", "type_t"]

pandas-stubs/core/base.pyi

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ from collections.abc import (
33
Iterator,
44
Sequence,
55
)
6+
from datetime import timedelta
67
from typing import (
78
Any,
89
Generic,
@@ -175,7 +176,6 @@ NumListLike: TypeAlias = (
175176
| np_ndarray_complex
176177
| dict[str, np.ndarray]
177178
| Sequence[complex]
178-
| IndexOpsMixin[complex]
179179
)
180180

181181
@type_check_only
@@ -266,6 +266,38 @@ class ElementOpsMixin(Generic[S2]):
266266
def _proto_rmul(
267267
self: ElementOpsMixin[str], other: Just[int] | np.integer
268268
) -> ElementOpsMixin[str]: ...
269+
@overload
270+
def _proto_truediv(
271+
self: ElementOpsMixin[int], other: int | np.integer
272+
) -> ElementOpsMixin[float]: ...
273+
@overload
274+
def _proto_truediv(
275+
self: ElementOpsMixin[float], other: float | np.floating
276+
) -> ElementOpsMixin[float]: ...
277+
@overload
278+
def _proto_truediv(
279+
self: ElementOpsMixin[complex], other: complex | np.complexfloating
280+
) -> ElementOpsMixin[complex]: ...
281+
@overload
282+
def _proto_truediv(
283+
self: ElementOpsMixin[Timedelta], other: timedelta | Timedelta | np.timedelta64
284+
) -> ElementOpsMixin[float]: ...
285+
@overload
286+
def _proto_rtruediv(
287+
self: ElementOpsMixin[int], other: int | np.integer
288+
) -> ElementOpsMixin[float]: ...
289+
@overload
290+
def _proto_rtruediv(
291+
self: ElementOpsMixin[float], other: float | np.floating
292+
) -> ElementOpsMixin[float]: ...
293+
@overload
294+
def _proto_rtruediv(
295+
self: ElementOpsMixin[complex], other: complex | np.complexfloating
296+
) -> ElementOpsMixin[complex]: ...
297+
@overload
298+
def _proto_rtruediv(
299+
self: ElementOpsMixin[Timedelta], other: timedelta | Timedelta | np.timedelta64
300+
) -> ElementOpsMixin[float]: ...
269301

270302
@type_check_only
271303
class Supports_ProtoAdd(Protocol[_T_contra, S2]):
@@ -282,3 +314,11 @@ class Supports_ProtoMul(Protocol[_T_contra, S2]):
282314
@type_check_only
283315
class Supports_ProtoRMul(Protocol[_T_contra, S2]):
284316
def _proto_rmul(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ...
317+
318+
@type_check_only
319+
class Supports_ProtoTrueDiv(Protocol[_T_contra, S2]):
320+
def _proto_truediv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ...
321+
322+
@type_check_only
323+
class Supports_ProtoRTrueDiv(Protocol[_T_contra, S2]):
324+
def _proto_rtruediv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ...

0 commit comments

Comments
 (0)