Skip to content

Commit 687709c

Browse files
committed
Address review
1 parent feb3365 commit 687709c

File tree

1 file changed

+84
-53
lines changed

1 file changed

+84
-53
lines changed

stdlib/numbers.pyi

Lines changed: 84 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Note: these stubs are incomplete. The more complex type
22
# signatures are currently omitted.
33
#
4-
# Use SupportsComplex, SupportsFloat and SupportsIndex for return types in this module
4+
# Use _ComplexLikeOrComplex, _RealLike and _IntegralLike for return types in this module
55
# rather than `numbers.Complex`, `numbers.Real` and `numbers.Integral`,
66
# to avoid an excessive number of `type: ignore`s in subclasses of these ABCs
77
# (since type checkers don't see `complex` as a subtype of `numbers.Complex`,
@@ -10,145 +10,176 @@
1010
import sys
1111
from _typeshed import Incomplete
1212
from abc import ABCMeta, abstractmethod
13-
from typing import Literal, SupportsFloat, SupportsIndex, overload
13+
from typing import Literal, Protocol, SupportsAbs, SupportsComplex, overload
1414
from typing_extensions import TypeAlias
1515

16+
__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
17+
18+
############################
19+
# Protocols for return types
20+
############################
21+
22+
# Structural-typing approximation
23+
# of the `Complex` ABC, which is not (and cannot be) a protocol
24+
_ComplexLike: TypeAlias = SupportsAbs[_RealLike]
25+
1626
if sys.version_info >= (3, 11):
17-
from typing import SupportsComplex as _SupportsComplex
27+
_ComplexLikeOrComplex: TypeAlias = _ComplexLike | SupportsComplex
1828
else:
1929
# builtins.complex didn't have a __complex__ method on older Pythons
20-
import typing
30+
_ComplexLikeOrComplex: TypeAlias = _ComplexLike | SupportsComplex | complex
2131

22-
_SupportsComplex: TypeAlias = typing.SupportsComplex | complex
32+
# Structural-typing approximation
33+
# of the `Real` ABC, which is not (and cannot be) a protocol
34+
class _RealLike(Protocol):
35+
@abstractmethod
36+
def __float__(self) -> float: ...
37+
@abstractmethod
38+
def __trunc__(self) -> _IntegralLike: ...
39+
@abstractmethod
40+
def __floor__(self) -> _IntegralLike: ...
41+
@abstractmethod
42+
def __ceil__(self) -> _IntegralLike: ...
2343

24-
__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
44+
# Structural-typing approximation
45+
# of the `Integral` ABC, which is not (and cannot be) a protocol
46+
class _IntegralLike(_RealLike, Protocol):
47+
@abstractmethod
48+
def __invert__(self) -> _IntegralLike: ...
49+
@abstractmethod
50+
def __int__(self) -> int: ...
51+
def __index__(self) -> int: ...
52+
53+
#################
54+
# Module "proper"
55+
#################
2556

2657
class Number(metaclass=ABCMeta):
2758
@abstractmethod
2859
def __hash__(self) -> int: ...
2960

3061
# See comment at the top of the file
3162
# for why some of these return types are purposefully vague
32-
class Complex(Number):
63+
class Complex(Number, _ComplexLike):
3364
@abstractmethod
3465
def __complex__(self) -> complex: ...
3566
def __bool__(self) -> bool: ...
3667
@property
3768
@abstractmethod
38-
def real(self) -> SupportsFloat: ...
69+
def real(self) -> _RealLike: ...
3970
@property
4071
@abstractmethod
41-
def imag(self) -> SupportsFloat: ...
72+
def imag(self) -> _RealLike: ...
4273
@abstractmethod
43-
def __add__(self, other) -> _SupportsComplex: ...
74+
def __add__(self, other) -> _ComplexLikeOrComplex: ...
4475
@abstractmethod
45-
def __radd__(self, other) -> _SupportsComplex: ...
76+
def __radd__(self, other) -> _ComplexLikeOrComplex: ...
4677
@abstractmethod
47-
def __neg__(self) -> _SupportsComplex: ...
78+
def __neg__(self) -> _ComplexLikeOrComplex: ...
4879
@abstractmethod
49-
def __pos__(self) -> _SupportsComplex: ...
50-
def __sub__(self, other) -> _SupportsComplex: ...
51-
def __rsub__(self, other) -> _SupportsComplex: ...
80+
def __pos__(self) -> _ComplexLikeOrComplex: ...
81+
def __sub__(self, other) -> _ComplexLikeOrComplex: ...
82+
def __rsub__(self, other) -> _ComplexLikeOrComplex: ...
5283
@abstractmethod
53-
def __mul__(self, other) -> _SupportsComplex: ...
84+
def __mul__(self, other) -> _ComplexLikeOrComplex: ...
5485
@abstractmethod
55-
def __rmul__(self, other) -> _SupportsComplex: ...
86+
def __rmul__(self, other) -> _ComplexLikeOrComplex: ...
5687
@abstractmethod
57-
def __truediv__(self, other) -> _SupportsComplex: ...
88+
def __truediv__(self, other) -> _ComplexLikeOrComplex: ...
5889
@abstractmethod
59-
def __rtruediv__(self, other) -> _SupportsComplex: ...
90+
def __rtruediv__(self, other) -> _ComplexLikeOrComplex: ...
6091
@abstractmethod
61-
def __pow__(self, exponent) -> _SupportsComplex: ...
92+
def __pow__(self, exponent) -> _ComplexLikeOrComplex: ...
6293
@abstractmethod
63-
def __rpow__(self, base) -> _SupportsComplex: ...
94+
def __rpow__(self, base) -> _ComplexLikeOrComplex: ...
6495
@abstractmethod
65-
def __abs__(self) -> SupportsFloat: ...
96+
def __abs__(self) -> _RealLike: ...
6697
@abstractmethod
67-
def conjugate(self) -> _SupportsComplex: ...
98+
def conjugate(self) -> _ComplexLikeOrComplex: ...
6899
@abstractmethod
69100
def __eq__(self, other: object) -> bool: ...
70101

71102
# See comment at the top of the file
72103
# for why some of these return types are purposefully vague
73-
class Real(Complex, SupportsFloat):
104+
class Real(Complex, _RealLike):
74105
@abstractmethod
75106
def __float__(self) -> float: ...
76107
@abstractmethod
77-
def __trunc__(self) -> SupportsIndex: ...
108+
def __trunc__(self) -> _IntegralLike: ...
78109
@abstractmethod
79-
def __floor__(self) -> SupportsIndex: ...
110+
def __floor__(self) -> _IntegralLike: ...
80111
@abstractmethod
81-
def __ceil__(self) -> SupportsIndex: ...
112+
def __ceil__(self) -> _IntegralLike: ...
82113
@abstractmethod
83114
@overload
84-
def __round__(self, ndigits: None = None) -> SupportsIndex: ...
115+
def __round__(self, ndigits: None = None) -> _IntegralLike: ...
85116
@abstractmethod
86117
@overload
87-
def __round__(self, ndigits: int) -> SupportsFloat: ...
88-
def __divmod__(self, other) -> tuple[SupportsFloat, SupportsFloat]: ...
89-
def __rdivmod__(self, other) -> tuple[SupportsFloat, SupportsFloat]: ...
118+
def __round__(self, ndigits: int) -> _RealLike: ...
119+
def __divmod__(self, other) -> tuple[_RealLike, _RealLike]: ...
120+
def __rdivmod__(self, other) -> tuple[_RealLike, _RealLike]: ...
90121
@abstractmethod
91-
def __floordiv__(self, other) -> SupportsFloat: ...
122+
def __floordiv__(self, other) -> _RealLike: ...
92123
@abstractmethod
93-
def __rfloordiv__(self, other) -> SupportsFloat: ...
124+
def __rfloordiv__(self, other) -> _RealLike: ...
94125
@abstractmethod
95-
def __mod__(self, other) -> SupportsFloat: ...
126+
def __mod__(self, other) -> _RealLike: ...
96127
@abstractmethod
97-
def __rmod__(self, other) -> SupportsFloat: ...
128+
def __rmod__(self, other) -> _RealLike: ...
98129
@abstractmethod
99130
def __lt__(self, other) -> bool: ...
100131
@abstractmethod
101132
def __le__(self, other) -> bool: ...
102133
def __complex__(self) -> complex: ...
103134
@property
104-
def real(self) -> SupportsFloat: ...
135+
def real(self) -> _RealLike: ...
105136
@property
106137
def imag(self) -> Literal[0]: ...
107-
def conjugate(self) -> SupportsFloat: ... # type: ignore[override]
138+
def conjugate(self) -> _RealLike: ... # type: ignore[override]
108139

109140
# See comment at the top of the file
110141
# for why some of these return types are purposefully vague
111142
class Rational(Real):
112143
@property
113144
@abstractmethod
114-
def numerator(self) -> SupportsIndex: ...
145+
def numerator(self) -> _IntegralLike: ...
115146
@property
116147
@abstractmethod
117-
def denominator(self) -> SupportsIndex: ...
148+
def denominator(self) -> _IntegralLike: ...
118149
def __float__(self) -> float: ...
119150

120151
# See comment at the top of the file
121152
# for why some of these return types are purposefully vague
122-
class Integral(Rational):
153+
class Integral(Rational, _IntegralLike):
123154
@abstractmethod
124155
def __int__(self) -> int: ...
125156
def __index__(self) -> int: ...
126157
@abstractmethod
127-
def __pow__(self, exponent, modulus: Incomplete | None = None) -> SupportsIndex: ... # type: ignore[override]
158+
def __pow__(self, exponent, modulus: Incomplete | None = None) -> _IntegralLike: ... # type: ignore[override]
128159
@abstractmethod
129-
def __lshift__(self, other) -> SupportsIndex: ...
160+
def __lshift__(self, other) -> _IntegralLike: ...
130161
@abstractmethod
131-
def __rlshift__(self, other) -> SupportsIndex: ...
162+
def __rlshift__(self, other) -> _IntegralLike: ...
132163
@abstractmethod
133-
def __rshift__(self, other) -> SupportsIndex: ...
164+
def __rshift__(self, other) -> _IntegralLike: ...
134165
@abstractmethod
135-
def __rrshift__(self, other) -> SupportsIndex: ...
166+
def __rrshift__(self, other) -> _IntegralLike: ...
136167
@abstractmethod
137-
def __and__(self, other) -> SupportsIndex: ...
168+
def __and__(self, other) -> _IntegralLike: ...
138169
@abstractmethod
139-
def __rand__(self, other) -> SupportsIndex: ...
170+
def __rand__(self, other) -> _IntegralLike: ...
140171
@abstractmethod
141-
def __xor__(self, other) -> SupportsIndex: ...
172+
def __xor__(self, other) -> _IntegralLike: ...
142173
@abstractmethod
143-
def __rxor__(self, other) -> SupportsIndex: ...
174+
def __rxor__(self, other) -> _IntegralLike: ...
144175
@abstractmethod
145-
def __or__(self, other) -> SupportsIndex: ...
176+
def __or__(self, other) -> _IntegralLike: ...
146177
@abstractmethod
147-
def __ror__(self, other) -> SupportsIndex: ...
178+
def __ror__(self, other) -> _IntegralLike: ...
148179
@abstractmethod
149-
def __invert__(self) -> SupportsIndex: ...
180+
def __invert__(self) -> _IntegralLike: ...
150181
def __float__(self) -> float: ...
151182
@property
152-
def numerator(self) -> SupportsIndex: ...
183+
def numerator(self) -> _IntegralLike: ...
153184
@property
154185
def denominator(self) -> Literal[1]: ...

0 commit comments

Comments
 (0)