-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Mypy doesn't seem to use types from @overload-ed __sub__ #11613
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
Comments
@mathialo looks like this example works for me on from typing import overload
class Arrow:
@overload
def __sub__(self, other: int) -> int:
...
@overload
def __sub__(self, other: str) -> str:
...
def __sub__(self, other: int | str) -> int | str:
...
a: Arrow
reveal_type(a - 1) # N: Revealed type is "builtins.int"
reveal_type(a - 'a') # N: Revealed type is "builtins.str" And this one as well: from typing import overload, Union, Any
from datetime import timedelta, datetime as dt_datetime
class relativedelta:
pass
class Arrow:
@overload
def __sub__(self, other: Union[timedelta, relativedelta]) -> "Arrow":
pass # pragma: no cover
@overload
def __sub__(self, other: Union[dt_datetime, "Arrow"]) -> timedelta:
pass # pragma: no cover
def __sub__(self, other: Any) -> Union[timedelta, "Arrow"]:
pass
a: Arrow
t: timedelta
r: relativedelta
d: dt_datetime
reveal_type(a - t) # N: Revealed type is "ex.Arrow"
reveal_type(a - r) # N: Revealed type is "ex.Arrow"
reveal_type(a - d) # N: Revealed type is "datetime.timedelta"
reveal_type(a - a) # N: Revealed type is "datetime.timedelta" Can you please verify? |
Hello, I'm experiencing this issue as well. I installed the I noticed that if you switch the order of the |
Could you provide a minimal example that reproduces the issue? Possible explanations I can see:
And yes, overload order does matter; mypy generally picks the first matching overload. |
In trying to make a minimal example, I believe I figured out the issue. The issue is that The easy fix is the install In any case, this doesn't appear to be a Mypy issue, so this issue is likely not indicative of a bug. However, it could be a nice Mypy feature to surface this kind of issue through a warning. Perhaps a disable-able warning if any argument to an overload is |
Not having this installed results in confusing errors when running `mypy` on the subtraction of two `Arrow` instances. See python/mypy#11613 for details.
Thanks for figuring that out! I explored a few simpler examples: from typing import Any, overload, Union
class X:
@overload
def __sub__(self, x: Any) -> int:
pass
@overload
def __sub__(self, x: int) -> str:
pass
def __sub__(self, x: object) -> Any:
raise NotImplementedError produces But now we change the first overload to from typing import Any, overload, Union
class X:
@overload
def __sub__(self, x: Union[str, Any]) -> int:
pass
@overload
def __sub__(self, x: int) -> str:
pass
def __sub__(self, x: object) -> Any:
raise NotImplementedError And we get Perhaps we should open a new issue focused on improving this behavior. |
Not having this installed results in confusing errors when running `mypy` on the subtraction of two `Arrow` instances. See python/mypy#11613 for details.
FYI, as of #17392, the second minimal example no longer shows an error. (due the |
Bug Report
The
__sub__
method on theArrow
class from thearrow
package has several@overload
s:In particular, one
Arrow
object minus anotherArrow
object will always yield atimedelta
. However, it seems mypy does not see this, and mistakes the type forArrow
.To Reproduce
I discovered the issue when finding the time diff between two arrow timestamps:
Which, when run with mypy yields:
Setting the type explicitly reviles that mypy thinks the type is
Arrow
, and nottimedelta
:Running mypy:
Expected Behavior
The second
@overload
onArrow
's__sub__
method specifies that the diff of twoArrow
objects is atimedelta
. There should be no type error assigning that to atimedelta
variable.Actual Behavior
Mypy mistakenly thinks the diff is
Arrow
, which creates a false positive.Your Environment
mypy.ini
(and other config files): NoneThe text was updated successfully, but these errors were encountered: