Skip to content

Commit dbe65e4

Browse files
committed
Merge branch 'main' into hotfix/cmp0xff/gh718-drop-tss-tds
2 parents 3df8ea0 + 8e5c754 commit dbe65e4

File tree

153 files changed

+13052
-3572
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+13052
-3572
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repos:
1111
hooks:
1212
- id: isort
1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.12.3
14+
rev: v0.12.10
1515
hooks:
1616
- id: ruff-check
1717
args: [

docs/philosophy.md

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ the following example that creates two series of datetimes with corresponding ar
3737

3838
```python
3939
import pandas as pd
40+
from typing import reveal_type
4041

4142
s1 = pd.Series(pd.to_datetime(["2022-05-01", "2022-06-01"]))
4243
reveal_type(s1)
@@ -45,26 +46,61 @@ reveal_type(s2)
4546
td = s1 - s2
4647
reveal_type(td)
4748
ssum = s1 + s2
48-
reveal_type(ssum)
4949
```
5050

51-
The above code (without the `reveal_type()` statements) will get a `Never`
52-
on the computation of `ssum` because it is
51+
The above code (without the `reveal_type()` statements) will get an error on the computation of `ssum` because it is
5352
inappropriate to add two series containing `Timestamp` values. The types will be
54-
revealed as follows:
53+
revealed by `mypy` as follows:
5554

5655
```text
57-
ttest.py:4: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]"
58-
ttest.py:6: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]"
59-
ttest.py:8: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timedeltas.Timedelta]"
60-
ttest.py:9: error: Need type annotation for "ssum" [var-annotated]
61-
ttest.py:10: note: Revealed type is "Never"
56+
ttest.py:5: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]"
57+
ttest.py:7: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]"
58+
ttest.py:9: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timedelta]"
59+
ttest.py:10: error: Unsupported operand types for + ("Series[Timestamp]" and "Series[Timestamp]") [operator]
6260
```
6361

6462
The type `Series[Timestamp]` is the result of creating a series from `pd.to_datetime()`, while
6563
the type `Series[Timedelta]` is the result of subtracting two `Series[Timestamp]` as well as
6664
the result of `pd.to_timedelta()`.
6765

66+
### Progressive arithmetic typing for generic Series
67+
68+
Consider the following Series from a DataFrame:
69+
70+
```python
71+
import pandas as pd
72+
from typing_extensions import reveal_type
73+
74+
75+
frame = pd.DataFrame({"timestamp": [pd.Timestamp(2025, 9, 15)], "tag": ["one"], "value": [1.0]})
76+
values = frame["value"]
77+
reveal_type(values) # type checker: Series[Any], runtime: Series
78+
new_values = values + 2
79+
80+
timestamps = frame["timestamp"]
81+
reveal_type(timestamps - pd.Timestamp(2025, 7, 12)) # type checker: TimedeltaSeries, runtime: Series
82+
83+
tags = frame["tag"]
84+
reveal_type("suffix" + tags) # type checker: Series[str], runtime: Series
85+
```
86+
87+
Since these Series are taken from a DataFrame, all three of them, `values`, `timestamps`
88+
and `tags`, are recognized by type checkers as `Series[Any]`. The code snippet
89+
runs fine at runtime. In the stub for type checking, when there is only one
90+
valid outcome, we provide the typing of this outcome as the result. For
91+
example, if a `Timestamp` is subtracted from a `Series[Any]`, or a `str`
92+
is added to a `Series[Any]`, valid outcomes can only be `TimedeltaSeries` and
93+
`Series[str]`, respectively, which will be realized when the left operands
94+
are actually `Series[Timestamp]` and `Series[str]`, respectively.
95+
96+
Note that static type checkers cannot determine the contents of a `Series[Any]`
97+
at runtime. Users are invited to verify the results provided progressivly by the
98+
type checkers and be warned if they are unreasonable.
99+
100+
When there are several possible valid outcomes of an arithmetic expression,
101+
for example numeric types `Series[bool]`, `Series[int]`, etc., `Series[Any]`
102+
will be given as the resulting type of the arithmetic operation.
103+
68104
### Interval is Generic
69105

70106
A pandas `Interval` can be a time interval, an interval of integers, or an interval of

pandas-stubs/__init__.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ from pandas.io.api import (
119119
read_stata as read_stata,
120120
read_table as read_table,
121121
read_xml as read_xml,
122-
to_pickle as to_pickle,
123122
)
124123
from pandas.io.json._normalize import json_normalize as json_normalize
125124
from pandas.tseries import offsets as offsets

pandas-stubs/_libs/interval.pyi

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ from pandas import (
1717
from pandas._typing import (
1818
IntervalClosedType,
1919
IntervalT,
20-
np_ndarray_bool,
20+
np_1darray,
2121
npt,
2222
)
2323

@@ -166,7 +166,9 @@ class Interval(IntervalMixin, Generic[_OrderableT]):
166166
@overload
167167
def __gt__(self, other: Interval[_OrderableT]) -> bool: ...
168168
@overload
169-
def __gt__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ...
169+
def __gt__(
170+
self: IntervalT, other: IntervalIndex[IntervalT]
171+
) -> np_1darray[np.bool]: ...
170172
@overload
171173
def __gt__(
172174
self,
@@ -175,7 +177,9 @@ class Interval(IntervalMixin, Generic[_OrderableT]):
175177
@overload
176178
def __lt__(self, other: Interval[_OrderableT]) -> bool: ...
177179
@overload
178-
def __lt__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ...
180+
def __lt__(
181+
self: IntervalT, other: IntervalIndex[IntervalT]
182+
) -> np_1darray[np.bool]: ...
179183
@overload
180184
def __lt__(
181185
self,
@@ -184,7 +188,9 @@ class Interval(IntervalMixin, Generic[_OrderableT]):
184188
@overload
185189
def __ge__(self, other: Interval[_OrderableT]) -> bool: ...
186190
@overload
187-
def __ge__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ...
191+
def __ge__(
192+
self: IntervalT, other: IntervalIndex[IntervalT]
193+
) -> np_1darray[np.bool]: ...
188194
@overload
189195
def __ge__(
190196
self,
@@ -193,19 +199,25 @@ class Interval(IntervalMixin, Generic[_OrderableT]):
193199
@overload
194200
def __le__(self, other: Interval[_OrderableT]) -> bool: ...
195201
@overload
196-
def __le__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ...
202+
def __le__(
203+
self: IntervalT, other: IntervalIndex[IntervalT]
204+
) -> np_1darray[np.bool]: ...
197205
@overload
198206
def __eq__(self, other: Interval[_OrderableT]) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
199207
@overload
200-
def __eq__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ...
208+
def __eq__(
209+
self: IntervalT, other: IntervalIndex[IntervalT]
210+
) -> np_1darray[np.bool]: ...
201211
@overload
202212
def __eq__(self, other: Series[_OrderableT]) -> Series[bool]: ... # type: ignore[overload-overlap]
203213
@overload
204214
def __eq__(self, other: object) -> Literal[False]: ...
205215
@overload
206216
def __ne__(self, other: Interval[_OrderableT]) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
207217
@overload
208-
def __ne__(self: IntervalT, other: IntervalIndex[IntervalT]) -> np_ndarray_bool: ...
218+
def __ne__(
219+
self: IntervalT, other: IntervalIndex[IntervalT]
220+
) -> np_1darray[np.bool]: ...
209221
@overload
210222
def __ne__(self, other: Series[_OrderableT]) -> Series[bool]: ... # type: ignore[overload-overlap]
211223
@overload

pandas-stubs/_libs/lib.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ class _NoDefault(Enum):
1616
no_default: Final = _NoDefault.no_default
1717
_NoDefaultDoNotUse: TypeAlias = Literal[_NoDefault.no_default] # noqa: PYI047
1818

19-
def infer_dtype(value: object, skipna: bool = ...) -> str: ...
19+
def infer_dtype(value: object, skipna: bool = True) -> str: ...
2020
def is_iterator(obj: object) -> bool: ...
2121
def is_scalar(val: object) -> bool: ...
22-
def is_list_like(obj: object, allow_sets: bool = ...) -> bool: ...
22+
def is_list_like(obj: object, allow_sets: bool = True) -> bool: ...
2323
def is_complex(val: object) -> TypeGuard[complex]: ...
2424
def is_bool(val: object) -> TypeGuard[bool | np.bool_]: ...
2525
def is_integer(val: object) -> TypeGuard[int | np.integer]: ...

0 commit comments

Comments
 (0)