@@ -36,67 +36,70 @@ This also allows type checking for operations on series that contain date/time d
36
36
the following example that creates two series of datetimes with corresponding arithmetic.
37
37
38
38
``` python
39
+ import pandas as pd
40
+ from typing import reveal_type
41
+
39
42
s1 = pd.Series(pd.to_datetime([" 2022-05-01" , " 2022-06-01" ]))
40
43
reveal_type(s1)
41
44
s2 = pd.Series(pd.to_datetime([" 2022-05-15" , " 2022-06-15" ]))
42
45
reveal_type(s2)
43
46
td = s1 - s2
44
47
reveal_type(td)
45
48
ssum = s1 + s2
46
- reveal_type(ssum)
47
49
```
48
50
49
- The above code (without the ` reveal_type() ` statements) will raise an ` Exception ` 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
50
52
inappropriate to add two series containing ` Timestamp ` values. The types will be
51
- revealed as follows:
53
+ revealed by ` mypy ` as follows:
52
54
53
55
``` text
54
- ttest.py:4 : note: Revealed type is "pandas.core.series.TimestampSeries "
55
- ttest.py:6 : note: Revealed type is "pandas.core.series.TimestampSeries "
56
- ttest.py:8 : note: Revealed type is "pandas.core.series.TimedeltaSeries"
57
- ttest.py:10: note: Revealed type is "builtins.Exception"
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.TimedeltaSeries"
59
+ ttest.py:10: error: Unsupported operand types for + ("Series[Timestamp]" and "Series[Timestamp]") [operator]
58
60
```
59
61
60
- The type ` TimestampSeries ` is the result of creating a series from ` pd.to_datetime() ` , while
61
- the type ` TimedeltaSeries ` is the result of subtracting two ` TimestampSeries ` as well as
62
+ The type ` Series[Timestamp] ` is the result of creating a series from ` pd.to_datetime() ` , while
63
+ the type ` TimedeltaSeries ` is the result of subtracting two ` Series[Timestamp] ` as well as
62
64
the result of ` pd.to_timedelta() ` .
63
65
64
- ### Generic Series have restricted arithmetic
66
+ ### Progressive arithmetic typing for generic Series
65
67
66
68
Consider the following Series from a DataFrame:
67
69
68
70
``` python
69
71
import pandas as pd
70
72
from typing_extensions import reveal_type
71
- from typing import TYPE_CHECKING , cast
72
-
73
- if TYPE_CHECKING :
74
- from pandas.core.series import TimestampSeries # noqa: F401
75
73
76
74
77
- frame = pd.DataFrame({" timestamp" : [pd.Timestamp(2025 , 8 , 26 )], " tag" : [" one" ], " value" : [1.0 ]})
75
+ frame = pd.DataFrame({" timestamp" : [pd.Timestamp(2025 , 9 , 15 )], " tag" : [" one" ], " value" : [1.0 ]})
78
76
values = frame[" value" ]
79
77
reveal_type(values) # type checker: Series[Any], runtime: Series
80
78
new_values = values + 2
81
79
82
80
timestamps = frame[" timestamp" ]
83
- reveal_type(timestamps) # type checker: Series[Any], runtime: Series
84
- reveal_type(timestamps - pd.Timestamp(2025 , 7 , 12 )) # type checker: Unknown and error, runtime: Series
85
- reveal_type(cast(" TimestampSeries" , timestamps) - pd.Timestamp(2025 , 7 , 12 )) # type checker: TimedeltaSeries, runtime: Series
81
+ reveal_type(timestamps - pd.Timestamp(2025 , 7 , 12 )) # type checker: TimedeltaSeries, runtime: Series
86
82
87
83
tags = frame[" tag" ]
88
- reveal_type(" suffix" + tags) # type checker: Never , runtime: Series
84
+ reveal_type(" suffix" + tags) # type checker: Series[str] , runtime: Series
89
85
```
90
86
91
- Since they are taken from a DataFrame, all three of them, ` values ` , ` timestamps `
87
+ Since these Series are taken from a DataFrame, all three of them, ` values ` , ` timestamps `
92
88
and ` tags ` , are recognized by type checkers as ` Series[Any] ` . The code snippet
93
- runs fine at runtime. In the stub for type checking, however, we restrict
94
- generic Series to perform arithmetic operations only with numeric types, and
95
- give ` Series[Any] ` for the results. For ` Timedelta ` , ` Timestamp ` , ` str ` , etc.,
96
- arithmetic is restricted to ` Series[Any] ` and the result is either undefined,
97
- showing ` Unknown ` and errors, or ` Never ` . Users are encouraged to cast such
98
- generic Series to ones with concrete types, so that type checkers can provide
99
- meaningful results.
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.
100
103
101
104
### Interval is Generic
102
105
0 commit comments