|
1 | 1 | # Note: these stubs are incomplete. The more complex type |
2 | 2 | # signatures are currently omitted. |
3 | 3 | # |
4 | | -# Use SupportsComplex, SupportsFloat and SupportsIndex for return types in this module |
| 4 | +# Use _ComplexLikeOrComplex, _RealLike and _IntegralLike for return types in this module |
5 | 5 | # rather than `numbers.Complex`, `numbers.Real` and `numbers.Integral`, |
6 | 6 | # to avoid an excessive number of `type: ignore`s in subclasses of these ABCs |
7 | 7 | # (since type checkers don't see `complex` as a subtype of `numbers.Complex`, |
|
10 | 10 | import sys |
11 | 11 | from _typeshed import Incomplete |
12 | 12 | from abc import ABCMeta, abstractmethod |
13 | | -from typing import Literal, SupportsFloat, SupportsIndex, overload |
| 13 | +from typing import Literal, Protocol, SupportsAbs, SupportsComplex, overload |
14 | 14 | from typing_extensions import TypeAlias |
15 | 15 |
|
| 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 | + |
16 | 26 | if sys.version_info >= (3, 11): |
17 | | - from typing import SupportsComplex as _SupportsComplex |
| 27 | + _ComplexLikeOrComplex: TypeAlias = _ComplexLike | SupportsComplex |
18 | 28 | else: |
19 | 29 | # builtins.complex didn't have a __complex__ method on older Pythons |
20 | | - import typing |
| 30 | + _ComplexLikeOrComplex: TypeAlias = _ComplexLike | SupportsComplex | complex |
21 | 31 |
|
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: ... |
23 | 43 |
|
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 | +################# |
25 | 56 |
|
26 | 57 | class Number(metaclass=ABCMeta): |
27 | 58 | @abstractmethod |
28 | 59 | def __hash__(self) -> int: ... |
29 | 60 |
|
30 | 61 | # See comment at the top of the file |
31 | 62 | # for why some of these return types are purposefully vague |
32 | | -class Complex(Number): |
| 63 | +class Complex(Number, _ComplexLike): |
33 | 64 | @abstractmethod |
34 | 65 | def __complex__(self) -> complex: ... |
35 | 66 | def __bool__(self) -> bool: ... |
36 | 67 | @property |
37 | 68 | @abstractmethod |
38 | | - def real(self) -> SupportsFloat: ... |
| 69 | + def real(self) -> _RealLike: ... |
39 | 70 | @property |
40 | 71 | @abstractmethod |
41 | | - def imag(self) -> SupportsFloat: ... |
| 72 | + def imag(self) -> _RealLike: ... |
42 | 73 | @abstractmethod |
43 | | - def __add__(self, other) -> _SupportsComplex: ... |
| 74 | + def __add__(self, other) -> _ComplexLikeOrComplex: ... |
44 | 75 | @abstractmethod |
45 | | - def __radd__(self, other) -> _SupportsComplex: ... |
| 76 | + def __radd__(self, other) -> _ComplexLikeOrComplex: ... |
46 | 77 | @abstractmethod |
47 | | - def __neg__(self) -> _SupportsComplex: ... |
| 78 | + def __neg__(self) -> _ComplexLikeOrComplex: ... |
48 | 79 | @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: ... |
52 | 83 | @abstractmethod |
53 | | - def __mul__(self, other) -> _SupportsComplex: ... |
| 84 | + def __mul__(self, other) -> _ComplexLikeOrComplex: ... |
54 | 85 | @abstractmethod |
55 | | - def __rmul__(self, other) -> _SupportsComplex: ... |
| 86 | + def __rmul__(self, other) -> _ComplexLikeOrComplex: ... |
56 | 87 | @abstractmethod |
57 | | - def __truediv__(self, other) -> _SupportsComplex: ... |
| 88 | + def __truediv__(self, other) -> _ComplexLikeOrComplex: ... |
58 | 89 | @abstractmethod |
59 | | - def __rtruediv__(self, other) -> _SupportsComplex: ... |
| 90 | + def __rtruediv__(self, other) -> _ComplexLikeOrComplex: ... |
60 | 91 | @abstractmethod |
61 | | - def __pow__(self, exponent) -> _SupportsComplex: ... |
| 92 | + def __pow__(self, exponent) -> _ComplexLikeOrComplex: ... |
62 | 93 | @abstractmethod |
63 | | - def __rpow__(self, base) -> _SupportsComplex: ... |
| 94 | + def __rpow__(self, base) -> _ComplexLikeOrComplex: ... |
64 | 95 | @abstractmethod |
65 | | - def __abs__(self) -> SupportsFloat: ... |
| 96 | + def __abs__(self) -> _RealLike: ... |
66 | 97 | @abstractmethod |
67 | | - def conjugate(self) -> _SupportsComplex: ... |
| 98 | + def conjugate(self) -> _ComplexLikeOrComplex: ... |
68 | 99 | @abstractmethod |
69 | 100 | def __eq__(self, other: object) -> bool: ... |
70 | 101 |
|
71 | 102 | # See comment at the top of the file |
72 | 103 | # for why some of these return types are purposefully vague |
73 | | -class Real(Complex, SupportsFloat): |
| 104 | +class Real(Complex, _RealLike): |
74 | 105 | @abstractmethod |
75 | 106 | def __float__(self) -> float: ... |
76 | 107 | @abstractmethod |
77 | | - def __trunc__(self) -> SupportsIndex: ... |
| 108 | + def __trunc__(self) -> _IntegralLike: ... |
78 | 109 | @abstractmethod |
79 | | - def __floor__(self) -> SupportsIndex: ... |
| 110 | + def __floor__(self) -> _IntegralLike: ... |
80 | 111 | @abstractmethod |
81 | | - def __ceil__(self) -> SupportsIndex: ... |
| 112 | + def __ceil__(self) -> _IntegralLike: ... |
82 | 113 | @abstractmethod |
83 | 114 | @overload |
84 | | - def __round__(self, ndigits: None = None) -> SupportsIndex: ... |
| 115 | + def __round__(self, ndigits: None = None) -> _IntegralLike: ... |
85 | 116 | @abstractmethod |
86 | 117 | @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]: ... |
90 | 121 | @abstractmethod |
91 | | - def __floordiv__(self, other) -> SupportsFloat: ... |
| 122 | + def __floordiv__(self, other) -> _RealLike: ... |
92 | 123 | @abstractmethod |
93 | | - def __rfloordiv__(self, other) -> SupportsFloat: ... |
| 124 | + def __rfloordiv__(self, other) -> _RealLike: ... |
94 | 125 | @abstractmethod |
95 | | - def __mod__(self, other) -> SupportsFloat: ... |
| 126 | + def __mod__(self, other) -> _RealLike: ... |
96 | 127 | @abstractmethod |
97 | | - def __rmod__(self, other) -> SupportsFloat: ... |
| 128 | + def __rmod__(self, other) -> _RealLike: ... |
98 | 129 | @abstractmethod |
99 | 130 | def __lt__(self, other) -> bool: ... |
100 | 131 | @abstractmethod |
101 | 132 | def __le__(self, other) -> bool: ... |
102 | 133 | def __complex__(self) -> complex: ... |
103 | 134 | @property |
104 | | - def real(self) -> SupportsFloat: ... |
| 135 | + def real(self) -> _RealLike: ... |
105 | 136 | @property |
106 | 137 | def imag(self) -> Literal[0]: ... |
107 | | - def conjugate(self) -> SupportsFloat: ... # type: ignore[override] |
| 138 | + def conjugate(self) -> _RealLike: ... # type: ignore[override] |
108 | 139 |
|
109 | 140 | # See comment at the top of the file |
110 | 141 | # for why some of these return types are purposefully vague |
111 | 142 | class Rational(Real): |
112 | 143 | @property |
113 | 144 | @abstractmethod |
114 | | - def numerator(self) -> SupportsIndex: ... |
| 145 | + def numerator(self) -> _IntegralLike: ... |
115 | 146 | @property |
116 | 147 | @abstractmethod |
117 | | - def denominator(self) -> SupportsIndex: ... |
| 148 | + def denominator(self) -> _IntegralLike: ... |
118 | 149 | def __float__(self) -> float: ... |
119 | 150 |
|
120 | 151 | # See comment at the top of the file |
121 | 152 | # for why some of these return types are purposefully vague |
122 | | -class Integral(Rational): |
| 153 | +class Integral(Rational, _IntegralLike): |
123 | 154 | @abstractmethod |
124 | 155 | def __int__(self) -> int: ... |
125 | 156 | def __index__(self) -> int: ... |
126 | 157 | @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] |
128 | 159 | @abstractmethod |
129 | | - def __lshift__(self, other) -> SupportsIndex: ... |
| 160 | + def __lshift__(self, other) -> _IntegralLike: ... |
130 | 161 | @abstractmethod |
131 | | - def __rlshift__(self, other) -> SupportsIndex: ... |
| 162 | + def __rlshift__(self, other) -> _IntegralLike: ... |
132 | 163 | @abstractmethod |
133 | | - def __rshift__(self, other) -> SupportsIndex: ... |
| 164 | + def __rshift__(self, other) -> _IntegralLike: ... |
134 | 165 | @abstractmethod |
135 | | - def __rrshift__(self, other) -> SupportsIndex: ... |
| 166 | + def __rrshift__(self, other) -> _IntegralLike: ... |
136 | 167 | @abstractmethod |
137 | | - def __and__(self, other) -> SupportsIndex: ... |
| 168 | + def __and__(self, other) -> _IntegralLike: ... |
138 | 169 | @abstractmethod |
139 | | - def __rand__(self, other) -> SupportsIndex: ... |
| 170 | + def __rand__(self, other) -> _IntegralLike: ... |
140 | 171 | @abstractmethod |
141 | | - def __xor__(self, other) -> SupportsIndex: ... |
| 172 | + def __xor__(self, other) -> _IntegralLike: ... |
142 | 173 | @abstractmethod |
143 | | - def __rxor__(self, other) -> SupportsIndex: ... |
| 174 | + def __rxor__(self, other) -> _IntegralLike: ... |
144 | 175 | @abstractmethod |
145 | | - def __or__(self, other) -> SupportsIndex: ... |
| 176 | + def __or__(self, other) -> _IntegralLike: ... |
146 | 177 | @abstractmethod |
147 | | - def __ror__(self, other) -> SupportsIndex: ... |
| 178 | + def __ror__(self, other) -> _IntegralLike: ... |
148 | 179 | @abstractmethod |
149 | | - def __invert__(self) -> SupportsIndex: ... |
| 180 | + def __invert__(self) -> _IntegralLike: ... |
150 | 181 | def __float__(self) -> float: ... |
151 | 182 | @property |
152 | | - def numerator(self) -> SupportsIndex: ... |
| 183 | + def numerator(self) -> _IntegralLike: ... |
153 | 184 | @property |
154 | 185 | def denominator(self) -> Literal[1]: ... |
0 commit comments