Skip to content

Commit c3ebc7e

Browse files
authored
More improvements to pow stubs (#7737)
1 parent 5df8de7 commit c3ebc7e

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

stdlib/builtins.pyi

+17-2
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,9 @@ class int:
254254
@overload
255255
def __pow__(self, __x: int, __modulo: int) -> int: ...
256256
@overload
257-
def __pow__(self, __x: Literal[0], __modulo: None = ...) -> Literal[1]: ...
257+
def __pow__(self, __x: Literal[0]) -> Literal[1]: ...
258+
@overload
259+
def __pow__(self, __x: Literal[0], __modulo: None) -> Literal[1]: ...
258260
@overload
259261
def __pow__(self, __x: _PositiveInteger, __modulo: None = ...) -> int: ...
260262
@overload
@@ -327,7 +329,12 @@ class float:
327329
def __rtruediv__(self, __x: float) -> float: ...
328330
def __rmod__(self, __x: float) -> float: ...
329331
def __rdivmod__(self, __x: float) -> tuple[float, float]: ...
330-
# Returns complex if the argument is negative.
332+
@overload
333+
def __rpow__(self, __x: _PositiveInteger, __modulo: None = ...) -> float: ...
334+
@overload
335+
def __rpow__(self, __x: _NegativeInteger, __mod: None = ...) -> complex: ...
336+
# Returning `complex` for the general case gives too many false-positive errors.
337+
@overload
331338
def __rpow__(self, __x: float, __mod: None = ...) -> Any: ...
332339
def __getnewargs__(self) -> tuple[float]: ...
333340
def __trunc__(self) -> int: ...
@@ -1422,6 +1429,10 @@ if sys.version_info >= (3, 8):
14221429
@overload
14231430
def pow(base: int, exp: int, mod: None = ...) -> Any: ...
14241431
@overload
1432+
def pow(base: _PositiveInteger, exp: float, mod: None = ...) -> float: ...
1433+
@overload
1434+
def pow(base: _NegativeInteger, exp: float, mod: None = ...) -> complex: ...
1435+
@overload
14251436
def pow(base: float, exp: int, mod: None = ...) -> float: ...
14261437
# float base & float exp could return float or complex
14271438
# return type must be Any (same as complex base, complex exp),
@@ -1455,6 +1466,10 @@ else:
14551466
@overload
14561467
def pow(__base: int, __exp: int, __mod: None = ...) -> Any: ...
14571468
@overload
1469+
def pow(__base: _PositiveInteger, __exp: float, __mod: None = ...) -> float: ...
1470+
@overload
1471+
def pow(__base: _NegativeInteger, __exp: float, __mod: None = ...) -> complex: ...
1472+
@overload
14581473
def pow(__base: float, __exp: int, __mod: None = ...) -> float: ...
14591474
@overload
14601475
def pow(__base: float, __exp: complex | _SupportsSomeKindOfPow, __mod: None = ...) -> Any: ...

test_cases/stdlib/builtins/test_pow.py

+36-3
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,55 @@
33
from typing import Any, NoReturn
44
from typing_extensions import Literal, assert_type
55

6-
assert_type(pow(1, 0), Literal[1]) # See #7163
7-
assert_type(pow(1, 0, None), Literal[1]) # See #7163
6+
# See #7163
7+
assert_type(pow(1, 0), Literal[1])
8+
assert_type(1**0, Literal[1])
9+
assert_type(pow(1, 0, None), Literal[1])
10+
811
assert_type(pow(2, 4, 0), NoReturn)
12+
913
assert_type(pow(2, 4), int)
14+
assert_type(2**4, int)
1015
assert_type(pow(4, 6, None), int)
16+
1117
assert_type(pow(5, -7), float)
18+
assert_type(5**-7, float)
19+
1220
assert_type(pow(2, 4, 5), int) # pow(<smallint>, <smallint>, <smallint>)
1321
assert_type(pow(2, 35, 3), int) # pow(<smallint>, <bigint>, <smallint>)
22+
23+
assert_type(pow(2, 8.5), float)
24+
assert_type(2**8.6, float)
25+
assert_type(pow(2, 8.6, None), float)
26+
27+
# TODO: Why does this pass pyright but not mypy??
28+
# assert_type((-2) ** 0.5, complex)
29+
30+
assert_type(pow((-5), 8.42, None), complex)
31+
1432
assert_type(pow(4.6, 8), float)
33+
assert_type(4.6**8, float)
1534
assert_type(pow(5.1, 4, None), float)
35+
1636
assert_type(pow(complex(6), 6.2), complex)
37+
assert_type(complex(6) ** 6.2, complex)
1738
assert_type(pow(complex(9), 7.3, None), complex)
39+
1840
assert_type(pow(Fraction(), 4, None), Fraction)
41+
assert_type(Fraction() ** 4, Fraction)
42+
1943
assert_type(pow(Fraction(3, 7), complex(1, 8)), complex)
44+
assert_type(Fraction(3, 7) ** complex(1, 8), complex)
45+
2046
assert_type(pow(complex(4, -8), Fraction(2, 3)), complex)
47+
assert_type(complex(4, -8) ** Fraction(2, 3), complex)
48+
2149
assert_type(pow(Decimal("1.0"), Decimal("1.6")), Decimal)
50+
assert_type(Decimal("1.0") ** Decimal("1.6"), Decimal)
51+
2252
assert_type(pow(Decimal("1.0"), Decimal("1.0"), Decimal("1.0")), Decimal)
2353
assert_type(pow(Decimal("4.6"), 7, None), Decimal)
54+
assert_type(Decimal("4.6") ** 7, Decimal)
2455

2556
# These would ideally be more precise, but `Any` is acceptable
2657
# They have to be `Any` due to the fact that type-checkers can't distinguish between positive and negative numbers for the second argument to `pow()`
@@ -29,6 +60,8 @@
2960
assert_type(pow(4, 65), Any)
3061
assert_type(pow(2, -45), Any)
3162
assert_type(pow(3, 57, None), Any)
63+
assert_type(pow(67, 0.98, None), Any)
64+
assert_type(87**7.32, Any)
3265
# pow(<pos-float>, <pos-or-neg-float>) -> float
3366
# pow(<neg-float>, <pos-or-neg-float>) -> complex
3467
assert_type(pow(4.7, 7.4), Any)
@@ -37,4 +70,4 @@
3770
assert_type(pow(8.2, -9.8), Any)
3871
assert_type(pow(4.7, 9.2, None), Any)
3972
# See #7046 -- float for a positive 1st arg, complex otherwise
40-
assert_type((-2) ** 0.5, Any)
73+
assert_type((-95) ** 8.42, Any)

0 commit comments

Comments
 (0)