Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve stubs for __pow__ #6287

Merged
merged 9 commits into from
Nov 12, 2021
Merged

Conversation

AlexWaygood
Copy link
Member

No description provided.

stdlib/builtins.pyi Outdated Show resolved Hide resolved
@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

freqtrade (https://github.com/freqtrade/freqtrade.git)
+ freqtrade/templates/sample_hyperopt_loss.py:47: error: Argument 1 to "exp" has incompatible type "complex"; expected "Union[SupportsFloat, SupportsIndex]"
+ freqtrade/optimize/hyperopt_loss_short_trade_dur.py:48: error: Argument 1 to "exp" has incompatible type "complex"; expected "Union[SupportsFloat, SupportsIndex]"

pandas (https://github.com/pandas-dev/pandas.git)
+ pandas/io/stata.py:2990: error: Incompatible return value type (got "float", expected "int")  [return-value]

vision (https://github.com/pytorch/vision.git)
+ torchvision/models/detection/backbone_utils.py:133: error: Argument 3 to "BackboneWithFPN" has incompatible type "List[float]"; expected "List[int]"  [arg-type]

aiortc (https://github.com/aiortc/aiortc)
+ src/aiortc/rate.py:158: error: Incompatible types in assignment (expression has type "Union[float, complex]", variable has type "float")
+ src/aiortc/rate.py:440: error: Incompatible types in assignment (expression has type "complex", variable has type "float")
+ src/aiortc/rate.py:442: error: Incompatible types in assignment (expression has type "complex", variable has type "float")

prefect (https://github.com/PrefectHQ/prefect.git)
+ src/prefect/utilities/datetimes.py:51: error: Incompatible return value type (got "Union[timedelta, float]", expected "timedelta")
+ src/prefect/utilities/datetimes.py:51: error: Unsupported operand types for * ("None" and "float")
+ src/prefect/utilities/datetimes.py:51: note: Left operand is of type "Optional[timedelta]"

kornia (https://github.com/kornia/kornia.git)
+ kornia/geometry/transform/pyramid.py:203: error: Argument 1 to "sqrt" has incompatible type "complex"; expected "Union[SupportsFloat, SupportsIndex]"  [arg-type]

paasta (https://github.com/yelp/paasta.git)
+ paasta_tools/utils.py:3553: error: Incompatible return value type (got "float", expected "int")

rich (https://github.com/willmcgugan/rich.git)
+ rich/filesize.py:50: error: Incompatible return value type (got "Tuple[float, str]", expected "Tuple[int, str]")

sympy (https://github.com/sympy/sympy.git)
+ sympy/core/evalf.py:300: error: Incompatible types in assignment (expression has type "float", variable has type "int")
+ sympy/core/evalf.py:623: error: Incompatible types in assignment (expression has type "float", variable has type "int")
+ sympy/core/evalf.py:1196: error: Incompatible types in assignment (expression has type "float", variable has type "int")
+ sympy/core/evalf.py:1354: error: Incompatible types in assignment (expression has type "float", variable has type "Symbol")

@AlexWaygood
Copy link
Member Author

AlexWaygood commented Nov 12, 2021

Diff from mypy_primer, showing the effect of this PR on open source code

Hmm, it's annoying that the type system doesn't have a way of specifying a positive integer. The new rich error, for example, doesn't really need to be there. Will can be confident that base and i will both be >0 in line 47, and so can be confident that the type of base ** i will be int. But there's no way of telling mypy that, since mypy can't distinguish between positive and negative integers.

@AlexWaygood AlexWaygood marked this pull request as draft November 12, 2021 19:33
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

stdlib/builtins.pyi Outdated Show resolved Hide resolved
@@ -324,12 +329,12 @@ class complex:
def __add__(self, __x: complex) -> complex: ...
def __sub__(self, __x: complex) -> complex: ...
def __mul__(self, __x: complex) -> complex: ...
def __pow__(self, __x: complex, mod: None = ...) -> complex: ...
def __pow__(self, __x: complex | int | float, mod: None = ...) -> complex: ...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

complex | float is enough. Type checkers imagine that int is a subclass of float, even though it actually isn't.

A protocol involving SupportsIndex might be more accurate, if these behave similarly to math functions (#6211 and #6216).

@github-actions

This comment has been minimized.

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

stdlib/builtins.pyi Outdated Show resolved Hide resolved
stdlib/builtins.pyi Outdated Show resolved Hide resolved
@github-actions

This comment has been minimized.

@AlexWaygood AlexWaygood marked this pull request as ready for review November 12, 2021 20:14
@@ -1284,7 +1284,7 @@ if sys.version_info >= (3, 8):
@overload
def pow(base: float, exp: int, mod: None = ...) -> float: ...
@overload
def pow(base: float, exp: float, mod: None = ...) -> Any: ... # return type could be float or complex
def pow(base: float, exp: float, mod: None = ...) -> Any: ... # return type could be float or complex depending on x
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

depending on exp

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also depends on base. If the base is positive, then any power will also be positive. Complex numbers need a negative base and a negative power.

Maybe the whole "depending on" part should be deleted? It obviously depends on the arguments in some way, which is really all that needs to be said.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth spelling out the conditions... pow is like catnip for typeshed contributors, because everyone always starts off thinking only about positive integers :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, sorry about that @hauntsaninja

@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@hauntsaninja hauntsaninja merged commit 3324e22 into python:master Nov 12, 2021
@hauntsaninja
Copy link
Collaborator

Hooray!

@@ -221,9 +221,13 @@ class int:
def __rmod__(self, __x: int) -> int: ...
def __rdivmod__(self, __x: int) -> tuple[int, int]: ...
@overload
def __pow__(self, __x: Literal[2], __modulo: int | None = ...) -> int: ...
def __pow__(self, __x: int, __modulo: Literal[0]) -> NoReturn: ...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't result of x ** 0 == 1?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pow(1, 1, 0):

In [4]: pow(1, 1, 0)

Traceback (most recent call last):
  File "/main_instance_shell/jelle/venv/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 3343, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-4-23a0b67588cd>", line 1, in <module>
    pow(1, 1, 0)
ValueError: pow() 3rd argument cannot be 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants